Ideas Unlimited Productions · Mumbai · 2026

Seven hours, one person.
One working business.

A GST-compliant invoice system for a 35-year theatre company. Proforma to tax lifecycle, audit trail, PDF generation, WhatsApp share. Built end to end by the person who files the invoices.

Ideas Unlimited Invoice System dashboard, FY 2025-26, 10 invoices, ₹34.5L tracked

Role

Solo Designer + Full-Stack Developer + User

Timeline

7 hours, end to end

Team

1 person — Janam

Scope

Full-Stack Product, Domain Architecture, AI-Assisted Build

7 hrs
Build time
₹34.5L
Tracked FY 2025-26
0
Manual errors

Background

I built the software
that runs my family's business.

Ideas Unlimited Productions · Mumbai · founded 1990

113+ productions. Clients include NCPA, Reliance, Kandivali Education Society. 2–3 invoices a month. ₹34.5L+ tracked in FY 2025-26.

Manoj Shah — my father — runs the company. I'm the one who makes the invoices. I was bad at it. Wrong dates, wrong play names, wrong GST splits. The accountant charged ₹40,000/year for work that was structured, repeatable, and rule-based.

The problem

Google Sheets is not a system.
An accountant is not software.

What existed

  • · Google Sheets
  • · Phone calls to the accountant
  • · Manual GST splits
  • · Wrong dates, wrong numbers
  • · Proforma + tax as two unrelated docs
  • · Payment proof trapped in WhatsApp chats
  • · ₹40K/year for rule-based work

What should exist

  • · One source of truth
  • · GST encoded as software, not human memory
  • · Proforma → tax as one lifecycle, not two documents
  • · Audit trail by default
  • · Indian small-business sharing flow (WhatsApp first)
  • · Built and owned by the person who uses it

The problem wasn't that no tool existed. It was that every tool was built for a generic small business — not for someone billing ₹14L for one performance, with a 50% advance, a 9%+9% GST split, an Indian-numbered amount-in-words, and a payment proof that lives in a WhatsApp screenshot.

The work

Five screens. The whole product.

Step 01 · Lifecycle as architecture

One invoice. Four states.
One source of truth.

Invoice detail page showing the proforma to advance received to invoice generated to paid lifecycle tracker

Most invoicing tools treat proforma and tax invoices as separate documents. IU's actually need to evolve through advance receipt — so the schema collapses both into one entity with a status enum.

Step 02 · Description Builder

Rule-based generation.
Manual override one click away.

New invoice form with the Description Builder active, play 'Adbhut' selected, 50 percent advance preset, and an auto-generated preview

Pick a play, pick an advance percentage, pick a date — the description writes itself in IU's exact voice. “Edit manually” sits one click away for the exceptions.

Step 03 · Dashboard

The financial year, at a glance.

Invoices dashboard with FY 2025-26 filter, four KPI cards (10 invoices, 34.5L revenue, 7 paid, 3 pending), and a sortable invoice table

FY filter, four KPI cards, sortable invoice table with payment status. The accountant's monthly reconciliation report — replaced by the homepage.

Step 04 · PDF generation

A real Indian tax invoice,
server-rendered.

Generated tax invoice PDF for The National Centre for the Performing Arts, performance fees for Clean Bold, total 88500 rupees with 9 percent CGST and 9 percent SGST split

What the PDF includes

  • · IDEAS UNLIMITED letterhead + logo + seal
  • · Bill From / Bill To / GSTIN / SAC code
  • · CGST + SGST split (9%+9%)
  • · Bank details for direct transfer
  • · Manoj Shah signature block
  • · Indian numbering: "Eighty Eight Thousand Five Hundred"

@react-pdf/renderer, two templates (proforma and tax). Field-for-field compliant with what IU's CA already accepts.

Step 05 · Built for phones

Manoj checks invoices on his phone.
So do I.

Mobile new-invoice form on iPhone 14 Pro Max viewport, Description Builder active
Desktop invoice detail page with the same lifecycle tracker and action buttons as the mobile flow

Same lifecycle, same tracker, same actions — 430px to 1440px. Tailwind 4, no separate mobile build.

Results

Built in seven hours.
Live for a real business since.

0hours

Build time

0L

Tracked FY 2025-26

0invoices

This FY

0

Manual errors

₹40K/year accountant fee → ₹0.
Replaced by a system the user owns,
built in one afternoon.

Deep dive

Seven chapters,
for readers who want the why.

Decisions, architecture, what AI got right, what didn't ship.

Chapter 1 · Build vs Buy

Why I didn't pay ₹500/month
and stop typing.

Workflow fit

No SaaS supports proforma → advance → tax invoice lifecycle with play/venue/date fields and an auto-generated description that reads in IU's voice.

Cost

₹0/month vs ₹500–2,000/month for a tool that still requires manual workarounds on every single invoice.

Ownership

The invoice system is the foundation of a 14-phase production management platform. You don't build your foundation on someone else's SaaS.

What no SaaS supports

A proforma that becomes a tax invoice after advance receipt, with auto-generated descriptions in IU's voice and amount-in-words rendered in Indian numbering (Lakhs and Crores). Three things that aren't features anywhere, because the assumed user isn't this user.

This is Phase 1 of a 14-phase production management platform. The invoice system is the foundation — once the data model is right, scheduling, cast/crew, contracts, and revenue splits are additions, not rewrites.

Chapter 2 · Lifecycle as architecture

One invoice, four states.
Not two documents.

State 1

proforma

State 2

advance_received

State 3

invoice_generated

State 4

paid

Side branch

cancelled

Status enum

status:
  | "proforma"
  | "advance_received"
  | "invoice_generated"
  | "paid"
  | "cancelled"
Activity log showing real status transitions for invoice 2025-26/08, including invoice created, advance received, converted to tax invoice, and shared via WhatsApp

The schema decision

advance_amount, advance_date, advance_proof_url all live on the invoices table. There is no proformas table. There is no payments table. There is one row that grows.

Chapter 3 · Domain encoded as software

GST splits. Lakhs and Crores.
Advance percentages I actually use.

GST auto-detection

Reads the first two digits of the client's GSTIN, compares to the seller's state code, picks the right tax split.

gstin[0:2]27 (Maharashtra)intra (CGST + SGST)

Indian numbering

Amount-in-words rendered in Lakhs and Crores, the way an Indian CA expects to read it.

✓ “One Lakh Twenty Thousand”

✗ “One Hundred Twenty Thousand”

Advance presets

25 / 40 / 50 / 75 + Custom. These are IU's actual percentages — known from doing the calculations manually for years.

25%40%50%75%Custom

SAC code 998596

Hard-coded in business settings. Indian tax invoices need a service accounting code that matches the work performed — for performing arts, that's 998596.

Business settings page showing the SAC Code field set to 998596

Each of these is a fact about IU's actual workflow. None of them are configurable. That's the point.

Chapter 4 · No context breaks

Same principle as
SBI's inline OTP.

Client picker dropdown open in the new invoice form, showing 12 saved clients and the option to create a new one inline
Inline 'Add New Client' form expanded directly below the picker — name, address, GST, PAN, save button

→ See SBI Redesign for the same principle applied to OTP entry

Why it matters

Modal-less. The form expands inline below the picker, the user fills it, saves, and the picker auto-selects the new client. Zero context loss. Same shape applied to plays, venues, and the Description Builder.

Chapter 5 · The trust system

Audit ≠ auth.
Both matter.

Activity log section of an invoice showing every state transition, share event, and payment update with device fingerprint and timestamp

Audit

  • · Invoice created
  • · Advance received (with proof URL)
  • · Converted to tax invoice
  • · Shared via WhatsApp / Email
  • · Final payment received
  • · Cancelled (with reason)

Each entry stamped with device info + timestamp. Survives the user.

Auth

  • · Email OTP, no passwords
  • · Phone allowlist (1–2 users)
  • · Two-step confirmation for writes
Email entry screen, the first step of the OTP flow
OTP entry screen, the second step of the OTP flow

Right-sized auth

A 1–2 user family tool doesn't need OAuth or SSO. It needs a 6-digit code, an allowlist, and an audit log that survives the user.

Chapter 6 · The Claude Code loop

Seven hours, one named principle,
three honest overrides.

[Claude] generated supabase/migrations/001_initial.sql
[Janam] rejected — Claude wants two tables (proformas, tax_invoices)
> revise: single entity, status enum, lifecycle as state machine
[Claude] regenerated with single table + state transitions
# next: invoice CRUD form (hour 2)

Hour 1

Architecture

7 Supabase migrations. Data model: clients ↔ plays ↔ invoices ↔ activity_log ↔ business_settings ↔ whatsapp_sessions. Status enum, audit trail, GST split logic.

Hours 2–3

Invoice CRUD

Create, edit, lifecycle state machine. Description Builder. GST auto-detection from client state code. Advance percentage presets.

Hours 4–5

PDF + Sharing

@react-pdf/renderer, two templates (proforma, tax). IU letterhead, tax breakdown, bank details, signature. WhatsApp + Email share flows.

Hours 5–6

Dashboard + Management

Financial dashboard with FY filtering. Client + play management with inline creation. Payment proof upload.

Hours 6–7

Polish + Audit

Activity log with device fingerprint. Settings page (company, bank, SAC). Mobile pass. Email OTP + phone allowlist.

Named principle

Architect for fast feedback. Schema first, UI last. Hour 1 was 7 Supabase migrations and an ER diagram in my head. After that the UI was just a view layer over decisions already made.

Three overrides

Schema

Claude

Two tables — proformas + tax_invoices.

Me

One entity, status enum, fewer joins, simpler audit trail.

Why

Proformas become tax invoices. They aren't separate documents.

Voice

Claude

Generic template: "Payment for the play..."

Me

Rewrote in IU’s voice: “Towards 50% of total fees to be paid as advance for the play ‘Adbhut’ on the 6th of May 2026.”

Why

Generic doesn't pass the accountant. Specific does.

Auth

Claude

Full auth flow — OAuth, password + reset, 2FA.

Me

Email OTP + phone allowlist. User count is 1–2.

Why

A family tool doesn't need enterprise auth.

Chapter 7 · What didn't ship (yet)

The chatbot. The platform.
The boundary.

Pages

  • /login
  • /clients
  • /plays
  • /settings
  • /invoices
  • /invoices/new
  • /invoices/[id]

API + Lib

  • /api/* (server actions)
  • /lib/pdf (@react-pdf)

Phase 2

  • /api/whatsapp
  • /lib/whatsapp (Anthropic SDK)

Supabase (Postgres)

  • clients
  • invoices
  • plays
  • venues
  • invoice_activity_log
  • business_settings
  • whatsapp_sessions

Block A · The WhatsApp chatbot, in design

The architecture exists: Meta Cloud API webhook, Anthropic SDK for Hindi/Hinglish parsing, a whatsapp_sessions table for confirmation state (migration 007), and a route scaffolded at /api/whatsapp. Not deployed. Phase 2.

Block B · The 14-phase platform

Invoicing is Phase 1. The plan, not the promise:

  • · Production scheduling
  • · Cast + crew management
  • · Venue contracts
  • · Revenue split with collaborators
  • · … plus 9 more

The 7 hours bought a working invoice system.
The architecture bought the next 7 phases.

Closing

The fastest way to ship the right thing
is to be the user who needs it.

What this project made me

Seven hours of build is only credible because the seven months before it were spent filing invoices badly. The speed is downstream of the domain. AI compiled the code; I compiled the requirements every time I sent a wrong invoice.

Phase 2 is the WhatsApp chatbot — designed, schema migrated, not yet deployed. Phase 3 onward is the rest of the production management platform: scheduling, cast/crew, contracts, revenue splits.