Everyone who freelances builds one of these eventually. It's a good project because the requirements are unambiguous, the output is a real artifact, and there's exactly enough fiddly detail to learn from.

1. Get the money right first

Before any layout. Amounts as integer minor units or a decimal type, never floats. Currency stored with every amount. Tax calculated per line or on the total — decide which, because they give different answers with rounding. Round exactly once, at display.

invoice-maths.txt
Write the calculation for an invoice with:
- Line items: description, quantity, unit price.
- A tax rate that may vary by line.
- An optional discount, which may be a percentage or a fixed amount.

Use integer minor units throughout. Show me:
- The order operations happen in, and why that order.
- Exactly where rounding occurs, and in which direction.
- A worked example where naive float maths gives a different total.

2. Build the numbering

Invoice numbers must be sequential, gapless in most jurisdictions, and never reused. This is a legal requirement in more places than people expect, and it's not something to improvise. Generate on save, not on preview, and never let a draft consume a number.

3. Generate the PDF

Two approaches. Render HTML and convert with a headless browser — easy, and it looks exactly like your web version. Or build the PDF directly with a library — more control, more work. For most invoices, HTML-to-PDF is the right call.

Either way, the invoice must include: both parties' names and addresses, the invoice number, issue date, due date, line items, subtotal, tax with its rate stated, total, and your payment details. Missing any of those creates a query and delays payment.

4. Store what you generated

Save the rendered PDF, not just the data. Prices change, your address changes, your logo changes — an invoice reissued next year from live data will not match what the client received. The document is the record.

Add the payment terms and a due date. "Payment due within 14 days" on the invoice is the cheapest cashflow improvement available to you.