Self-hosted service
piratuks/invoice-builder avatar
piratuks/invoice-builder

Invoice Builder keeps the ledger on your machine and the PDF under your control

Invoice and quotation builder desktop app with PDF export, designed for small businesses and freelancers. Create, manage, and export invoices and quotes easily using a local database in an Electron-based app.

1,322 stars202 forksTypeScriptMIT

At a glance

What is it?
Invoice Builder is a MIT licensed Electron and React desktop application for small businesses and freelancers, with live PDF preview, a drag and drop visual layout builder, XLSX import and export for the reference data, and e-invoicing output in UBL 2.1, Peppol BIS Billing 3.0 and XRechnung. It runs on SQLite locally, and the same codebase can be self-hosted in Docker with SQLite or PostgreSQL.
Who is it for?
Invoice Builder suits a freelancer or small business that wants to issue invoices without a subscription, without an account and without its customer data leaving the machine, and that needs compliant e-invoicing formats rather than just a PDF. It does not suit a multi-user finance department that needs shared access, approval workflows and audit trails, since the data model is a single local database file by design.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Offline first, and the database file is the unit of ownership

Invoice Builder is described as an offline-first, open-source invoicing and quoting application for freelancers and small businesses, and the second half of the sentence is the pitch: no accounts, no cloud, no subscriptions, your data stays on your machine in a database file you own, with an optional self-hosted web or Docker mode for multi-device access.

That is a different starting point from the hosted billing services, and the consequences run through the whole design. There is no login to implement, so no password resets, no session handling and no third party seeing your client list. There is no subscription, so the project can be MIT licensed. And because the database is a file, the backup story is a file copy, which is also why the app ships full database backup and restore, JSON export and import, and per-document data snapshots for historical accuracy.

The snapshot feature is the one worth understanding. An invoice is a financial record, and if you edit the client name or the item price after issuing, the document on disk changes, and a legal dispute about what was billed six months ago becomes a question about your database history. Per-document snapshots mean each issued document keeps the data it was issued with, which is the difference between a record and a rendering.

The reference data is managed in the same spirit. Businesses, Clients, Banks, Items, Categories, Units and Currencies each have XLSX import and export, so a catalogue can be seeded from a spreadsheet and taken out again, rather than being typed in once through a form.

One codebase, three ways to run it

The application is an Electron plus React app with an optional Node.js webserver, using SQLite or PostgreSQL for storage, and the documentation describes three distinct ways to use that.

The first is the desktop application, with builds for Windows, Linux and macOS from the Releases page, backed by SQLite, with native receipt printing.

The second is the self-hosted Docker deployment, which is where the web mode becomes useful, since the browser client talks to the server over HTTP and the server owns the database, and that is the configuration for using the app from more than one device. The compose file in the repository is a two container setup, with a backend service and an nginx service in front of it, and the backend is described as internal-only, working only via nginx, with its ports commented out.

The third is the public browser demo, and the README is unusually careful about it. The demo runs on Render's free plan and may take a moment to wake up, and users are told to use fictional data only, because databases may be accessible to other visitors and can disappear without notice. It also notes that the demo is separate from the desktop and self-hosted installations, which store data on your own device or configured server.

That warning is the kind of thing that says more about the project than the feature list does. A demo whose database is shared and disposable is a demo, and a tool that lets you keep your own database is something else.

The development section confirms the shape of the codebase: an Electron plus React app with an optional Node.js webserver, SQLite or PostgreSQL for storage, with a running locally guide and a project structure and core stack section in the documentation.

The PDF is the product, and the layout builder is how you get there

The first capability listed is creating and managing invoices and quotes with live PDF preview, A4 and Letter formats, and a drag-and-drop Visual Layout Builder.

The live preview is what makes the layout builder usable. A template for an invoice is a set of positions and fields on a page, and a template for an invoice is a set of positions and fields on a page, and iterating on that by exporting a PDF and reopening it is slow enough that people give up and use whatever the default was. Rendering as you edit removes that loop.

The formats matter too, because invoice layout is not a free choice. A4 and Letter are not the same page size, and a layout that fits one will not fit the other, so supporting both means the builder has to understand a page, not just a box.

The financial model around the document is where an invoicing tool earns its keep. The list covers surcharges, discounts, shipping, inclusive or exclusive tax, partial payments, and document states. Partial payments in particular is the feature that separates a billing tool from a PDF generator, because a client paying in instalments means a document has a lifecycle, and document states are how that lifecycle is represented. Inclusive versus exclusive tax is the other one, since the two conventions change the arithmetic on every line and the difference between them is the kind of thing that has to be a configuration choice rather than a habit.

Printing is split by platform too, with native receipt printing on the desktop and browser print to PDF in the web and Docker mode, which is the honest split, since a browser cannot drive a thermal receipt printer without an extension.

UBL, Peppol and XRechnung are what lift it past PDF

One capability line is worth pulling out of the list on its own, because it changes who the tool is for. The application can export invoices as UBL 2.1, Peppol BIS Billing 3.0 or XRechnung XML for compliant e-invoicing.

A PDF is what a human reads. These three formats are what a tax authority or a business network reads. UBL 2.1 is the underlying invoice standard, Peppol BIS Billing 3.0 is the billing syntax used over the Peppol network, and XRechnung is the German standard that sits on top of UBL. Exporting them means the invoice can be ingested by a receiving system without a human retyping it, and it means the tax information in the document is structured rather than positioned.

The practical effect is that the tool stops being only for small businesses that email PDFs. A company that has to send machine readable invoices to a customer who requires them needs exactly this, and the layout builder and the tax settings are the same work either way.

The reason the README mentions the live PDF preview and the XML exports in the same breath is that they answer two audiences from one document. The PDF is what the client reads, the XML is what the customer's accounting system ingests, and the numbers in both come from the same fields, so there is no second place for a rounding difference to hide.

The 3.0.2 upgrade notice is the first thing to read

There is a boxed warning in the README about a one-time upgrade notice for version 3.0.2, and it is the most operationally important paragraph in the document.

Before upgrading, you are told to back up each existing database and to make sure it completed migrations through version 2.10.0. The reason is that version 3.0.2 initializes new databases from a consolidated schema and does not include the historical migration chain, so databases with incomplete migrations are not upgraded. The notice says this applies to Electron, manual, and web or Docker upgrades, so there is no route around it.

What happened underneath is a deliberate change of approach. The old scheme was a chain of incremental migrations that a new database would have to walk through one step at a time. The new scheme is a consolidated schema that new databases are created from directly, which is faster and simpler to reason about, at the price of the history. A database that has already reached 2.10.0 can be converted, and one that has not is left behind, which is why the instruction is to check the migration state first and to back up everything.

Two files in the repository root are worth noting next to that warning. There is a SECURITY.md and there is a LICENSE-DISCLAIMER.md, alongside the MIT LICENSE, which is an unusual combination for an application and suggests the author has thought about the liability questions an invoicing tool raises, since the app produces documents that carry legal weight in the jurisdiction it is used in.

Docker runs two containers, and the backend is not exposed

The self-hosting route is short. You need Git and Docker with the Compose plugin, then a clone and two commands:

bash
git clone https://github.com/piratuks/invoice-builder.git
cd invoice-builder
docker compose pull
docker compose up -d

Then you open http://localhost:3001 and create or connect a database.

The compose file explains the shape of the deployment. The backend service runs the pre-built image from GitHub Container Registry with a container name of backend, an extra_hosts entry mapping host.docker.internal to the host gateway, and the ports mapping left commented out, with the note that the backend is internal-only and works only via nginx. The environment is where the interesting configuration sits: SERVICE=backend, NODE_ENV=docker, DB_DIRECTORY=/app-data, the backend webserver port at 3000 with the host at 0.0.0.0, the frontend webserver URL pointing at http://localhost:3001, and MIGRATIONS_PATH pointing at the migrations directory in the volume. The PostgreSQL connection pool is configured through PG_POOL_MAX, PG_POOL_IDLE_TIMEOUT_MS, PG_POOL_CONNECTION_TIMEOUT_MS, PG_POOL_MAX_LIFETIME_SECONDS and PG_POOL_ALLOW_EXIT_ON_IDLE, and the webserver session lifecycle through WEBSERVER_CLEANUP_INTERVAL_MS and WEBSERVER_SESSION_TTL_MS.

One thing to know before you customise it. The compose file notes that VITE_API_URL is baked into the frontend at image build time, and that if you need a custom backend URL you should build the image yourself with docker build --build-arg VITE_API_URL=http://your-host:3000 -t invoice-builder and replace the image lines. The Dockerfile shows the same story from the other side, with a note that VITE_API_URL is no longer required for Docker because nginx proxies the API path internally, and it is kept only as an optional build argument for non-Docker deployments. The runtime image is node:20-alpine with nginx and gettext, the latter because envsubst is used to template the nginx configuration at startup.

One maintainer, an MIT licence and a sensible scope

The project is maintained by a single developer, and the README says so in the support section, pointing at GitHub Sponsors and Buy Me a Coffee rather than at a company behind it. That is a useful fact for an adopter, because it tells you what kind of project this is and what kind of support to expect.

The licence is the MIT License, and the repository carries the full set of community files, a code of conduct, a contributing guide, a security policy and a disclaimer. The tooling is a pnpm workspace with apps/ for the renderer, the server, the desktop shell and the website, packages/ for the shared contracts and core, an e2e/ directory with Playwright, Vitest for the unit tests, ESLint, Prettier and markdownlint, and a separate vite configuration for the migrations, which are treated as a build artefact that the container copies into the image.

On versions, the recent releases are 3.1.2 in October 2026, 3.0.4 at the end of September and 3.0.3 a day earlier, and the last push was on 2026-10-13. The line is young, and the concentration of releases in late September 2026 lines up with the 3.0 migration work described above.

The fit, then, is narrow and clear. A freelancer or a two person company that wants to issue invoices, keep the client list on its own disk, and send compliant e-invoicing when a customer demands it will find everything it needs here. A company with a shared finance function, approval workflows and a need for several people in one database will not, because the design assumes one file and one owner, and the 3.0.2 change made the database handling more opinionated rather than less.

Editorial conclusion

Invoice Builder suits a freelancer or small business that wants to issue invoices without a subscription, without an account and without its customer data leaving the machine, and that needs compliant e-invoicing formats rather than just a PDF. It does not suit a multi-user finance department that needs shared access, approval workflows and audit trails, since the data model is a single local database file by design. Verify first which storage you will use, and if you are upgrading an existing installation, read the 3.0.2 upgrade notice first, because that version does not carry the historical migration chain and a database that has not reached 2.10.0 will not be migrated by it.

Frequently asked questions

What is Invoice Builder and who is it for?

It is an offline-first, open-source invoicing and quoting application for freelancers and small businesses, with no accounts, no cloud and no subscriptions, so the data stays on your machine in a database file you own, with an optional self-hosted web or Docker mode for multi-device access.

How do I run Invoice Builder with Docker?

Install Git and Docker with the Compose plugin, clone the repository, then run docker compose pull and docker compose up -d, and open http://localhost:3001 to create or connect a database. The compose file runs a backend and an nginx service, and the backend port is not exposed directly.

What happens to my database when I upgrade to version 3.0.2?

Version 3.0.2 initializes new databases from a consolidated schema and does not include the historical migration chain, so a database that has not completed migrations through version 2.10.0 will not be upgraded. The README says to back up each existing database and check the migration state first, for Electron, manual and web or Docker upgrades alike.

Which e-invoicing formats does Invoice Builder export?

UBL 2.1, Peppol BIS Billing 3.0 and XRechnung XML, so invoices can be sent as compliant e-invoicing rather than only as a PDF.

Is the public demo of Invoice Builder safe for real data?

No. The README says the public Docker demo runs on Render's free plan, that databases may be accessible to other visitors and can disappear without notice, and that fictional data only should be used, with no real invoices, personal information or database credentials uploaded.

Official sources

  1. Issues
  2. License: MIT
  3. piratuks/invoice-builder on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/piratuks-invoice-builder.svg)](https://hysenlabs.com/projects/piratuks-invoice-builder)

Was this useful?