No description
- JavaScript 66.4%
- CSS 23.3%
- HTML 7.6%
- Shell 1.5%
- Dockerfile 1.2%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| config | ||
| lib | ||
| public | ||
| scripts | ||
| .dockerignore | ||
| .gitignore | ||
| CLAUDE.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| server.js | ||
| vitest.config.mjs | ||
Garage Days
A tiny self-hosted board for the Premature Apexers to post weekly availability for race car work sessions, and see which day(s) get the most hands.
No accounts, no passwords — pick your name from a fixed roster and mark your days. The app never auto-picks a day for you; it ranks all seven so a human still makes the call (someone might have the most votes on a day the one guy with the welder can't make it).
How it works
- A week runs Monday–Sunday.
- Each person marks themselves available/not per day, with an optional short note (e.g. "evenings only", "can bring the trailer").
- "Copy from last week" pulls your prior week's marks into the editor so you can tweak instead of starting blank — it doesn't save until you hit Save.
- The left panel ranks all seven days by headcount, highlighting the top day(s), and lists who's in (with their notes) for each.
Running it
Local test, no Docker
npm install
npm start
Then open http://localhost:3000
On your homelab (Docker + Traefik)
- Copy this whole folder onto your server (e.g. alongside your other compose stacks).
- Edit
docker-compose.yml:- Set the
networks:name to whatever network your Traefik is attached to (same pattern as your other services). - Set the
Host()rule to the subdomain you want, and match your existing certresolver name.
- Set the
docker compose up -d --build
Data persists in ./data/availability.json on the host via the bind mount,
so it survives container rebuants/restarts.
Managing the roster
Edit config/roster.json — it's just a JSON array of names:
["Kevin", "Josh", "Melanie", "Kyra", "Tom", "Aaron P"]
Restart the container after changing it (docker compose restart garage-days) — no rebuild needed since it's bind-mounted.
Notes / things you may want to change
- No auth at all beyond picking a name from a dropdown — anyone with the URL can mark availability as anyone else. Fine for a small trusted team on your own network; if you ever expose this outside your LAN/VPN, put it behind Authentik like your other services rather than relying on obscurity.
- Storage is a single JSON file, not a database. That's intentional for
a team this size — dead simple to back up (it's one file) and to inspect
by hand. If the group ever grows past a dozen or so people or you want
history/analytics, swap
lib/store.jsfor SQLite; the API layer doesn't need to change. - Notes are capped at 280 characters server-side.