Type to search notes, tools, and pages...

Heftli

Invoicing SaaS for freelancers and Swiss SMEs

Role
Sole designer, engineer, operator
Launched
January 2026
Stack
TypeScript, React, Supabase, Stripe, PostgreSQL
Heftli interface

The problem

Swiss freelancers and small businesses have to issue QR-Bill invoices, a national standard with strict formatting rules that most international invoicing tools either do not support or bolt on badly. The alternatives were enterprise accounting suites with a setup cost measured in days, or spreadsheets.

I wanted something that handled QR-Bill natively, tracked time against clients, and did not require a bookkeeping background to operate.

Architecture

Multi-tenant from the first commit

Retrofitting tenancy is expensive, so row-level security and tenant scoping went in before the first feature. Supabase provides the Postgres layer and auth; every query runs under an RLS policy, so a tenancy bug in the application cannot leak data across accounts. The app started on Cloudflare Workers. I moved it to DigitalOcean to avoid lock-in to one vendor's runtime.

Stripe handles subscriptions with webhook reconciliation. The app derives billing state from Stripe instead of maintaining a mirror, which removes a whole class of drift bugs.

The QR-Bill generator is a self-contained module producing Swiss-standard payment parts, validated against the specification rather than against sample output.

  • Tenant isolation enforced by row-level security in Postgres
  • Stripe as the source of truth for billing state
  • Background jobs for reconciliation and scheduled invoicing
  • Migrations run in CI against a production-shaped dataset

Operating it

One person, every layer

There is no team. I write the migrations, handle the failed-payment edge cases, monitor the background workers, answer the support email, and ship the frontend.

That constraint shaped the architecture more than any preference did. Anything requiring routine manual intervention got automated or removed, because there is nobody to hand it to. The system has to be boring enough to leave alone for a week.

Get in touch

Get in touch

Send a note to start a conversation, or reach out directly by email.

Contact