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