Mark Ku's Blog
v1.0 in development · MIT

open-pos

A local-first restaurant POS. Ordering, checkout, printing and day-close all run on the machine in your shop, so a dead internet connection never stops you taking money, and your data stays yours.

Free · MITWorks offline · No subscription
open-pos · order screen
The order screen. Categories and items on the left, the current order and total on the right; net and tax are both shown, because those are the two numbers that have to match the invoice.

What it actually solves

Every one of these is a real cost small restaurants pay today, not a bullet on a feature list.

💸

Subscriptions and lock-in

Commercial POS systems often mean a three-year contract, a monthly fee, and no way to get your data out. open-pos costs nothing and your data is one SQLite file on your own disk.

📴

No internet, no sales

A cloud POS that loses its connection stops the business. Here the host sits in the shop; the network is only there to connect tablets and phones, not to take money.

🖨

Printers locked behind drivers

Vendor SDKs are frequently Windows-only DLLs with nothing for Linux. This opens a TCP connection on port 9100 and sends ESC/POS bytes, identical on every OS and with no driver to install.

🧮

Amounts off by one dollar

Money is always integer dollars. Tax is computed first by the statutory formula and the net sales figure derived by subtraction, so sales + tax = total always holds, which is exactly what the tax authority checks.

🔍

Books that do not reconcile

Every operation that touches money is written to an append-only audit log and journal. Who changed which order, when, and to what is answerable, including voiding an order after it was settled.

💾

Losing everything

Backups use SQLite's online consistent snapshot rather than copying files (which yields a torn database), and can be restored in place. If a backup has not run for too long, the health panel says so.

What works today

The goal for v1.0 is not a long feature list. It is: one computer and one printer are enough to open, and you never lose data.

👆

Touch ordering

Menu on the left, cart on the right, so the cashier's motion runs one way and never doubles back. Tiles are deliberately large, because at peak hours people are standing and poking with one finger.

💵

Checkout and change

Cash gets quick note buttons, and the change due stays on screen so it can be counted out. The amount is computed once, on the backend, so the screen and the database can never disagree.

🧾

Menu management

Categories, items and variants are edited in the app, never in the database. Price changes leave an audit trail, and order lines keep a snapshot of the name and price at the time of sale.

📶

Local network terminals

The same binary serves the local network. The upcoming kitchen display and QR ordering share this backend, while the cashier UI is deliberately not served over the LAN, so nobody on the shop Wi-Fi can load it.

What it looks like

The interface is dark on purpose: restaurants are brightly lit and this screen is on all day.

The order screen. Categories and items on the left, the current order and total on the right; net and tax are both shown, because those are the two numbers that have to match the invoice.
The order screen. Categories and items on the left, the current order and total on the right; net and tax are both shown, because those are the two numbers that have to match the invoice.
System status. The hardest thing about local software is the report that says it broke at lunch and now it works again, so version, data location and health checks live somewhere the shop can read them.
System status. The hardest thing about local software is the report that says it broke at lunch and now it works again, so version, data location and health checks live somewhere the shop can read them.

Four things to know first

Stating the limits up front is more honest than explaining them afterwards.

  1. 1

    There is no installer yet

    v1.0 is still in development, so for now you build from source. Installers will be published to GitHub Releases when v1.0 ships, and this page will be updated.

  2. 2

    Single machine, with a cold standby

    One host, one SQLite file, one writer, which is the same topology as the largest commercial POS in Taiwan. A second machine runs the same build but stays off; if the host dies you restore a backup on it and carry on, roughly ten minutes. There is no multi-master sync.

  3. 3

    The data must not sit on a network drive or a sync folder

    SQLite's WAL corrupts silently on SMB shares, and OneDrive or Dropbox will each copy the three database files independently. The app refuses to start on those paths and tells you where to put the data instead.

  4. 4

    Taiwan e-invoicing is not implemented

    It is scheduled for v1.4, starting with the government's free self-hosted Turnkey. Until then this system does not issue electronic invoices.

Technology choices

Every dependency is pure Rust, with no C libraries, so you clone it and the tests run. That is the first impression an open-source project gets to make.

Desktop shellTauri 2
BackendRust 2021 + sqlx
DatabaseSQLite (WAL · dual pool)
FrontendReact 18 + Vite 5 + Tailwind 3
PrintersESC/POS over TCP 9100
LicenseMIT

Install

Installers for three platforms will live here once v1.0 ships. Until then, build from source.

Windows

open-pos_x.y.z_x64-setup.exe

Available at v1.0. This is the primary target, because nearly every till in a Taiwanese restaurant runs Windows.

macOS

open-pos_x.y.z_universal.dmg

Available at v1.0. Fine for development and evaluation, rare on an actual counter.

Linux

open-pos_x.y.z_amd64.AppImage

Available at v1.0. There is also open-posd, a headless build that serves the local network only.

Until installers exist, the fastest way to try it is the build command below. Add --demo when you run it and you get a sample menu instead of having to type in products first.

Build from source

  1. 1

    Install Rust (stable) and Node.js 20 or newer. On Windows you also need the Microsoft C++ build tools.

  2. 2

    Clone the repository and run npm install for the frontend dependencies.

  3. 3

    npm run tauri dev starts the frontend and the Rust backend together and opens the development window.

  4. 4

    To just look around: cargo run --bin open-posd -- --demo creates a 38-item sample menu and serves the local network. Seeding is idempotent, so it will never pollute a menu you built yourself.

The first Rust build takes a few minutes; after that it is fast.

What comes next

Ordered by how much of the critical path is actually in my hands: e-invoicing waits on each shop's own government registration, and QR ordering waits on customers' phones.

  • v1.0Ordering, checkout, printing, shift close, backupIn development
  • v1.1Kitchen display systemPlanned
  • v1.2Richer reports and audit searchPlanned
  • v1.3Customer QR self-orderingPlanned
  • v1.4Taiwan e-invoicing (self-hosted Turnkey)Planned
  • v2.0PostgreSQL supportPlanned

License and boundaries

MIT, fully open, with no community-versus-commercial split. But read what it will not do: no cloud multi-store, no loyalty points, no card payment integration (which keeps it out of PCI scope), and no free customisation; hardware support depends on community reports. This is maintained by one person, and writing the boundary down first is what makes that sustainable.

Read the license

Your shop, your data

If you also think opening a restaurant should not start with signing a three-year contract, come read the code, report the printer model you own, or just open an issue.

open-pos: A local-first, open-source POS for restaurants - Mark Ku's Tech Notes