calendar: consume the scout-calendar feed instead of local events.json

Events now come from EVENTS_FEED_URL (the scout-calendar container,
which serves Radicale mike/site73 as JSON). The last good copy is
cached to /data/events-cache.json and served whenever the feed is down
or empty; 'Nothing on the books' remains the cold-start floor only.
The round-trip test proved the feed reproduces all 32 rows of
app/events.json byte-identically, so nothing visible changes today.

Removes app/events.json, the first-boot seed copy, and the local load
path; README calendar section rewritten; compose gains EVENTS_FEED_URL
from the Portainer stack env.
This commit is contained in:
Claude
2026-08-29 11:33:43 -04:00
parent 7d2c241126
commit 27f1a2104b
4 changed files with 58 additions and 253 deletions
+7 -10
View File
@@ -6,16 +6,16 @@ Replaces the `scoutpoc` proof of concept (claude-workspace/stacks/scoutpoc).
## Updating the calendar (the part you'll actually do)
All dates on the site (home "Next up," both program pages, the Calendar page) render from **one JSON file**, read fresh on every request:
All dates on the site (home "Next up," both program pages, the Calendar page) come from the **scout-calendar feed** (claude-workspace/stacks/scout-calendar), which serves the Radicale collection `mike/site73` as JSON:
```
/srv/scout-website/data/events.json ← the LIVE file. Edit this.
app/events.json ← seed only; copied to /data on first boot.
EVENTS_FEED_URL ← Portainer stack env; http://scout-calendar:8000/events.json
/data/events-cache.json ← last good copy, served automatically whenever the feed is down
```
Edit the live file on the host (or ask Claude), save, refresh the site. **No rebuild, no redeploy.**
Edit the calendar in any CalDAV client pointed at Radicale (or ask Claude), and the site follows within ~5 minutes. **No file edits, no rebuild, no redeploy.** The public ICS families can subscribe to is https://calendar.greenlanescouts73.org/calendar.ics.
Event format (one object per event):
Event fields the feed emits (one object per event):
```json
{"date": "2026-10-17", "end": "2026-10-18", "time": "from 4:00 PM",
@@ -26,15 +26,12 @@ Event format (one object per event):
- `date` required (YYYY-MM-DD). `end` only for multi-day events.
- `unit`: `"pack"`, `"troop"`, or `"both"` (default pack). Drives the Pack/Troop calendar filter and each page's "Next up."
- `badge`: optional shouty label (`FALL OPEN HOUSE`, `OVERNIGHT`, `THE BIG ONE`).
- Past events are hidden from "Next up" automatically; keep or prune them in the file, your call.
- TeamSnap (team 8198615) stays the source of truth; this file is the public snapshot.
To change the **seed** for future rebuilds too, edit `app/events.json` here in Gitea and redeploy the stack.
- Past events are hidden from "Next up" automatically; the Calendar page shows the whole program year.
- TeamSnap (team 8198615) stays the source of truth for registered families; Radicale `mike/site73` is the source for this public site.
## Layout
- `app/app.py` — FastAPI app, all five pages server-rendered (Home, /cubs, /troop, /calendar?unit=, /join). `/contact` 301s to `/join`.
- `app/events.json` — calendar seed (see above).
- `docker-compose.yml` — Portainer Repository stack definition (port 8131).
- Images: **not in the repo.** Bind-mounted read-only from `/srv/scout-website-assets/img`. Source photos live on the NAS (`Scouting-Recruitment-Images`, `scouting-comms/pack-73/assets/social`); web-sized copies in `Scouting-Recruitment-Images/_web`.