Parents get a real push notification when a kid checks off a task (false->true transitions only, fire-and-forget, degrades gracefully with no VAPID keys configured). Dashboard is a fully installable iOS/Android PWA; each child's kiosk link gets its own dynamic per-token manifest so "Add to Home Screen" opens straight into their board in standalone mode. Kiosk view is reworked for tablets: safe-area-aware full-bleed layout, the whole task row is now tappable (previously only the 24px checkbox was, well under Apple's touch-target minimum), and app icons are generated by a small dependency-free PNG encoder (no image tooling available in this environment). Push requires real HTTPS (iOS Safari won't allow it otherwise) - README and UNRAID.md cover VAPID setup and the HTTPS prerequisite.
6.8 KiB
Running on Unraid
This app has no native/compiled dependencies (it uses Node's built-in
node:sqlite), so it builds and runs on Unraid's stock Docker exactly like
anywhere else. docker-compose.unraid.yml builds straight from the Gitea
repo — Docker/BuildKit clones it itself as part of the build, so you don't
need to check out the source on the array at all, and there's no deploy
key involved in this path.
1. Make the repo readable over HTTP
The compose file's build.context is a Git URL
(https://git.oservr.com/ort/KCal.git#main) — Docker fetches that itself
at build time. This is a read-only clone, same as any anonymous git clone, so the repo needs to allow anonymous HTTP read access:
In Gitea: repo → Settings → Visibility → Public (save).
No token, no key, no extra permission grant — public visibility is sufficient for a read-only clone.
2. Create the appdata data folder
mkdir -p /mnt/user/appdata/kids-calendar
This is where the SQLite database will live — the compose file bind-mounts it in, instead of using a Docker-managed named volume, so it shows up normally in Unraid's Docker tab and gets picked up by appdata backup plugins (e.g. CA Backup/Restore) like any other app's data.
3. Deploy
Via Compose Manager Plus (recommended)
-
Docker → Compose → Add Stack, name it
kids-calendar. -
In the Compose tab, paste:
services: kids-calendar: build: context: https://git.oservr.com/ort/KCal.git#main dockerfile: Dockerfile container_name: kids-calendar ports: - "3007:3007" volumes: - /mnt/user/appdata/kids-calendar:/app/data environment: - SESSION_SECRET=${SESSION_SECRET:?set a long random value in .env} - COOKIE_SECURE=${COOKIE_SECURE:-false} - DISABLE_PUBLIC_SIGNUP=${DISABLE_PUBLIC_SIGNUP:-false} - VAPID_PUBLIC_KEY=${VAPID_PUBLIC_KEY:-} - VAPID_PRIVATE_KEY=${VAPID_PRIVATE_KEY:-} - VAPID_SUBJECT=${VAPID_SUBJECT:-} restart: unless-stopped -
In the ENV tab, set:
SESSION_SECRET=<output of: openssl rand -hex 32> COOKIE_SECURE=false DISABLE_PUBLIC_SIGNUP=falseLeave the three
VAPID_*vars unset for now unless you're setting up push notifications and already have real HTTPS in front of this stack — see "Push notifications" below. -
Compose Up. First run builds the image (a minute or so — it's cloning the repo and running
npm install), then the container starts on port 3007.
Via terminal (no plugin needed)
You only need the one compose file and a .env next to it — not a full
checkout, since Docker fetches the source itself:
mkdir -p /mnt/user/appdata/kids-calendar-src
cd /mnt/user/appdata/kids-calendar-src
curl -o docker-compose.unraid.yml \
https://git.oservr.com/ort/KCal/raw/branch/main/docker-compose.unraid.yml
cat > .env <<EOF
SESSION_SECRET=$(openssl rand -hex 32)
COOKIE_SECURE=false
DISABLE_PUBLIC_SIGNUP=false
VAPID_PUBLIC_KEY=
VAPID_PRIVATE_KEY=
VAPID_SUBJECT=
EOF
docker compose -f docker-compose.unraid.yml up -d --build
4. Use it
Open http://<unraid-ip>:3007/signup.html, create the first parent
account, invite your spouse, add your kids, build out calendars, and grab
each child's kiosk link from the dashboard for their tablet.
Updating
Docker re-clones the repo's main branch fresh every time you build —
there's no separate git pull step. Just re-run the build:
- Compose Manager Plus: right-click the stack → Update & Rebuild (or Build & Up if stopped).
- Terminal:
docker compose -f docker-compose.unraid.yml up -d --buildfrom the folder in the terminal steps above.
Either way, your data in /mnt/user/appdata/kids-calendar is untouched.
Prefer not to make the repo public?
If you'd rather keep KCal private, the alternative is authenticating the
git-context fetch with a Gitea access token instead of flipping visibility
— generate a read-only token in Gitea, then reference it via compose
variable substitution so it isn't hardcoded in the file itself:
build:
context: https://${GITEA_USER}:${GITEA_TOKEN}@git.oservr.com/ort/KCal.git#main
with GITEA_USER/GITEA_TOKEN set in the stack's ENV tab (or .env for
the terminal path) instead of SESSION_SECRET's neighbors above. Ask if
you want this wired up instead.
Reverse proxy / access from outside your LAN
If you're exposing this beyond your home network (e.g. via Swag or Nginx Proxy Manager, both common on Unraid) with a real HTTPS certificate:
- Point the proxy at
http://<unraid-ip>:3007internally. - Set
COOKIE_SECURE=true(ENV tab, or.envfor the terminal path) and rebuild — otherwise login cookies won't be marked secure and some browsers/proxies will refuse to send them back over HTTPS. - Once your household(s) exist, consider setting
DISABLE_PUBLIC_SIGNUP=trueso/signup.htmlstops accepting new households.
This same real-HTTPS setup is also the prerequisite for push notifications below — Swag and Nginx Proxy Manager both produce real Let's Encrypt certs given a domain, so if you've already followed this section, you qualify.
Push notifications
Optional: parents get a real push notification (not just the silent polling-based update) when a kid checks off a task on the kiosk.
Needs the real HTTPS from the section above already in place — a
self-signed cert doesn't satisfy iOS, and plain http://<unraid-ip>:3007
won't work for this feature at all, even though the rest of the app is
fine over plain HTTP on your LAN.
Once HTTPS is confirmed working through your reverse proxy:
- Generate a VAPID keypair — from the Unraid terminal:
docker run --rm node:22-alpine npx web-push generate-vapid-keys. - Set
VAPID_PUBLIC_KEY,VAPID_PRIVATE_KEY,VAPID_SUBJECT(mailto:you@example.com) in the stack's ENV tab (or.envfor the terminal path), then rebuild (Update & Rebuild, ordocker compose -f docker-compose.unraid.yml up -d --build). - On the dashboard (loaded through your HTTPS domain, not the bare
http://<unraid-ip>:3007), each parent clicks "Enable notifications on this device" — per-device, so repeat on every phone/computer.
On iPhone/iPad, Safari only allows push for web apps added to the Home Screen — tap Share → Add to Home Screen on the dashboard first, then open the app icon and enable notifications from there. The dashboard explains this in place if needed. Regenerating the VAPID keypair invalidates every existing subscription, so treat it as a one-time setup step.
Backups
Since data lives at /mnt/user/appdata/kids-calendar (a plain file, the
SQLite database), it's covered by whatever you already use to back up
/mnt/user/appdata — no special-casing needed.