docs(plan): Sma Grodorna midsummer theme implementation plan (+ spec: WebAudio jingle)

9-task plan with complete code for the frog/maypole theme: scoped CSS
overlay, useMidsummer provider, dancing maypole, crown/frog dots, banner +
confetti, frog-hop easter egg, WebAudio jingle. Spec updated to synthesize
the jingle (no mp3 asset / licensing).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-19 09:22:54 +02:00
parent b3753d1ab0
commit e803c35af9
2 changed files with 910 additions and 15 deletions

View file

@ -92,17 +92,18 @@ future change. The scoped overlay avoids duplication.
a palette), but uses the same frog assets.
### 5. Jingle — `hooks/useMidsummerSound.ts`
- Plays a short *Små grodorna* clip **once** (not looping — a looping jingle
- Plays the *Små grodorna* melody **once** (not looping — a looping jingle
on a left-open dashboard is grating).
- Asset: `static/midsummer/sma-grodorna.mp3` (a short royalty-free / public
clip sourced during implementation; documented in the plan).
- Browser reality: unmuted audio cannot autoplay before a user gesture, so
the clip fires on the **first user interaction (any click) or the moment
the 🐸/🔊 control is used** — never silently on page-paint. A 🔇 control
stops/disables it; preference persisted (`soundOn`).
- Single module-level `Audio`/`AudioContext`, reused — no per-play leak (the
audit flagged per-notification `AudioContext` leaks elsewhere; don't repeat
that pattern).
- **No audio asset**: the melody is synthesized with WebAudio oscillators
from the public-domain folk tune (note frequencies in code). This removes
any licensing question and ships nothing for the service worker to cache.
- Browser reality: WebAudio cannot start before a user gesture, so the tune
fires on the **first user interaction (any click) or the moment the 🐸/🔊
control is used** — never silently on page-paint. A 🔇 control disables
it; preference persisted (`soundOn`, default on).
- Single module-level `AudioContext`, reused and `resume()`d on gesture — no
per-play allocation (the audit flagged per-notification `AudioContext`
leaks elsewhere; don't repeat that pattern).
## File plan
@ -114,7 +115,7 @@ New:
- `frontend/src/components/midsummer/MidsummerBanner.tsx`
- `frontend/src/components/midsummer/FrogToggle.tsx`
- `frontend/src/components/midsummer/confetti.ts` (tiny helper)
- `static/midsummer/sma-grodorna.mp3` (audio asset)
- (no audio asset — jingle is WebAudio-synthesized)
Edited:
- `App.tsx` — wrap in `MidsummerProvider`; import `midsummer.css`.
@ -136,10 +137,9 @@ Edited:
## Deploy
`bash deploy-frontend.sh && git add static/ && git commit && git push`, then
`git pull` on the host (bind-mounted `static/`). No container restart. The
new audio file lives under `static/midsummer/` so it ships with the static
bundle; confirm the service worker (`sw.js`) either ignores it or caches it
intentionally.
`git pull` on the host (bind-mounted `static/`). No container restart. No new
runtime assets (jingle is synthesized), so the service worker needs no
changes.
## Testing / verification