diff --git a/CLAUDE.md b/CLAUDE.md index c355f6a..24f7760 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,18 +4,65 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Overview -A single-file, zero-dependency Elden Ring death counter (`Elden Ring Counter.html`). Open directly in any browser — no build step, no server needed. +Elden Ring-themed death counter for Schmendrizzle's Twitch stream. Originally a single standalone HTML file; now a Deno server with real-time multi-client WebSocket sync. Compiles to a self-contained Windows `.exe` via `deno compile`. + +## File Structure + +``` +EldenRingCounter/ +├── server.ts # Deno HTTP + WebSocket server +├── desktop.html # Main counter page with YOU DIED overlay +├── mobile.html # Touch-optimized control page +├── obs.html # Transparent browser source for OBS +├── Elden Ring Counter.html # Original standalone file (localStorage), kept for reference +└── .gitea/workflows/ + └── release.yml # Builds and publishes Windows .exe on tag push +``` ## Architecture -Everything lives in one HTML file with three sections: +**`server.ts`** — Single `Deno.serve({ port: 8080 })` handling: +- `GET /` → `desktop.html` +- `GET /mobile` → `mobile.html` +- `GET /obs` → `obs.html` +- `GET /ws` (WebSocket upgrade) → real-time sync -- **CSS** (lines 8–339): Elden Ring-themed dark UI using CSS custom properties (`--gold`, `--bg0`, etc.). The "YOU DIED" overlay is CSS-animation-driven via the `.show` class. -- **HTML** (lines 342–376): Static markup. `#roman` and `#arabic` are the display targets; `#overlay` holds the death animation. -- **JS** (lines 378–468): Vanilla JS. `deaths` is the single state variable, persisted to `localStorage` under key `elden_deathcounter_value`. `render()` syncs state → DOM → storage. `add(delta)` is the only way to mutate count; it triggers the overlay on increment. +State: single `deaths` variable in memory, broadcast to all clients on every mutation. Persisted to `counter.json` in cwd after each change; loaded on startup. + +**WebSocket protocol:** +- Client → server: `{"action": "increment" | "decrement" | "reset"}` +- Server → all clients: `{"count": 42}` + +**`desktop.html`** — Full counter UI. WebSocket client with auto-reconnect. YOU DIED overlay triggers when received count is higher than previous. Keyboard controls: `+`/`=`/`↑` increment, `-`/`_`/`↓` decrement, `R` reset. + +**`mobile.html`** — Large touch buttons only. Same WebSocket client, no overlay. + +**`obs.html`** — Fixed-size (`440×160px`) display box with transparent background. No controls, no status indicator. ## Key constraints - Roman numeral display is capped at 3999 (`clamp(0, 3999)`); 0 displays as `—`. - The overlay animation restarts cleanly via a forced reflow (`void overlay.offsetWidth`) before re-adding `.show`. -- UI language is German (`lang="de"`); string literals like `"Tode:"` and `"Gespeichert lokal ✓"` are in German. +- UI language is German (`lang="de"`); string literals like `"Tode:"` are in German. +- `obs.html` has a fixed size so the layout never jumps as numbers grow. + +## Commands + +```bash +# Dev +deno run --allow-net --allow-read --allow-write server.ts + +# Build Windows .exe +deno compile \ + --allow-net --allow-read --allow-write \ + --include desktop.html \ + --include mobile.html \ + --include obs.html \ + --target x86_64-pc-windows-msvc \ + --output elden-counter.exe \ + server.ts +``` + +## CI + +`.gitea/workflows/release.yml` triggers on `v*` tags. Builds the Windows `.exe` and publishes it as a release asset via `softprops/action-gh-release`.