Heftli
Invoicing SaaS for freelancers and Swiss SMEs
- Sole designer, engineer, operator
- January 2026
- TypeScript, React, Supabase, Stripe, PostgreSQL

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