Build a full invoicing system. This is real software that real freelancers pay for (FreshBooks, Wave, Invoice Ninja). You'll deal with financial calculations, PDF generation, status workflows, and dashboard analytics.
What to Build
- Client management: name, email, company, address, phone. Full CRUD.
- Invoice builder: select a client, add line items (description, quantity, unit price), tax rate, discount, notes. Auto-calculate subtotal, tax, total.
- Invoice statuses with a workflow: Draft → Sent → Viewed → Paid → Overdue. Status changes logged with timestamps.
- Auto-incrementing invoice numbers (INV-001, INV-002), configurable prefix
- Recurring invoices: mark as recurring (weekly/monthly), auto-generate new drafts
- Dashboard: revenue this month/quarter/year, outstanding amount, overdue amount, invoices by status, revenue over time chart
- PDF generation: generate a clean PDF of any invoice server-side (pdfkit or puppeteer)
- Due date tracking: invoices auto-become "overdue" after the due date
- Payment recording: mark paid with date and payment method
Phases
1Design schemas: User, Client, Invoice, LineItem, Payment. Where do line items live? How do you store status history?
2Backend: Client CRUD, Invoice CRUD with status transitions, line item calculations server-side (never trust the frontend with money), PDF endpoint, dashboard aggregation with MongoDB pipeline.
3Frontend: client list, invoice builder (dynamic add/remove line items), invoice detail, dashboard with charts, PDF download.
4Tests: SuperTest for invoice total calculations and edge cases, Playwright for full creation flow. Deploy.
Decisions You'll Make
How to handle money (floating point is dangerous — store cents as integers?). How to build the dynamic line item form (add/remove rows, recalculate live). How to implement the status workflow (what transitions are valid? can Paid go back to Draft?). How to generate PDFs server-side. How to build aggregation queries for revenue by month grouped by status.
Stack
React
Express
MongoDB
Mongoose
JWT
React Router
React Query
useReducer
Custom Hooks
Vitest
SuperTest
Playwright