COMP1531
From Ideation to Income:
Building real software
Presented by The Growth Hunting Company

In this lecture
A lot of software engineering is applying the SDLC on existing systems. "All software development is maintenance".
Today I'm going to talk about building a system from scratch using the tools that you've learned in COMP1531.
This lecture is in some ways a revamp of a previous lecture "Building an MVP".
Don't take it too literally

More or less the same

The Growth Hunting Company
https://www.growthhunting.com.au/
We believe in the transformative power of education to unlock human potential and drive positive change. Our mission is to empower individuals, organisations, and communities through continuous learning and development.

My Pressure Story


My Pressure Story
Where we're at in April 2025.
Rewind, back to August 2023
[DISCOVER] Ideation
It all starts with an idea.

From paper to PDF: Digitising my pressure story
[DISCOVER] Requirements engineering
Take the time to understand what problem it is you're trying to solve and why it's worth solving.

Dogfood before you build

Drafting a UI design with Figma
[PLAN] Create an initial design to scope out requirements
Sometimes the best way to figure out what to build is to go and build it, and get it wrong.


Getting the team together: Startup land
December 2023
[TEAM] Project Kickoff
Teams' operation is a function of their context. Figure out what works for yours.

Architectural & API design
27 Dec 2023
[PLAN] Decide on your system design




Initial commit
27 Dec 2023
[BUILD] Let's get coding!

Building real software in JavaScript
Express HTTP Server
app.post(
'/mps',
validateAndAuthenticateBuckets,
async (req: PressureStoryRequest, res: any) => {
try {
// Call update function
await updatePressureStoryBuckets(req.body)
res.send('Success')
} catch (err: any) {
console.log('❌ Error updating pressure story buckets:', err)
res.status(500).send('Error saving data')
}
}
)
Building real software in JavaScript
Package management with NPM
{
"name": "gzgs-api",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"start:local": "npm run build:ci && npm run start",
"start": "node dist/api/src/app.js",
"dev": "nodemon --watch src --exec ts-node src/api/src/app.ts",
"build": "./build.sh",
"build:ci": "tsc",
"test": "jest",
"lint": "./node_modules/.bin/eslint src/**/*.ts*",
"lint:fix": "npx prettier -w . && ./node_modules/.bin/eslint src/**/*.ts* --fix"
},
"author": "sneaky-patriki",
"license": "ISC",
"dependencies": {
"@react-email/render": "^0.0.15",
"@types/node": "^20.10.5",
"antd": "^5.17.4",
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"dotenv": "^16.4.7",
"emailjs-com": "^3.2.0",
...
}
}
Building real software in JavaScript
Dynamic verification with Jest

Building real software in JavaScript
Static verification with TypeScript

Building real software in JavaScript
Linting with ESLint & Prettier

At some point, we'll fix these warnings, but it's not the most important thing... right now
Building real software in JavaScript
Persistence
export const CauseBucket = sequelize.define('CauseBucket', {
orgId: DataTypes.STRING,
cause: DataTypes.STRING
})
export const AppearsBucket = sequelize.define('AppearsBucket', {
orgId: DataTypes.STRING,
appears: DataTypes.STRING
})
export const ReasonBucket = sequelize.define('ReasonBucket', {
orgId: DataTypes.STRING,
reason: DataTypes.STRING
})


Sequelize: A NodeJS library that allows you to interact with a database engine
PostgreSQL: A database engine that allows you to create relational models and store data persistently
Building real software in JavaScript
Authentication & Authorisation
export const authenticateMPS = async (
userPassword: string,
salt: string
): Promise<{ sessionToken: string } | null> => {
const adminPassword = process.env.MPS_ADMIN_PASSWORD
if (!adminPassword) {
throw new Error('Admin password is not set')
}
const hashedActualPassword = await bcrypt.hash(adminPassword, salt)
if (userPassword !== hashedActualPassword) {
return null
}
const adminToken = jwt.sign(
{ orgId: null, isAdmin: true, timestamp: Date.now() },
JWT_SECRET,
{ expiresIn: '48h' }
)
await MPSSession.create({
orgId: 'admin',
sessionToken: adminToken
})
return { sessionToken: adminToken }
}
Building real software in JavaScript
LLM Integration
import OpenAI from 'openai'
const modelId = 'gpt-3.5-turbo'
export const aiWritePressureStory = async (
pressureStory: string
): Promise<string | null> => {
const result = await openai.chat.completions.create({
model: modelId,
messages: [
{
role: 'user',
content: pressureStory
}
]
})
return result.choices[0].message.content
}
const getPrompt = (topic) => {
topic = topic.toLowerCase().includes("effect")
? topic.toLowerCase().includes("on me")
? "EffectMe"
: "EffectOthers"
: topic;
const prompt = `Write a concise paragraph in first person.
Begin with ${promptMessage[topic]} and include ${prev.join(", ")}.
Do not give suggestions only expand on the prompt.
Do not duplicate the content.
Use natural sentence casing.
Make the paragraph flow naturally.`;
if (topic === "Strategy") {
return `${prompt}. Use "I need" language.`;
} else if (topic === "Support") {
return `${prompt}. Write from the perspective of the support I need from those around me is...`;
} else {
return `${prompt}. Don't talk about how I am working through/navigating this pressure.`;
}
};
Development lifecycle
Using GitHub for branches, commits and PR reviews

Development lifecycle
Continuous Integration via GitHub Actions

Deployment
Heroku for backend, Vercel for frontend.


The domain is managed separately, but Vercel can link to a domain.
[DEPLOY] Deploy a simple version of your software early and make it part of the development lifecycle.
Project lifecycle
Jira for task management, Confluence for documentation management, Atlas for project tracking



[TEAM] Establish the source of truth which your team updates to keep itself on track.
Demonstrate a Minimum Viable Product
August 2024

... and iterate
December 2024

Crunch time
[CONTINUOUS FEEDBACK] Validate your software with the people who are using it

January 2025
Into the wild
[OPERATE & OBSERVE] Good software is unexciting when you release it :)
February 2025 - My Pressure Story used in a live Growth Hunting Session

Adding value to a business
[DISCOVER] We build software to create value. Always think about what real life process your software is helping oil.

Hunting growth
[TEAM] As you develop operational maturity, you will be able to scale the development of your software

Ideation to Implementation, sure - but income?
Yesterday

Lessons learned along the way
#1: Focus on the most important thing, one at a time.
#2: Learn to think like your users.
#3: Don't pigeon hole yourself as an engineer.
COMP1531 25T1: From Ideation to Income - The SDLC IRL
By npatrikeos
COMP1531 25T1: From Ideation to Income - The SDLC IRL
- 209