tngoman/Store-POS: a single-till or LAN point of sale built on Electron, Express and sql.js
Modern Electron Point of Sale — React till, Express + SQLite API, LAN multi-terminal, catalog/photos, and Windows installer.
At a glance
- What is it?
- Store POS is a desktop point of sale for one register or a network of tills, with a React till, an Express API over a SQLite database, and three operating modes that let a back office PC serve the network while other machines run as terminals. It is a version 2 rewrite of an earlier Electron app, and the choices in it, a WebAssembly SQLite instead of a native one, a preload bridge instead of node integration, and an explicit security checklist, tell you what kind of project it is.
- Who is it for?
- Adopt Store POS if you run a single shop on Windows and want a till, a catalogue and an invoice flow in one offline capable desktop application, especially if you need several tills on one LAN sharing a catalogue. Do not adopt it for a multi site business or an internet facing ordering system, since the server mode is explicitly documented as a trusted LAN arrangement with a firewall in front for wider exposure.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 3 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 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A till, a catalogue and a ledger on one desktop
Store POS is a modern desktop point of sale for a single register or a LAN of networked tills, and version 2.0 rebuilds the original Electron app on what the README calls a secure, maintainable stack.
The feature list is organised the way a shop is organised. The till does barcode scanning and search, with Enter to add, category filter chips, product tiles with photos, price and stock status, a cart with quantity controls, discount and tax, a customer picker with quick add, hold and resume for sales, a cash payment pad, card payment, a change and still due display and a printable receipt.
The catalogue holds products and categories, tracks inventory, has a photo picker with local upload and Pexels download to a local media library, a seed demo of sample products and customers, and multi-select bulk delete.
Sales history is filtered by date range, cashier, till and status, paid or held. Customers and team means customer records and staff accounts with permission flags for products, categories, sales, users and settings. Settings covers store identity, currency symbol and optional tax, operating mode, till number, a Pexels API key for catalog photos, and a demo data seed or a full catalog and sales wipe.
Two details date the project to a specific market. The cash payment pad has South African note shortcuts from R10 to R200, and the seed demo catalog is described as SA-style products and customers.
The stack, and the one substitution that was deliberate
The quick start is two commands, and the stack behind it is short and every line is a decision.
npm install
npm run devThe tech stack table is short and every line is a decision.
| Layer | Technology | |--------|------------| | Desktop shell | Electron 33 (contextIsolation, preload bridge, no `nodeIntegration`) | | UI | React 18 + TypeScript + Vite 6 | | API | Express | | Auth | JWT + bcrypt | | Database | SQLite via `sql.js` (no native build toolchain required) | | Installer | electron-builder (Windows NSIS) |
The database line is the interesting one, and the troubleshooting section explains why. The project uses sql.js deliberately to avoid better-sqlite3 compile issues, which means there is no native module to build and no compiler to install on the machine that runs the till.
For a point of sale that has to install cleanly on a shop's own PC, that trade is right. A native SQLite binding would be faster, and the cost of the WebAssembly build is paid on every query, but the alternative is a checkout that will not start because somebody's Node version has a different prebuilt binary. The same reasoning explains the security notes, since the renderer has no Node integration and privileged actions go through the preload bridge, so a compromised page in the renderer cannot reach the file system.
The dependencies are correspondingly few and mostly pure JavaScript: bcryptjs rather than bcrypt, jsonwebtoken, express, cors, multer for uploads, react and react-dom, and sql.js.
Three modes, and how a LAN of tills is set up
The operating mode is set under Settings and Register, and the app has to be restarted after a change. There are three modes and the difference between them is where the data lives.
Standalone runs a local API and SQLite on the same PC, bound to `127.0.0.1:8001`. Network Server runs the same database and API but bound to `0.0.0.0:8001` so other tills can connect. Network Terminal has no local database at all and connects to the server IP you enter.
The typical LAN setup is three steps. On the back office or main PC you set Network Server and note the LAN IP shown in Settings. On each till PC you set Network Terminal, point the Server IP at that address and assign a unique till number. Then you restart both apps.
That is a sensible design for a small shop, and it is also the design with the sharpest edges, since the server holds the entire catalogue and the sales history and is reachable by anything on the network. The security notes say to prefer Network Server only on a trusted LAN and to put a firewall in front for wider exposure, and the troubleshooting table lists a terminal that cannot reach the server as the first item, with the checks being the same LAN, the correct server IP, the mode set to Network Server and port 8001 open.
The API, the bearer token and the demo endpoints
The local API base in standalone mode is `http://127.0.0.1:8001/api`, and the overview lists one route per area.
Auth is `POST /users/login`. The catalogue is `/inventory/products` and `/categories/all`. Sales are `POST /new`, `GET /by-date` and `GET /on-hold`. Media is `/media/library` and `/media/pexels/search`. And the demo area is `POST /demo/seed` and `POST /demo/clear`.
Authenticated routes expect an `Authorization: Bearer <token>` header, which is the standard JWT flow the auth layer implies.
The demo endpoints are worth understanding, because they are a data management tool rather than a toy. Seed demo adds sample categories, products and customers if those names do not already exist, so it is safe to run on a shop with real data. Bulk delete in the catalogue removes the selected products. Bulk delete catalog and sales in Settings removes products, categories, sales history and customers except Walk-in, and keeps staff and settings, which is the right scope for a reset that does not force you to rebuild your user accounts.
One troubleshooting entry explains a behaviour that will otherwise look like a bug. Sales history can appear empty because the date filters use local time and the default range is from the start of the month to the end of today, so a shop that opened this morning sees a narrow window.
The installer, and why sql.js is unpacked
Packaging is handled by electron-builder with an NSIS target for x64 on Windows, and the output is a conventional installer at `release/Store POS Setup 2.0.0.exe`. The npm scripts cover the whole cycle: `npm run dev` runs Vite and Electron together, using concurrently with a kill flag and a wait-on for the dev server, `npm run build` produces the production UI into `dist/`, `npm start` runs Electron against an existing build and config, `npm run smoke` runs the API and LAN smoke tests, and `npm run dist` builds the UI and creates the Windows installer.
The build configuration has a few details that matter in the field. The NSIS options set `oneClick` to false and allow the installation directory to be changed, with desktop and start menu shortcuts. And `signAndEditExecutable` is false, which means the shipped executable is neither signed nor edited, so Windows SmartScreen will treat it as an unsigned binary.
There is one entry that is easy to miss and that explains an installation problem if it goes wrong. The `asarUnpack` list contains the sql.js module, because the WebAssembly asset it carries cannot be loaded from inside the asar archive, so it has to be unpacked to disk. If that list is lost during a rebuild, the application installs and then fails to find its database engine.
The data and uploads live under the Electron userData directory rather than in the repository, and the README notes that uninstalling may leave a database folder behind depending on the operating system's settings, which is the sort of thing that matters when a shop replaces a machine.
Where this is the wrong choice
The first wrong case is a multi site business. Every mode assumes one server and the tills on one LAN, and the server holds one catalogue and one sales history, with no notion of a second location in the documentation.
The second is an internet facing shop. The server mode binds to `0.0.0.0:8001` with JWT and bcrypt on the API and no TLS in the documentation, which is a fine design for a shop's own network and a poor one for the public internet.
The third is a business that needs accounting. The billing features are quotes, invoices, expenses, tax and a payment pad, which is a till's billing, not a ledger, and the word accounting in the project description should not be read as a general ledger.
The fourth is a team that wants a maintained product. The repository has no GitHub releases, the last push was on 2026-10-13, and the licence is not one GitHub could classify, so there is no stated redistribution or reuse story. It is maintained for store use, and the README says to look to the repository history for the contributors to the original app and to the rewrite.
On the state of the project, the package is `store-pos` at version 2.0.0, marked private, with the author field left as a placeholder and the application id set to a generic one, so the defaults would need changing before any distribution outside the shop it was written for. The security section is the part to read first regardless, and it is short and specific, change the default admin credentials before real use, prefer Network Server only on a trusted LAN, and treat the Pexels key stored in settings on the server machine as a secret.
Editorial conclusion
Adopt Store POS if you run a single shop on Windows and want a till, a catalogue and an invoice flow in one offline capable desktop application, especially if you need several tills on one LAN sharing a catalogue. Do not adopt it for a multi site business or an internet facing ordering system, since the server mode is explicitly documented as a trusted LAN arrangement with a firewall in front for wider exposure. Verify first that you can change the default admin credentials before the till sees a customer, that the Pexels key stored in settings on the server machine is treated as a secret, and that port 8001 is reachable from the terminals, because the troubleshooting table lists exactly that as the usual reason a terminal cannot reach the server.
Frequently asked questions
How do I install and run Store POS?
With Node.js 18 or newer, 20 LTS recommended, run `npm install` and then `npm run dev`. The default login is `admin` with the password `admin`, and the documentation says to change that password after the first login in a production deployment. The packaged Windows installer is produced with `npm run dist`.
How do I set up several tills on a LAN?
On the main PC choose the Network Server mode under Settings and Register, note the LAN IP it shows, then on each till PC choose Network Terminal, set the Server IP to that address and give each till a unique number, and restart both apps. The server holds the database and listens on port 8001.
Why does Store POS use sql.js instead of a native SQLite binding?
The project uses sql.js deliberately to avoid better-sqlite3 compile issues, which means there is no native build toolchain required on the machine running the till. The consequence is that the sql.js module is listed in the asarUnpack configuration, because its WebAssembly asset cannot be loaded from inside the packaged archive.
What are the security notes for Store POS?
The renderer has no Node integration and privileged actions go through the preload bridge, you should change the default admin credentials before real use, the Network Server mode should only be used on a trusted LAN with a firewall in front for wider exposure, and the Pexels key stored in settings on the server machine should be treated like a secret.
How do I reset the catalog and sales data in Store POS?
From Catalog you can bulk delete the selected products, and from Settings under Demo data there is a bulk delete catalog and sales option that removes products, categories, sales history and customers except Walk-in while keeping staff and settings. Seeding the demo catalog is safe on a shop with real data, because it only adds sample entries whose names do not already exist.
Official sources
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.
[](https://hysenlabs.com/projects/tngoman-store-pos)Was this useful?