Minimal fridge POS with a React + Vite frontend and a Node 24 + oRPC backend. Transactions are stored in a local SQLite file (no external database required).
- Install dependencies
pnpm install- Configure frontend environment
cp apps/frontend/.env.example apps/frontend/.env.localUpdate the values in apps/frontend/.env.local if needed.
- Start frontend + backend
pnpm dev:allTo enable the simple admin panel export endpoint, set a backend password first:
export ADMIN_PANEL_PASSWORD="change-me"Frontend runs on Vite, backend runs on oRPC. Runtime data is stored under apps/backend/data/ (including transactions.sqlite). Product catalog lives in apps/backend/catalog/products.json (kept in git, not in the mounted runtime data dir).
This repo includes production-oriented Dockerfiles with faster rebuild characteristics:
infra/frontend.Dockerfile- single container serving built frontend via
vite preview - minimal moving parts (no extra web server in the container)
- single container serving built frontend via
infra/backend.Dockerfile- single-stage runtime build (keeps pnpm workspace resolution simple)
- cached dependency install
/healthzendpoint for container health checks
For local compose:
pnpm docker:upFor Dokploy, use:
- compose file:
infra/docker-compose.dokploy.yml - required env vars:
ADMIN_PANEL_PASSWORDVITE_IBANVITE_IBAN_NAME
- optional env vars:
VITE_API_URL(defaults to/rpcfor same-domain routing)VITE_APP_VERSION(defaults todev; set to commit SHA or build timestamp)
For GitHub Actions deploy verification, also configure:
- repository variable:
DEPLOY_CHECK_URL(public URL to the live frontend, e.g.https://cashier.ko-lab.space)
- repository secret:
DOKPLOY_WEBHOOK_URL
The Dokploy compose is intentionally minimal for Dokploy: no Traefik labels, no host port bindings, and uses external dokploy-network + a named volume (backend-data) for SQLite persistence.
The frontend checks /version.json every 60 seconds.
- It compares the server version against
VITE_APP_VERSIONbaked into the running app. - If versions differ, it reloads automatically only when safe:
- POS mode
- cart view
- no selected items
- no active transaction/loading
- If not safe yet, it shows a small notice and refreshes once the page becomes idle.
In Docker builds, infra/frontend.Dockerfile writes dist/version.json from VITE_APP_VERSION.
Set VITE_APP_VERSION in Dokploy/CI to a unique value per deploy (e.g. git SHA).
The frontend version is also exposed in two places for quick verification:
- Footer text in the app:
Frontend commit: <version> - HTML meta tag on
/:<meta name="app-commit" content="<version>">
You can deploy this stack either from the Dokploy UI or via Dokploy CLI.
-
Push this repository branch to GitHub/Git provider.
-
In Dokploy, create a new Compose application.
-
Select this repository and branch.
-
Set compose file path to:
infra/docker-compose.dokploy.yml -
Add environment variables (from
infra/.env.example):ADMIN_PANEL_PASSWORDVITE_IBANVITE_IBAN_NAME- optional:
VITE_API_URL(default is/rpcfor same-domain routing)
-
Expose routes on the same domain (
cashier.ko-lab.be) with path-based routing:- Frontend service: host
cashier.ko-lab.be, path/, port4173 - Backend RPC: host
cashier.ko-lab.be, path/rpc, port4000 - Optional backend health: host
cashier.ko-lab.be, path/healthz, port4000
- Frontend service: host
-
Deploy.
After deploy, verify:
- Frontend loads at
https://cashier.ko-lab.be - RPC works at
https://cashier.ko-lab.be/rpc - Health endpoint works at
https://cashier.ko-lab.be/healthz(if routed)
If you manage Dokploy through its CLI, use the same compose file and env values:
# From repo root
cp infra/.env.example infra/.env
# edit infra/.env with real values
# Then deploy using your Dokploy CLI workflow,
# referencing infra/docker-compose.dokploy.ymlNotes for CLI usage:
- Keep
infra/.envout of git (contains secrets). - Re-deploy on each new commit/branch update.
- If you split frontend/backend into separate Dokploy apps later, set
VITE_API_URLto the backend public/rpcURL.
Workflow: .github/workflows/dokploy-webhook.yml
- Triggers on push to
master - Calls Dokploy via
DOKPLOY_WEBHOOK_URL - Sends both branch ref and pushed SHA in the webhook payload
- Waits until the live page at
DEPLOY_CHECK_URLcontains the pushed commit in:<meta name="app-commit" content="${GITHUB_SHA}">
The job retries with polling and fails on timeout, so a green workflow means the live page has updated to the expected frontend commit.
pnpm test:allOr run just one side:
pnpm test:fe
pnpm test:be