A per-event queue board for a repair cafe. Customers sign items in on a shared tablet; volunteers drag repairs through Queue, In progress and Done on a dashboard, then export the day's records as CSV. Zero npm dependencies: node:http plus JSON files on disk, no build step. Categories and house rules are set in config.json. Events are deleted 7 days after creation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
124 lines
4.3 KiB
Markdown
124 lines
4.3 KiB
Markdown
# Repair Cafe Kanban
|
|
|
|
A small queue board for a repair cafe. Volunteers create a board for one event,
|
|
customers sign their items in on a shared tablet, and volunteers drag repairs
|
|
through **Queue → In progress → Done**, then download the day's data as a CSV.
|
|
|
|
No database, no build step, no npm dependencies. Just Node.
|
|
|
|
## Running it
|
|
|
|
```sh
|
|
git clone ssh://git@git.autonomic.zone:2222/trav/repair-cafe-kanban.git
|
|
cd repair-cafe-kanban
|
|
node server.js
|
|
```
|
|
|
|
Then open <http://localhost:8080>. Node 18 or newer is all it needs — there is
|
|
nothing to install.
|
|
|
|
To use a different port:
|
|
|
|
```sh
|
|
PORT=9000 node server.js
|
|
```
|
|
|
|
By default it listens on all interfaces, so other people on the same network can
|
|
reach it at `http://<this-machine's-ip>:8080`. Set `HOST=127.0.0.1` to keep it on
|
|
this machine only.
|
|
|
|
## How it is used on the day
|
|
|
|
1. On the main page press **Create repair cafe kanban** and name the event.
|
|
Tick *randomise the address* if you want a hard-to-guess URL.
|
|
2. You land on the **sign-in form** at `/<event-name>`. Leave this open on a
|
|
tablet or laptop by the door — it clears itself after every submission.
|
|
3. Open the **dashboard** at `/<event-name>/dashboard` on the volunteers' laptop.
|
|
There is a link to it at the bottom of the sign-in form.
|
|
4. Drag cards between columns. Moving a card into *In progress* asks who is
|
|
repairing it; moving it into *Done* asks how it went. A card that reaches
|
|
*Done* without a result is outlined in red until someone fills it in.
|
|
5. Click any card's title to see and edit the full record, and to add notes.
|
|
6. Press **Download CSV** at the end of the day.
|
|
|
|
On a touch screen, drag a card by its **⠿** grip in the top right corner — that
|
|
leaves the rest of the card free for scrolling. You can also change a card's
|
|
status from the detail overlay without dragging at all.
|
|
|
|
## Configuration
|
|
|
|
Everything adjustable lives in `config.json`. Restart the server after editing it.
|
|
|
|
| Key | What it does |
|
|
| --- | --- |
|
|
| `port` | Port to listen on (the `PORT` environment variable wins). |
|
|
| `retentionDays` | Events are deleted this many days after creation. Set to `0` to keep them forever. |
|
|
| `categories` | The item categories offered on the sign-in form, each with the colour of its badge on the board. |
|
|
| `houseRules` | The text shown in the house rules popup. `\n` starts a new line. |
|
|
|
|
Adding a category is a config edit and a restart — no code change.
|
|
|
|
## Where the data lives
|
|
|
|
One JSON file per event in `data/`, named after its URL. They are plain text, so
|
|
you can read, back up, or delete them by hand. `data/expired.json` remembers the
|
|
names of events that have been auto-deleted, so their URLs can say "expired"
|
|
instead of "not found".
|
|
|
|
Each event's CSV is linked from its own dashboard. There is also a **combined CSV
|
|
of every event at `/export.csv`** — it is not linked from anywhere, since it is
|
|
for the person running the server rather than for volunteers on the day.
|
|
|
|
**Events are permanently deleted after `retentionDays` days** (7 by default),
|
|
on startup and once a day after that. Download the CSV before then if you want
|
|
to keep the data.
|
|
|
|
## Putting it on a real server
|
|
|
|
Copy the folder up and run `node server.js`. To keep it running, a systemd unit
|
|
is enough:
|
|
|
|
```ini
|
|
# /etc/systemd/system/repair-cafe.service
|
|
[Unit]
|
|
Description=Repair Cafe Kanban
|
|
After=network.target
|
|
|
|
[Service]
|
|
ExecStart=/usr/bin/node /srv/repair-cafe-kanban/server.js
|
|
WorkingDirectory=/srv/repair-cafe-kanban
|
|
Environment=HOST=127.0.0.1
|
|
Restart=always
|
|
User=www-data
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
Then put nginx in front of it for TLS and a real domain name:
|
|
|
|
```nginx
|
|
server {
|
|
server_name repair.example.org;
|
|
location / {
|
|
proxy_pass http://127.0.0.1:8080;
|
|
proxy_set_header Host $host;
|
|
}
|
|
}
|
|
```
|
|
|
|
There are no accounts and no passwords: anyone with a board's URL can view it,
|
|
sign items in, and move cards. That is fine for a public repair cafe, but do not
|
|
put anything on it you would not put on a whiteboard in the room.
|
|
|
|
## Layout
|
|
|
|
```
|
|
server.js HTTP server: routing, JSON API, CSV export, retention
|
|
config.json categories, house rules, port, retention
|
|
lib/store.js reading and writing events on disk
|
|
lib/csv.js CSV formatting
|
|
public/ the pages, one stylesheet, two scripts
|
|
data/ one JSON file per event (created on first run, not in git)
|
|
```
|