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
Stripe Payment Link on the accept page for the deposit; 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.