MVP Build Order & Product Design Principles
Status: agreed for MVP · Last updated: 10 June 2026
Companion to: Architecture, Schema & Cost Model.
Original strategy doc: “MVP Build Plan - Quoting, Invoicing & Tax App for Tradespeople”.
Strategy in one line
Section titled “Strategy in one line”Getting paid is the acquisition hook; tax is the retention hook. Build money-in first, tax second, MTD filing third. Every feature passes the test: would our customer zero actually use this on a Tuesday in a van?
Build order
Section titled “Build order”Before code (this week)
Shadow customer zero through one real quoting cycle and one late-payment chase; design screens to mirror his existing steps. Register on the HMRC Developer Hub now - recognition is the long pole for Phase 3 even though the API isn’t touched for months.
Bootstrap weekend
Monorepo: /app (Expo, TS), /web (client quote page), /api (Python Azure Functions). Supabase project created from version-controlled migration files (supabase db push), never dashboard clicking. Empty Function App deployed so the pipeline exists before it matters.
Work split: one of us on Expo/web, one on Functions/database, meeting at the Supabase schema and a small set of API contracts.
Weeks 1-3 - the vertical slice
Create quote in app -> public token link -> client opens web page -> taps accept -> status flips -> push notification fires. No payments, no PDF, no expenses. Ugly, end-to-end, on customer zero’s actual phone.
Week 4 - money
Payment is decoupled from acceptance: the client accepts (or declines) a quote with no money changing hands, the tradesperson raises an invoice when the work is done, and the client then pays that invoice by card (Stripe Checkout) or cash. Webhook -> payment row -> invoice paid. This is the quote-to-paid demo shown to the 5-10 trades customer zero introduces.
After the slice
PDF generation, receipt capture, chase messages - in that order. None matter until quotes flow.
Scope discipline: anything that smells like a settings page, “manage X” screen, or job management goes in a parked-ideas file, not the backlog. The vertical slice is the only thing with permission to exist for a month.
Backend function inventory
Section titled “Backend function inventory”pdf.py- WeasyPrint quote/invoice renderreceipts.py- Claude vision call ->{amount, date, merchant, category}webhooks.py- Stripe signature verify, idempotent payment insertchasers.py- daily 08:00 timer, derived-overdue query, email -> SMS ladder- Deposit-link endpoint - on accept: create deposit invoice + Stripe Payment Link (holds the Stripe key, hence Functions not Postgres)
UI design principles: tradesperson side
Section titled “UI design principles: tradesperson side”- One-thumb, in-a-van: primary action is a full-width button at the bottom of every screen; targets big enough for gloves.
- Plain English, never accounting jargon: “Owed to you”, not “accounts receivable”; “Put aside for January”, not “estimated liability”.
- “Owed to you” is the first number on the home screen, with the overdue amount as a red badge - the daily reason to open the app. Always show post-CIS figures: what actually lands in the bank.
- CIS is always framed as “tax already paid”, never “deduction”. The progress bar (“55% of your January bill already covered”) is the emotional core of the tax feature and the word-of-mouth moment.
- Invoice detail shows the contractor’s maths explicitly: total -> CIS withheld -> you’ll receive.
- Automation with a manual override: chasers run nightly, but “chase again now” and “mark paid another way” keep the user in control. Automation that can’t be overridden gets turned off.
- Receipt capture is confirm-not-type: extraction pre-fills, user checks and saves. Category chips (six, on-screen), not dropdowns. Camera -> glance -> save in under ten seconds.
- Rate picker is a bottom sheet asking a question (“How many days?”) with the live total on the add button. Per-job override = manual price, null rate card. More than roughly five rate cards is a signal the user is really a team, which is out of scope.
- Status colours are a language: green = money/done, amber = waiting, red = overdue, grey = inert. No badge should need reading to know if it’s good news.
UI design principles: client side
Section titled “UI design principles: client side”- The client never logs in and never installs anything. Quote, accept, and pay all live on one tokenised link.
- The tradesperson’s brand leads the page; ours stays out of the way. It’s Rhys’s quote.
- Trust signals by the pay button: “handled by Stripe”, “Rhys never sees your card details”. Deposit/remainder split stated before acceptance - no surprises.
- The accept tap and the deposit ask are one gesture, not an invoice email three days later.
- Expired quotes are not dead ends: one-tap “ask for an updated quote” notifies the tradesperson and turns a stale lead warm. Cheap to build, highly tellable.
Tax feature cautions
Section titled “Tax feature cautions”- Position as a running estimate, never advice. Keep the “estimate only - based on what’s recorded here” line.
- The real calculation has traps: payments on account (doubles the first year’s bill - the thing that blindsides first-year subbies), Class 4 NI thresholds, trading allowance. Payments-on-account warning is a must-have before Phase 2 ships.
- Accountant export ships as a dumb CSV (the five summary numbers + categorised expenses) long before MTD. Accountants tolerate it happily; it buys Phase 3 time.
Standing risks
Section titled “Standing risks”- Can’t compete on compliance price (ANNA et al. file free); we win on the quote-to-paid workflow.
- HMRC recognition drags - sandbox work starts months early.
- Scope creep into job management - resist until people pay for it.
Potential features
Section titled “Potential features”A scratchpad for ideas worth considering after the vertical slice. Anyone can add — keep entries short, lead with the user problem, not the implementation. Promotion into the backlog happens during build-order reviews; until then, nothing here is committed.
Format per entry: Title — one-line user problem. Added by, date. Optional second line for context.
- Similar past jobs at quote time — while drafting a quote, surface previous jobs that look similar so the tradesperson can see what they charged before. Avoids under-pricing and speeds up quoting; works off existing
quotes/quote_itemsdata. - Invisible discount / mark-up — let the tradesperson apply a private adjustment (e.g. mates’ rates for family/friends, or a mark-up for awkward jobs) that never appears on the client-facing quote or PDF. Client sees only the final line total; internal records keep the original and the adjustment for the tax estimate.
- Client user accounts (very long term) — repeat clients have no single place to see their quotes, invoices and payment history across tradespeople. Optional client login on top of the tokenised links, which must keep working with no account. Not before the tradesperson product is paying its way; would revisit the “client never logs in” principle and the anon-role rule. Added by steamedtoast0704 (Discord), 2026-09-30.