diff --git a/projects/sasch40/AGENTS.md b/projects/sasch40/AGENTS.md index 760ff14..c01f85f 100644 --- a/projects/sasch40/AGENTS.md +++ b/projects/sasch40/AGENTS.md @@ -108,6 +108,32 @@ This document records the foundational design decisions, their rationale ("Why") --- +### 8. Unhashed Asset Cache Invalidation (`nginx.conf`) +* **The Decision**: Unhashed static files (`/assets/scenes/*.jpg`, `/assets/characters/*/*.jpg`) MUST be served with `Cache-Control: "no-cache, no-store, must-revalidate"` and `Expires: -1`. +* **Why**: In mobile browsers (Safari iOS, Chrome Mobile), default caching headers (`expires 30d`) cause updated character portraits and scene backgrounds to remain stale for weeks on user devices. +* **The Rule**: In `nginx.conf`, static media matches `\.(png|jpg|jpeg|gif|ico|svg|webp|mp3|wav|ogg)$` with `no-cache, no-store, must-revalidate`. Bundled JS/CSS matches `\.(js|css)$` with `public, immutable` for 1 year. + +--- + +### 9. Easter Egg Invisibility Pattern (`TavernView.vue`) +* **The Decision**: Secret hotspots (e.g. `secret-tap-hotspot` in the Schankraum) must be 100% invisible initially. +* **Why**: An Easter egg marked with a glowing button or text badge is not a secret; it invites immediate trivial clicking. +* **The Rule**: + * The button must render with transparent background, no border, no outline, no box shadow, no hover change, and no tooltip (`:title="undefined"`). + * Only upon the user's first click does it reveal the gold key icon, play a celebratory fanfare, unlock the Easter egg in the game store (+500 points), and transition to the secret room. + +--- + +### 10. LocalStorage Persistence & Clean Game Reset (`gameStore.ts`) +* **The Decision**: Game state automatically synchronizes to `localStorage` (`sasch40_game_save_v1`) on every mutation and is cleanly wiped when clicking *„🔄 NOCHMAL SPIELEN“*. +* **Why**: Mobile users frequently refresh or switch apps to snap photos. Without persistence, a browser reload resets their progress back to Act I. +* **The Rule**: + * `useGameStore` automatically initializes from `localStorage` if valid data exists. + * `store.$subscribe` writes the state to `localStorage` whenever any value changes. + * `resetGame()` clears `localStorage.removeItem(...)`, sets all stats to zero, and returns to the Prequel Intro. + +--- + ## 🛠️ Build, Test & Deployment Workflow ### Fast Docker Packaging (Local ARM64 Compile)