Files
Zauberwald/.planning/phases/01-grundger-st-tippmechanik/01-01-PLAN.md
T

15 KiB
Raw Blame History

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
01-grundger-st-tippmechanik 01 execute 1
package.json
tsconfig.json
vite.config.ts
biome.json
index.html
.gitignore
src/main.ts
src/types.ts
src/storage/db.ts
src/styles/main.css
public/config.example.json
true
FNDN-01
FNDN-02
FNDN-03
FNDN-04
PLSH-06
truths artifacts key_links
npm run dev startet Vite auf 0.0.0.0:5173 ohne Fehler
Alle Verzeichnisse aus Spec Abschnitt 13 existieren
TypeScript-Interfaces sind exportiert und typisiert
IndexedDB oeffnet mit 5 Stores und schliesst nicht bei reload
CSS Custom Properties fuer alle Farben und Fonts sind definiert
path provides contains
package.json Project dependencies and scripts vite
path provides exports
src/types.ts All shared TypeScript interfaces
Progress
ForestElement
CompanionAssets
Level
Settings
StyleReference
path provides exports
src/storage/db.ts IndexedDB wrapper with 5 stores
openDB
getProgress
saveProgress
getSettings
saveSettings
path provides contains
src/styles/main.css CSS palette and typography --bg-cream
from to via pattern
src/storage/db.ts src/types.ts imports Progress, Settings, ForestElement etc. import.*from.*types
from to via pattern
src/main.ts src/storage/db.ts initializes DB on app start openDB
Scaffold the complete Vite project, define all TypeScript interfaces, create the IndexedDB wrapper, and establish the CSS design system.

Purpose: Every subsequent plan depends on the project existing, types being defined, storage being available, and styles being set. Output: A runnable Vite dev server with types, IndexedDB, and CSS custom properties — no visible UI yet beyond a blank styled page.

<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/01-grundger-st-tippmechanik/01-CONTEXT.md @SPEC.md (sections 6.2, 6.3, 7.2, 13) Task 1: Vite project scaffold + project structure + CSS design system package.json, tsconfig.json, vite.config.ts, biome.json, index.html, .gitignore, src/main.ts, src/styles/main.css, public/config.example.json SPEC.md (section 13 for project structure, section 6.2 for tech stack, section 7.2 for CSS palette) .planning/phases/01-grundger-st-tippmechanik/01-CONTEXT.md 1. Initialize Vite project with vanilla-ts template: `npm create vite@latest . -- --template vanilla-ts` (or manually create files if directory not empty).
2. Install dependencies:
   - `npm install` (vite, typescript)
   - `npm install -D vitest @biomejs/biome`

3. Configure vite.config.ts (per D-01, spec section 0):
   ```typescript
   import { defineConfig } from 'vite'
   export default defineConfig({
     server: { host: '0.0.0.0', port: 5173 },
     preview: { host: '0.0.0.0', port: 4173 }
   })
   ```

4. Configure tsconfig.json: `"strict": true`, target ES2020, module ESNext, moduleResolution bundler.

5. Configure biome.json: enable formatter and linter, indent with tabs, line width 100.

6. Configure package.json scripts:
   ```json
   {
     "dev": "vite --host",
     "build": "tsc && vite build",
     "preview": "vite preview --host --port 4173",
     "test": "vitest run",
     "test:watch": "vitest",
     "lint": "biome check .",
     "lint:fix": "biome check --write ."
   }
   ```

7. Create .gitignore with: node_modules, dist, public/config.json, *.local

8. Create ALL directories from spec section 13:
   - src/game/, src/forest/, src/companion/, src/api/, src/storage/, src/ui/, src/styles/
   - src/assets/companions/fee-lila/, src/assets/companions/einhorn-stella/,
     src/assets/companions/fuchs-finn/, src/assets/companions/eule-elsa/
   - src/assets/style-reference/, src/assets/fallback-images/
   - scripts/
   - public/
   Place empty .gitkeep in asset directories that have no files yet.

9. Create public/config.example.json:
   ```json
   {
     "geminiApiKey": "YOUR_API_KEY_HERE",
     "geminiModel": "gemini-2.5-flash",
     "imageModel": "gemini-3.1-flash-image-preview"
   }
   ```

10. Create index.html with:
    - DOCTYPE html, lang="de"
    - Google Fonts link: Quicksand (400, 600, 700) + Nunito (400, 600)
    - Link to src/styles/main.css (via Vite)
    - 5 screen sections per D-01: `<section id="screen-welcome" class="screen">`,
      `<section id="screen-forest" class="screen">`,
      `<section id="screen-lesson" class="screen">`,
      `<section id="screen-reward" class="screen">`,
      `<section id="screen-parent" class="screen">`
    - Only screen-welcome gets class `screen--active` initially
    - `<script type="module" src="/src/main.ts"></script>`

11. Create src/styles/main.css with ALL CSS custom properties from spec section 7.2:
    ```css
    :root {
      --bg-cream: #FFF8F0;
      --bg-forest: #E8F5E4;
      --text-dark: #3D3225;
      --text-warm: #5C4A3A;
      --text-light: #8B7D6B;
      --accent-green: #6DB87D;
      --accent-gold: #E8B84B;
      --accent-pink: #E88BAE;
      --accent-purple: #9B7DC4;
      --accent-blue: #7DB8D4;
      --finger-l-pinky: #E8B4C8;
      --finger-l-ring: #C4A8D4;
      --finger-l-mid: #A8C4E0;
      --finger-l-index: #A8D8B8;
      --finger-r-index: #D4D8A8;
      --finger-r-mid: #E0C4A8;
      --finger-r-ring: #D4A8A8;
      --finger-r-pinky: #C8B4E8;
      --finger-thumb: #D4CFC8;
    }
    ```
    Body: font-family 'Nunito', sans-serif; background var(--bg-cream); color var(--text-dark); min font-size 16px; margin 0; padding 0.
    Headings (h1h3): font-family 'Quicksand', sans-serif.
    Screen base: `.screen { display: none; opacity: 0; transition: opacity 0.3s ease; }` and `.screen--active { display: flex; flex-direction: column; align-items: center; opacity: 1; min-height: 100vh; }`.

12. Create src/main.ts as minimal entry: import './styles/main.css', console.log('Zauberwald loaded').
cd /home/dev/workspace/zauberwald && npm run dev -- --strictPort 2>&1 & sleep 3 && curl -s http://localhost:5173 | grep -q "Zauberwald" || curl -s http://localhost:5173 | grep -q "screen-welcome" && kill %1 && echo "PASS" - package.json contains "vite" in devDependencies and scripts "dev", "build", "preview", "test", "lint" - vite.config.ts contains `host: '0.0.0.0'` and `port: 5173` - tsconfig.json contains `"strict": true` - biome.json exists and contains `"formatter"` and `"linter"` - .gitignore contains `public/config.json` and `node_modules` - index.html contains 5 ` Vite project runs, all directories exist per spec section 13, CSS custom properties match spec section 7.2, index.html has 5 screen sections Task 2: TypeScript interfaces + IndexedDB wrapper src/types.ts, src/storage/db.ts, src/storage/db.test.ts SPEC.md (section 6.3 for IndexedDB stores, section 4.1 for level structure, section 5.2 for companion types) src/types.ts (after Task 1 creates it — may be empty placeholder) - Test: openDB() resolves to an IDBDatabase with 5 object store names - Test: saveProgress({ currentLevel: 1, ... }) then getProgress() returns same data - Test: saveSettings({ audioEnabled: true, ... }) then getSettings() returns same data - Test: getProgress() on empty DB returns null (not crash) - Test: getSettings() on empty DB returns null (not crash) 1. Create src/types.ts with ALL interfaces per spec section 6.3 (per FNDN-03):
```typescript
// Companion types
export type CompanionType = 'fee' | 'einhorn' | 'fuchs' | 'eule';
export type KeyboardLayout = 'de' | 'ch';

// Level status for the forest map
export type LevelStatus = 'locked' | 'current' | 'completed';

// Progress store
export interface Progress {
  id: 1; // singleton row
  currentLevel: number;
  completedLevels: number[];
  totalSessions: number;
  sessionDates: string[]; // ISO date strings (days only)
  selectedCharacter: CompanionType;
  selectedLayout: KeyboardLayout;
}

// Companion assets store
export interface CompanionAssets {
  characterType: CompanionType;
  characterSheet: Blob;
  avatarImage: Blob;
  generatedAt: string; // ISO date
}

// Style reference store
export interface StyleReference {
  id: 1; // singleton
  imageBlob: Blob;
  generatedAt: string;
}

// Forest element store
export interface ForestElement {
  id?: number; // auto-increment
  levelCompleted: number;
  imageBlob: Blob;
  imagePrompt: string;
  description: string;
  companionText: string;
  position: { x: number; y: number };
  createdAt: string;
}

// Settings store
export interface Settings {
  id: 1; // singleton
  audioEnabled: boolean;
  apiKey: string;
}

// Level definition (used in game/levels.ts)
export interface Level {
  level: number;
  newKeys: string[];
  allKeys: string[]; // cumulative keys up to this level
  fingerMap: Record<string, string>; // key -> CSS variable name for finger color
}

// Typing exercise state
export interface TypingExerciseState {
  currentLetterIndex: number;
  letters: string[];
  intervalMs: number;
  correctStreak: number;
  totalCorrect: number;
  totalErrors: number;
}

// Screen names
export type ScreenName = 'welcome' | 'forest' | 'lesson' | 'reward' | 'parent';
```

2. Create src/storage/db.ts — IndexedDB wrapper (per D-02, all 5 stores created, only progress + settings fully used):

```typescript
import type { Progress, Settings, ForestElement, CompanionAssets, StyleReference } from '../types';

const DB_NAME = 'zauberwald';
const DB_VERSION = 1;

export function openDB(): Promise<IDBDatabase> {
  return new Promise((resolve, reject) => {
    const request = indexedDB.open(DB_NAME, DB_VERSION);
    request.onupgradeneeded = (event) => {
      const db = (event.target as IDBOpenDBRequest).result;
      if (!db.objectStoreNames.contains('progress')) {
        db.createObjectStore('progress', { keyPath: 'id' });
      }
      if (!db.objectStoreNames.contains('companionAssets')) {
        db.createObjectStore('companionAssets', { keyPath: 'characterType' });
      }
      if (!db.objectStoreNames.contains('styleReference')) {
        db.createObjectStore('styleReference', { keyPath: 'id' });
      }
      if (!db.objectStoreNames.contains('forestElements')) {
        db.createObjectStore('forestElements', { keyPath: 'id', autoIncrement: true });
      }
      if (!db.objectStoreNames.contains('settings')) {
        db.createObjectStore('settings', { keyPath: 'id' });
      }
    };
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
  });
}

export async function getProgress(db: IDBDatabase): Promise<Progress | null> { ... }
export async function saveProgress(db: IDBDatabase, progress: Progress): Promise<void> { ... }
export async function getSettings(db: IDBDatabase): Promise<Settings | null> { ... }
export async function saveSettings(db: IDBDatabase, settings: Settings): Promise<void> { ... }
```

Each get/save function wraps IDB transaction in a Promise. Use 'readonly' for gets, 'readwrite' for saves. Store name matches interface.

3. Create src/storage/db.test.ts using vitest with fake-indexeddb:
   - `npm install -D fake-indexeddb`
   - Import `import 'fake-indexeddb/auto'` at top of test
   - Test all behaviors listed above
cd /home/dev/workspace/zauberwald && npx vitest run src/storage/db.test.ts - src/types.ts exports: Progress, ForestElement, CompanionAssets, Settings, StyleReference, Level, CompanionType, KeyboardLayout, LevelStatus, ScreenName, TypingExerciseState - src/types.ts contains `type CompanionType = 'fee' | 'einhorn' | 'fuchs' | 'eule'` - src/types.ts contains `type KeyboardLayout = 'de' | 'ch'` - src/storage/db.ts exports: openDB, getProgress, saveProgress, getSettings, saveSettings - src/storage/db.ts contains `const DB_NAME = 'zauberwald'` - src/storage/db.ts contains all 5 store names: 'progress', 'companionAssets', 'styleReference', 'forestElements', 'settings' - src/storage/db.test.ts exists and `npx vitest run src/storage/db.test.ts` exits 0 - package.json contains `fake-indexeddb` in devDependencies All TypeScript interfaces exported, IndexedDB wrapper creates 5 stores, read/write for progress and settings works, all tests pass - `npm run dev` starts without errors on port 5173 - `npx vitest run` passes all DB tests - `npx biome check .` shows no errors (or only warnings) - All directories from spec section 13 exist - index.html has 5 screen sections - CSS custom properties match spec section 7.2 exactly

<success_criteria>

  • Vite dev server accessible at 0.0.0.0:5173
  • TypeScript compiles without errors in strict mode
  • IndexedDB wrapper tested and working with 5 stores
  • CSS design system complete with all palette colors and typography
  • Project structure matches spec section 13 </success_criteria>
After completion, create `.planning/phases/01-grundger-st-tippmechanik/01-01-SUMMARY.md`