DEV Community

How I built a free, no-sign-up invoice generator on Cloudflare (Pages + D1 + Workers)

Every "free" invoice tool I tried had the same catch: create an account, then you can download your PDF. For someone who just needs to send one invoice, that's a lot of friction - and your data ends up on someone else's server.

So I built Free BizDoc: you fill in the fields and the PDF is generated in your browser. No account, nothing uploaded. Here's how it's put together and why the core can stay free.

The constraint: near-zero running cost

If a tool is going to be free with no sign-up, it has to be cheap to run. That ruled out a classic always-on server.

The whole thing sits on Cloudflare:

  • Pages for the static front-end (the tool pages, blog, landing pages).
  • D1 (SQLite at the edge) for the optional accounts / saved documents.
  • Workers / Pages Functions for the few dynamic endpoints (auth, Stripe webhook, contact).

At low-to-moderate traffic this lands comfortably in free/cheap tiers, which is the real reason the generator can be free rather than a loss-leader funnel.

Generating the PDF in the browser

The part people ask about most: the invoice PDF is built client-side with pdf-lib. The form state becomes a document model, then a PDF, all in the tab.

That has two nice properties:

  • Privacy - invoice contents (client names, amounts) never touch a server unless the user explicitly saves.
  • Cost - no server-side rendering to pay for.

The trade-off is that you lean on the browser, so I keep the document model explicit (anchored columns, right-aligned money) rather than relying on HTML-to-PDF.

Multi-country tax as pure functions

The product targets the US, UK, Australia and Canada. Tax is the fiddly bit, so each regime is a small pure function over the line items:

  • US sales tax (rate you set)
  • UK VAT (per-rate breakdown, VAT number)
  • Australian GST which produces a compliant "Tax invoice"
  • Canadian GST/HST + PST/QST by province

Switching country re-labels fields (currency, paper size Letter/A4, date format, tax-ID name) and swaps the tax function. Keeping them pure made them easy to unit-test with sample line items.

Share without storing: data in the URL

Instead of saving a document to send it, "Create a share link" base64-encodes the document into the URL hash. Open the link and the recipient sees a read-only view with the amount, due date and bank details, plus a PDF download.

The data lives only in the link - nothing is stored server-side. The cost is a long URL, which is a fair trade for not running a storage path.

One-click conversions

Because every document shares the same model, converting estimate into invoice into receipt is just re-labelling and re-numbering the same data. It's the feature people seem to like most and it was almost free to add.

What I'd do differently

  • Put the tax logic behind a tiny test harness from day one - I retrofitted it.
  • The URL-hash share is neat but bumps into URL length for big documents; a short-link option is on the list.

Try it Live: https://free-bizdocs.com/en/ - make an invoice, no account. Happy to answer anything about the browser-side PDF generation, the D1 schema, or the tax functions in the comments.

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.