docs: logo, security warning, emoji headings
- embed favicon.svg as a logo in the README - add a prominent "no security — trusted networks only" callout - sprinkle emoji through README/TODO/PLAN/NOTES headings; fix NOTES typo
This commit is contained in:
parent
cca3077b7a
commit
3bfb853d0b
4 changed files with 49 additions and 28 deletions
2
NOTES.md
2
NOTES.md
|
|
@ -1,4 +1,4 @@
|
|||
## Decription
|
||||
## 📝 Description
|
||||
|
||||
Calculator / tracker for festival
|
||||
|
||||
|
|
|
|||
20
PLAN.md
20
PLAN.md
|
|
@ -1,9 +1,9 @@
|
|||
# wutzcalc — Implementation Plan
|
||||
# 🗺️ wutzcalc — Implementation Plan
|
||||
|
||||
Festival drink-sale tracker. 3 bars, ~10k attendees over 1 week, old iPads (iOS 12),
|
||||
local network only, central linux server.
|
||||
|
||||
## Decisions (locked for v1)
|
||||
## 🔒 Decisions (locked for v1)
|
||||
|
||||
- **Stack:** Preact + Vite (client), Node + Fastify (server), SQLite (better-sqlite3).
|
||||
- **Deployment:** single Node process serves API + static client + opens one `.db` file.
|
||||
|
|
@ -17,7 +17,7 @@ local network only, central linux server.
|
|||
- **Undo:** only before confirming, fully local (edit the current cart). No undo of confirmed transactions in v1.
|
||||
- **iOS 12 target:** Vite build with `legacy` plugin → ES2017 + polyfills. No CSS features past Safari 12.
|
||||
|
||||
## Architecture
|
||||
## 🏗️ Architecture
|
||||
|
||||
```
|
||||
┌──────────────┐ HTTP/JSON ┌────────────────────────┐
|
||||
|
|
@ -33,7 +33,7 @@ local network only, central linux server.
|
|||
- Single port, single binary-ish (`node server.js`). Systemd unit for autostart.
|
||||
- SQLite WAL mode for concurrent reads from dashboard while writes happen.
|
||||
|
||||
## Data model (SQLite)
|
||||
## 🗄️ Data model (SQLite)
|
||||
|
||||
```
|
||||
bars(id, name, pfand_cents)
|
||||
|
|
@ -56,7 +56,7 @@ settings(key, value) -- admin password hash etc.
|
|||
- `client_uuid` makes confirm idempotent against double-tap / retry.
|
||||
- Returns stored as separate line items with `is_return=1` and negative contribution to total.
|
||||
|
||||
## API surface
|
||||
## 🔌 API surface
|
||||
|
||||
- `GET /api/config?bar=<id>` → bar + its drinks + pfand value.
|
||||
- `GET /api/bars` → list of bars (for tablet first-run picker).
|
||||
|
|
@ -69,7 +69,7 @@ settings(key, value) -- admin password hash etc.
|
|||
|
||||
Server is the source of truth for prices — tablet sends drink IDs + qty only.
|
||||
|
||||
## Client (tablet) UX
|
||||
## 📱 Client (tablet) UX
|
||||
|
||||
- **First run:** pick which bar this tablet is. Stored in `localStorage`.
|
||||
- **Main screen:** grid of large buttons, one per drink served at this bar.
|
||||
|
|
@ -80,7 +80,7 @@ Server is the source of truth for prices — tablet sends drink IDs + qty only.
|
|||
- All cart edits are local until confirm — undo = remove from cart.
|
||||
- Tap targets ≥ 64px, no hover states, no small text.
|
||||
|
||||
## Backoffice (v1)
|
||||
## 🏢 Backoffice (v1)
|
||||
|
||||
- `/admin` login (single password from env `ADMIN_PASSWORD`).
|
||||
- Pages:
|
||||
|
|
@ -89,7 +89,7 @@ Server is the source of truth for prices — tablet sends drink IDs + qty only.
|
|||
3. **Stats**: totals per bar, top drinks, crew freebie count/value.
|
||||
4. **Export**: CSV of transactions and transaction_items.
|
||||
|
||||
## Repo layout
|
||||
## 📁 Repo layout
|
||||
|
||||
```
|
||||
wutzcalc/
|
||||
|
|
@ -119,7 +119,7 @@ wutzcalc/
|
|||
|
||||
(Admin can be a second entry in the same Vite build, or server-rendered HTML — leaning toward second Vite entry for consistency.)
|
||||
|
||||
## Implementation order
|
||||
## 🔢 Implementation order
|
||||
|
||||
1. Repo scaffold: pnpm workspaces, Fastify server skeleton, Vite client skeleton, shared types package.
|
||||
2. SQLite schema + migrations + seed (3 bars, a few drinks).
|
||||
|
|
@ -131,7 +131,7 @@ wutzcalc/
|
|||
8. Legacy build verification on an iOS 12 Safari (or BrowserStack equivalent).
|
||||
9. Systemd unit + README deploy instructions + backup cron note.
|
||||
|
||||
## Open risks
|
||||
## ⚠️ Open risks
|
||||
|
||||
- iOS 12 Safari is the main constraint — need to verify Preact + legacy plugin output actually runs there early (after step 1, before building more).
|
||||
- Local network reliability: if the WiFi at the venue is flaky, online-only model bites. Tracked in `TODO.md` (offline-capable client).
|
||||
|
|
|
|||
45
README.md
45
README.md
|
|
@ -1,4 +1,6 @@
|
|||
# wutzcalc
|
||||
# wutzcalc 🍺
|
||||
|
||||
<img src="client/public/favicon.svg" alt="wutzcalc logo" width="120" align="right" />
|
||||
|
||||
> ## ⚠️ AI-generated code
|
||||
>
|
||||
|
|
@ -8,23 +10,42 @@
|
|||
> events), read the code yourself, test the edge cases that matter to you, and
|
||||
> assume there are bugs. Use at your own risk.
|
||||
|
||||
Festival drink-sale tracker. See [PLAN.md](PLAN.md) for architecture, [NOTES.md](NOTES.md)
|
||||
> ## 🔓 No security — trusted networks only
|
||||
>
|
||||
> **This app has essentially no protection. Assume anyone who can reach it can
|
||||
> read and write everything.**
|
||||
>
|
||||
> - 🚫 The tablet UI (`/`, `/api`) has **no authentication** — anyone on the
|
||||
> network can record sales, return Pfand, or reset a cart.
|
||||
> - 🔑 The backoffice (`/admin`) is gated by a **single shared password** in
|
||||
> plaintext (`ADMIN_PASSWORD`), sent and stored as-is — no per-user accounts,
|
||||
> no rate limiting, no audit log.
|
||||
> - 🌐 There is **no HTTPS** built in — traffic (including the admin password) is
|
||||
> plaintext unless you put it behind your own TLS-terminating reverse proxy.
|
||||
> - 🧱 No CSRF tokens (only a `SameSite=Lax` cookie) and no input hardening
|
||||
> beyond basic request validation.
|
||||
>
|
||||
> Run it only on a **trusted, isolated LAN** (e.g. the bar's own Wi-Fi/VLAN),
|
||||
> never exposed to the public internet. See [TODO.md](TODO.md) for the auth and
|
||||
> hardening work deferred from v1.
|
||||
|
||||
🎪 Festival drink-sale tracker. See [PLAN.md](PLAN.md) for architecture, [NOTES.md](NOTES.md)
|
||||
for the original requirements, and [TODO.md](TODO.md) for deferred work.
|
||||
|
||||
Source: <https://git.berlin.ccc.de/vinzenz/wutzcalc>
|
||||
🔗 Source: <https://git.berlin.ccc.de/vinzenz/wutzcalc>
|
||||
|
||||
## Toolchain setup
|
||||
## 🔧 Toolchain setup
|
||||
|
||||
Requires Node.js 20+ and pnpm 9+. Native SQLite bindings install from prebuilt
|
||||
binaries on x86_64 / arm64 — no compiler needed for most setups.
|
||||
|
||||
### Nix (Linux / macOS)
|
||||
### ❄️ Nix (Linux / macOS)
|
||||
|
||||
```sh
|
||||
nix develop # node 20, pnpm, sqlite, build deps
|
||||
```
|
||||
|
||||
### Debian / Ubuntu
|
||||
### 🐧 Debian / Ubuntu
|
||||
|
||||
```sh
|
||||
# Node 20 from NodeSource
|
||||
|
|
@ -36,7 +57,7 @@ sudo corepack enable # provides pnpm
|
|||
sudo apt install -y build-essential python3
|
||||
```
|
||||
|
||||
### Fedora
|
||||
### 🎩 Fedora
|
||||
|
||||
```sh
|
||||
# Node 20 + pnpm (corepack ships with the nodejs package)
|
||||
|
|
@ -47,7 +68,7 @@ sudo corepack enable # provides pnpm
|
|||
sudo dnf install -y gcc-c++ make python3
|
||||
```
|
||||
|
||||
### Windows
|
||||
### 🪟 Windows
|
||||
|
||||
Install Node.js 20 LTS via the official MSI from <https://nodejs.org> (this
|
||||
also installs the optional "Tools for Native Modules"). Then in PowerShell:
|
||||
|
|
@ -59,7 +80,7 @@ corepack enable # provides pnpm
|
|||
Use PowerShell to set env vars on the same line, e.g.
|
||||
`$env:ADMIN_PASSWORD="changeme"; pnpm dev:server`.
|
||||
|
||||
## Dev
|
||||
## 🛠️ Dev
|
||||
|
||||
```sh
|
||||
pnpm install
|
||||
|
|
@ -70,7 +91,7 @@ pnpm dev:client # http://localhost:5173 (proxies /api
|
|||
Open `http://localhost:5173/` for the tablet UI and
|
||||
`http://localhost:5173/admin.html` for the backoffice.
|
||||
|
||||
## Production build
|
||||
## 📦 Production build
|
||||
|
||||
```sh
|
||||
pnpm install
|
||||
|
|
@ -81,7 +102,7 @@ ADMIN_PASSWORD=... DB_PATH=/var/lib/wutzcalc/wutz.db node server/dist/index.js
|
|||
Single Node process serves the API, both client entries (`/` tablet,
|
||||
`/admin` backoffice), and writes to one SQLite file.
|
||||
|
||||
## Run as a systemd service
|
||||
## 🚀 Run as a systemd service
|
||||
|
||||
On Fedora, the `Makefile` automates everything below — from a fresh checkout, as root:
|
||||
|
||||
|
|
@ -127,7 +148,7 @@ Confirm `ExecStart` matches your Node path (`command -v node`) — it defaults t
|
|||
`/usr/bin/node`. The unit creates `/var/lib/wutzcalc` via `StateDirectory`, so
|
||||
the service user owns the database directory automatically.
|
||||
|
||||
## Env vars
|
||||
## ⚙️ Env vars
|
||||
|
||||
- `PORT` (default `3000`)
|
||||
- `HOST` (default `0.0.0.0`)
|
||||
|
|
|
|||
10
TODO.md
10
TODO.md
|
|
@ -1,22 +1,22 @@
|
|||
# TODO
|
||||
# 📋 TODO
|
||||
|
||||
Longer-term items deferred from v1.
|
||||
|
||||
## Auth & access control
|
||||
## 🔐 Auth & access control
|
||||
- Add short PIN per bar/tablet on first launch (currently no client auth).
|
||||
- Harden `/admin` beyond a single shared password (per-user, audit log).
|
||||
- Decide whether bartender identity should be tracked per transaction.
|
||||
|
||||
## Features
|
||||
## ✨ Features
|
||||
- Custom price entry (free-form numpad amount as a line item, and/or per-drink price override).
|
||||
- Per-bar price overrides on top of the shared drink catalog (v1 is shared catalog + per-bar selection only).
|
||||
- Crew identification (which crew member took the freebie) beyond a flat "by crew" flag.
|
||||
- Backoffice: live transaction feed, per-drink charts, void/edit confirmed transactions.
|
||||
- Offline-capable client with sync queue (v1 is online-only).
|
||||
|
||||
## UX / scaling
|
||||
## 📱 UX / scaling
|
||||
- Check what happens on the tablet UI when a bar has *many* drinks — current no-scroll grid divides the available height equally across rows, so tiles will shrink. Verify legibility/tap target size with 15–25 drinks; may need pagination, scrolling, or smaller-grid mode.
|
||||
|
||||
## Ops
|
||||
## 🔧 Ops
|
||||
- Backup strategy for the SQLite file (cron + copy off-box).
|
||||
- Health check endpoint + simple status page on the tablet if server unreachable.
|
||||
|
|
|
|||
Loading…
Reference in a new issue