Hamzah.
Work Feedback About Training ↗
Get in touch

This case study is private.

Return to the homepage and unlock with a password to view this work.

← Back to work
← Selected work / 02

Replacing four SaaS tools with one platform that runs the agency end-to-end

Operations platform · Development agency

Role
Full-stack engineer · solo build
Industry
Operations platform · Development agency
Status
Active · In production
Stack
Next.js · TypeScript · Supabase · PostgreSQL · Stripe · React Query

One internal platform that runs a development agency end-to-end. A signed deal spins up a client and project, developers log time, invoices generate and settle through Stripe — no exports, no spreadsheets, no manual reconciliation. Built solo. Replaced four standing SaaS subscriptions and the master spreadsheet between them.

  1. 01

    The patchwork problem

    Four SaaS tools, monthly exports, one fragile spreadsheet holding it together.

    The agency ran on disconnected third-party tools: time tracking in one place, invoicing in another, deals tracked manually, with a master spreadsheet glueing it all together at the end of the month.

    Every billing cycle was the same routine. Export time. Reconcile it against deal terms. Generate invoices. Send payment links. Chase payments by hand. Knowing how a project was tracking against budget meant doing the math after the fact.

    With multiple client projects in parallel, the monthly close had quietly become a part-time job.

  2. 02

    One workflow, top to bottom

    Deal → client → project → tracked time → invoice → settlement. One app, one URL.

    Built as a single Next.js app with typed entities from the database up. The flow follows how the agency actually operates: a signed deal creates a client and spins up the project that fulfils it. Developers log time against the project's tasks. Budgets aggregate that time live against deal terms. Invoices generate from the same data and route through Stripe, with paid/failed/refunded state syncing back via webhooks.

    One source of truth. One URL. No exports.

  3. 03

    Role-based access at the database

    Admins manage. Developers log time. Postgres enforces the rules, not the UI.

    Two roles, strict scoping. Admins manage users, projects, clients, deals, and invoices. Developers see only the projects they're assigned to and can log time against them. The boundary isn't enforced in the UI — it lives in Postgres as Row Level Security policies, so even a direct API call can't cross the line.

    The win isn't the policies themselves. It's that application code stops carrying access checks. Every query is safe by default. A UI bug can't leak data the user wasn't supposed to see, because the database refuses to return it.

  4. 04

    Stripe, the billing surface

    Hosted checkout, idempotent webhooks, state that converges no matter what arrives.

    Invoices generate in the app and route to Stripe-hosted checkout. Webhooks reconcile paid, failed, partially-refunded, and disputed states back into the deal record.

    The hard part wasn't sending invoices. It was making sure that if a webhook arrives twice, out of order, or weeks late after a manual refund in the Stripe dashboard, the local state still converges to the truth. Idempotency keys on every state mutation. Status transitions encoded as a small state machine. The cycle that used to demand manual exports, manual sends, and manual chase-ups now runs as one button and self-corrects as money moves.

  5. 05

    Outcome

    The monthly close stopped being a project.

    The agency retired four SaaS subscriptions and the standing spreadsheet that lived between them. The manual reconciliation that used to consume the close cycle is gone — there's nothing to reconcile, because there's nothing to export.

    Budgets read live instead of springing surprises at month-end. Invoices generate from the same data developers were logging anyway. The team and the client see the same numbers in the same place.

    The boring metric: no one talks about billing in standups anymore.

← Previous Scaling a learning platform to 180,000 learners across 90+ countries Next → Collapsing an LMS and a student CRM into one product for the auction industry

Build with intent. Ship with care.

© 2026 Hamzah. All rights reserved. Karachi · Available Q3 2026