Home / Work / Billing Platform
INTERNAL PLATFORM · IN DAILY USE

A billing system
with a zero
hosting bill.

Invoices, quotations, a master price list, a billable-services ledger, client records, recurring monthly and annual profiles, payment allocation and a receivables dashboard — a complete billing platform that fits entirely inside Cloudflare's free tier. The document engine renders pixel-exact multi-page A4 in the browser, so PDF generation costs nothing either.

Type
Internal platform, run in production
Frontend
React + TypeScript + Vite SPA
Backend
Hono on Cloudflare Pages Functions
Database
Cloudflare D1 — 14 tables
Catalogue
~128 SKUs across six domains
Infra cost
$0 / month
$0
Monthly infrastructure cost
14
Database tables
128
SKU master price list
0
Paid cron jobs for recurring billing
/ 01
The Problem

Off-the-shelf invoicing charges per seat, per month, forever — for a workflow that is fundamentally a few tables and a rendering problem. It also imposes someone else's document design, which for a consultancy whose entire pitch is precision is a bad look on every invoice it sends.

The harder requirement was the document itself. An invoice with forty line items has to break across pages correctly: headers repeat, Page X / Y is right on every sheet, and the totals block never splits across a page boundary. CSS print rules alone do not reliably deliver this — the browser will happily orphan a totals row.

/ 02
The Approach

The document engine is measurement-based, not rule-based. Rather than hoping CSS page-break hints behave, it measures rendered element heights against the real A4 content box and assigns rows to pages deliberately. Because the layout is computed rather than hinted, output is correct for any number of line items — and the totals block is placed as an atomic unit that cannot be split.

PDF generation is the browser's own print pipeline. No headless Chrome on a server, no PDF library, no rendering worker — which removes both the largest cost centre and the most common source of "it looks different in production" bugs.

Recurring billing runs without a paid scheduler. Rather than a cron worker firing on a timer, profiles are evaluated lazily against their next-due date whenever the application is used, generating draft documents when they come due. For a system with a daily human in it, lazy evaluation is indistinguishable from a scheduler — and free.

The data model is a real ledger: documents and document lines, payments with explicit payment allocations, ledger entries, recurring profiles with their own line templates, and an activity log. Payment allocation as a first-class table is what makes partial payments and credit against multiple invoices tractable instead of a reconciliation nightmare.

/ 03
The Hard Parts
  1. Pixel-exact A4 from HTML Getting a browser to emit a document that measures correctly in millimetres — with repeating headers, correct page counts and unbreakable blocks — is finicky work that most teams avoid by paying for a server-side renderer.
  2. Living inside free-tier limits by design D1 and Pages Functions have real ceilings on request duration, query volume and storage. The schema and query patterns were designed against those limits from the start, rather than discovering them later under load.
  3. Quotation-to-invoice conversion without duplication A quotation that becomes an invoice must keep its line items, periods and comments while taking a new number in a different sequence — and the original must remain intact as a record of what was offered.
  4. Authentication that holds up on a static host A static front end has no server session by default, which is where most such systems quietly compromise. Credentials are hashed with a slow, salted algorithm and sessions are validated server-side rather than trusted from the browser.
/ 04
The Outcome

The platform runs our own billing. Quotations convert to invoices in a click, line items autocomplete from the master price list, VAT is configurable per document, and the dashboard shows pending, billable, billed and paid alongside receivables and overdue items.

Every invoice we send is rendered in our own document design — which, for a business selling precision engineering, is the most-seen artefact we produce.

It is also a working proof of a pattern we deploy for clients: a genuinely complete internal business system with no recurring infrastructure cost, built on primitives that scale up if the volume ever justifies it.

Stack Cloudflare D1 Pages Functions Hono React TypeScript Vite Measurement-based pagination Browser print-to-PDF Server-side sessions Relational schema design

Most "we need a SaaS subscription" problems
are fourteen tables and a renderer.

STOP RENTING YOUR OWN WORKFLOW

Per-seat pricing on a system you
could own outright compounds forever.

Contact Us →