Brightloop build plan

We're building a billing system that tells a small team what needs doing today and handles the routine work itself. Our pitch: Brightloop's month, running by itself.

The day

All times are IST. Start at 9:30 and submit by 4:45, which leaves 15 minutes spare before the round closes at 5:00.

9:30 to 10:30Foundation
10:30 to 1:30Billing run, tax and discount engine
1:30 to 2:30Time machine, renewals
2:30 to 3:30Bank matching
3:30 to 4:00Deploy
9:30 to 11:30Login, reset, roles
11:30 to 2:30Products, variants, plans, taxes, discounts
2:30 to 3:30Guided setup, preview
3:30 to 4:00Spec check
9:30 to 12:30Quote templates, subscriptions, status flow
12:30 to 2:00Invoice screens
2:00 to 3:00Timeline
3:00 to 4:00Today queue
9:30 to 10:30App shell
10:30 to 12:30Payments, overdue
12:30 to 2:30Customer portal
2:30 to 3:30Finance page
3:30 to 4:00Big seed, speed
Everyone
4:00 to 4:30Demo, fixes
4:30 to 5:00Submit
Now

Who does what

Each task is done only when its "Done when" line is true. Ticks are saved on your device only, so they won't show for anyone else.

Swayam

Owns the schema, the billing engine and the live link.

Next.js, Postgres, Drizzle, the full schema, all status values, and the shared functions listed below.

Done when: all four people run the app and small seed locally by 10:30.

Put the first version on Vercel and Neon, then keep the live link working all day.

Done when: main reaches the live link automatically by 11:00.

computeInvoice() covers tax rules, fixed and percentage discounts, minimum purchase or quantity, date windows, usage limits, and product or subscription scope.

Done when: tests cover each rule, and expired or used-up discounts stop applying.

It finds everything due, creates draft invoices with lines filled in, and records why anything was skipped. Daily, weekly, monthly and yearly plans all work.

Done when: a second run creates 0 new invoices, and 5,000 subscriptions finish with visible progress.

An admin control moves the app date forward. That triggers renewals and auto-close, and respects each plan's pause, close-early and renew settings.

Done when: jumping a month changes subscriptions, discounts and overdue invoices correctly, with a clear "simulated date" banner.

Upload a CSV, suggest invoice matches by amount, reference and date, and let staff confirm each one.

Done when: confirming a match records a payment and updates the invoice.

Supriya

Owns access control and everything the admin sets up.

Better Auth with unique emails. Send the reset link by real email using Nodemailer and Gmail SMTP.

Done when: an 8-character password fails, a compliant 9-character one passes, and the reset link arrives in a real inbox.

Admin, staff and customer roles, enforced on the server. Provide requireRole() early for everyone else.

Done when: only an admin can add staff or create discounts, even by calling the API directly.

Name, type, sales price, cost price and notes, plus variants with an extra price.

Done when: choosing the Odoo brand adds 560 to the price.

Price, billing frequency, minimum quantity and availability dates, with per-plan switches for auto-close, close early, pause and renew.

Done when: every option is saved and can be read by the billing engine.

Admin-only forms for every rule field, with clear validation errors.

Done when: rules created here change the result of computeInvoice().

Steps run from product to variants, plan and rules. The preview uses computeInvoice(), not separate maths.

Done when: changing any price, tax or discount updates the preview immediately.

Go through the PDF scene by scene on the live link and post gaps in the team chat.

Done when: every scene is confirmed or has an owner fixing it by 4:00.

Shreyansh

Owns the daily staff workflow, from quote to invoice.

Preset plan and product lines, with a validity period in days.

Done when: a rep starts a quote from a template in a few clicks, and an expired quote can't be confirmed.

Auto-generated number, customer, plan, start and expiry dates, payment terms, and lines with product, quantity, unit price, taxes and amount.

Done when: minimum quantity is enforced and totals match computeInvoice().

Draft, Quotation, Confirmed, Active, then Closed, using the shared transition function.

Done when: skipping a step is rejected by the server, and the current status is visible everywhere.

List, detail, confirm, cancel, send by email and a clean print view.

Done when: all four actions work and the print view looks like a real invoice.

Status changes, invoices, payments, discounts and pauses in date order, read from the shared event log.

Done when: someone new can tell what happened to a subscription without asking.

The staff home page lists upcoming renewals, invoices to confirm, overdue invoices and expiring quotes, each with its action in place.

Done when: completing an action removes the item, and time machine jumps change the list.

Debangshu

Owns the app's look, customer experience and finance reporting.

Navigation per role, layout, colours, and table, form, status-badge and empty-state components for everyone to reuse.

Done when: the kit is merged by 10:30 and works at phone width.

Record method, amount, date and note against an invoice. Show paid, outstanding and overdue lists.

Done when: part-payment leaves the balance visible, and full payment moves the invoice to Paid.

Customers view their subscriptions and invoices, switch add-ons, change seats and pause where the plan allows. Changes take effect on the next invoice.

Done when: the next invoice shows before confirming, and one customer can't open another's data by changing a URL.

Active subscriptions, revenue, amount owed, payments and overdue invoices, with filters and a summary.

Done when: clicking any number opens the records behind it, and those records add up to it.

Add 5,000 subscriptions with realistic invoices, then check every page. Use server-side pagination, indexes and database totals. Show load time on screen.

Done when: every page loads in under 2 seconds on the live link.

Turn the running order below into a final script, and add setup steps and demo logins for each role.

Done when: someone outside the team could run the app and log in from the README.

Rules for all of us

Stack

  • Next.js and TypeScript in one repo
  • Postgres with Drizzle, Better Auth and Zod
  • Tailwind and shadcn/ui
  • Nodemailer and Gmail SMTP for email
  • Vercel and Neon for the live link

Working together

  • Everyone commits their own work from their own GitHub account, because the rules call for real team use of Git.
  • Use short branches and merge to main at least once an hour.
  • Ask Swayam before changing the schema, so migrations don't collide.
  • Understand any AI-written code you merge, since you may have to explain it.
  • Write everything during the round, with no code from earlier projects.

Rules in the code

  • Never use new Date() for business logic. Always use appNow(), or the time machine breaks.
  • Store money as whole paise, never as decimals.
  • Only computeInvoice() does invoice maths, so the preview, portal and final invoice always agree.
  • Change status only through transition(), which also writes the event log.
  • Check roles on the server. Hiding a button doesn't count.
  • Validate all input with Zod on the server and show field-level errors.
  • Paginate lists on the server and calculate totals in the database.
  • Allow one non-cancelled invoice per subscription and billing period, using a unique index. This is our guarantee against double billing.

Where we depend on each other

Whoever's waiting builds against the stub or seed data until the real thing lands.

WhatFromUsed byBy
Schema, appNow(), transition(), small seedSwayamEveryone10:30
Table, form and status-badge componentsDebangshuEveryone10:30
requireRole() and the current userSupriyaEveryone10:30
computeInvoice(), first as a stubSwayamSupriya, Shreyansh, DebangshuStub 10:30, real 12:30
Plans and discounts in the databaseSupriyaSwayam, Shreyansh1:00
Active subscriptions to billShreyanshSwayam12:30
Draft invoices from the billing runSwayamShreyansh, Debangshu1:30
Payment recording functionDebangshuSwayam, for bank matching12:30

The 3-minute demo

Everything we build should make one of these moments work. Debangshu keeps the final script and everyone rehearses at 4:00.

  1. The admin launches a product with an Odoo variant that adds 560, and the invoice preview updates live.
  2. A rep starts from a quote template and moves the subscription through to Active.
  3. Jump to billing day and run billing across 5,000 subscriptions. Run it again to show 0 new invoices.
  4. A customer logs in, adds seats, and sees their next invoice before confirming.
  5. Staff upload a bank statement and confirm the suggested payment matches.
  6. Jump ahead a month. A discount has ended, overdue invoices appear in the Today queue, and a plan closes itself.
  7. The finance lead clicks revenue, sees the invoices behind it, and the load time on screen stays under 2 seconds.