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:
- The PDF had her old business name
/newshould remember the last client- Stripe link should pre-fill her email
- 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.
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.
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