Case Studyโ€ขโ€ข2 min readโ€ข511 words

Case study: invoice generator MVP shipped in 6 days

A day-by-day breakdown of how I scoped, built and launched an invoice generator MVP in six working days โ€” including the cuts that made it possible and the unexpected technical wall on day 4.

Founder reached out on a Sunday. By the next Sunday there were three paying customers. Here is the actual timeline, with the parts I usually don't put in marketing copy.

The brief

A freelance accountant who wanted to sell a stripped-down invoice generator to her small-business clients. Send a Telegram message with the client name and amount, get a PDF invoice back, billed monthly per active client.

The riskiest assumption: would her existing client base actually pay for this when they could use a free template? That was the only thing the MVP needed to answer.

Day 1 (Monday) โ€” scope and design

3-hour kickoff call. We cut:

  • Multi-user accounts (she was the only user)
  • A web dashboard (Telegram was the surface)
  • Logo upload (hard-coded for v1)
  • Multiple currencies (USD only)
  • Tax line items (one tax rate, set once)

What stayed: a Telegram bot, a PDF generator, a Stripe link, a tiny admin page for her to see active customers.

Day 2 โ€” build the spine

Telegram bot with grammY. Three commands: /new, /list, /help. Wrote the conversation flow first, then the storage. By end of day, the bot accepted a message and stored it in Supabase. No PDF yet.

Day 3 โ€” the PDF

This is where I always underestimate. PDF generation is fiddly. Spent 5 hours getting a clean A4 layout in pdf-lib that worked across viewers. The trick: don't try to be clever with layouts. One column, generous margins, system font. Done.

Day 4 โ€” the wall

Cloudflare Workers don't ship with the Node fs module. pdf-lib needed font files. I had wired font loading to read from disk, which works locally and explodes on deploy.

Fix: inline the font as a base64 string at build time. Cost me 6 hours and one emergency Discord question. Lesson re-learned: test deploys on day 2, not day 4.

Day 5 โ€” Stripe and the admin page

Stripe payment link (not full Checkout โ€” too much for a 6-day budget). A 50-line Next-ish admin page so the founder could see who paid and revoke access. Manually wired the webhook.

Day 6 โ€” show, fix, ship

Showed the founder. She found 4 things I'd missed:

  1. The PDF had her old business name
  2. /new should remember the last client
  3. Stripe link should pre-fill her email
  4. The bot's welcome message was too long

All four were 15-minute fixes. Shipped Friday evening. First paying customer Saturday morning.

What I'd do differently

  • Test the production deploy on day 2, not day 4.
  • Cut the admin page entirely. She would have used Supabase Studio for a week and been fine.
  • Charge slightly more. Fixed-price sprints look great until the day 4 wall.

The whole thing was 35 billable hours. Three months later it's at 40 paying customers with zero ongoing work from me. That's the bar for "good MVP outcome" โ€” you ship something, it buys real information, and you're not on the hook to babysit it.

Frequently asked

Common questions

How much did this MVP cost to build?
Roughly 35 hours at my freelance rate. Stack and hosting were under $10/mo. The founder paid me on a fixed-price 6-day sprint, not hourly.
What stack did you use?
TanStack Start, Supabase for auth and Postgres, Stripe for one-shot payments, and pdf-lib for the PDF rendering. Deployed on Cloudflare Workers.
Written by
Oxymore

Oxymore is a one-person studio shipping MVPs, landing pages, React apps and Telegram bots for founders who would rather move than meet.

Last updated