---
phase: 01-grundger-st-tippmechanik
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - 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
autonomous: true
requirements:
  - FNDN-01
  - FNDN-02
  - FNDN-03
  - FNDN-04
  - PLSH-06

must_haves:
  truths:
    - "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"
  artifacts:
    - path: "package.json"
      provides: "Project dependencies and scripts"
      contains: "vite"
    - path: "src/types.ts"
      provides: "All shared TypeScript interfaces"
      exports: ["Progress", "ForestElement", "CompanionAssets", "Level", "Settings", "StyleReference"]
    - path: "src/storage/db.ts"
      provides: "IndexedDB wrapper with 5 stores"
      exports: ["openDB", "getProgress", "saveProgress", "getSettings", "saveSettings"]
    - path: "src/styles/main.css"
      provides: "CSS palette and typography"
      contains: "--bg-cream"
  key_links:
    - from: "src/storage/db.ts"
      to: "src/types.ts"
      via: "imports Progress, Settings, ForestElement etc."
      pattern: "import.*from.*types"
    - from: "src/main.ts"
      to: "src/storage/db.ts"
      via: "initializes DB on app start"
      pattern: "openDB"
---

<objective>
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.
</objective>

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

<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)
</context>

<tasks>

<task type="auto">
  <name>Task 1: Vite project scaffold + project structure + CSS design system</name>
  <files>
    package.json, tsconfig.json, vite.config.ts, biome.json, index.html,
    .gitignore, src/main.ts, src/styles/main.css, public/config.example.json
  </files>
  <read_first>
    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
  </read_first>
  <action>
    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 (h1–h3): 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').
  </action>
  <verify>
    <automated>cd /home/dev/workspace/zauberwald && npm run dev -- --strictPort 2>&1 &amp; sleep 3 && curl -s http://localhost:5173 | grep -q "Zauberwald" || curl -s http://localhost:5173 | grep -q "screen-welcome" && kill %1 && echo "PASS"</automated>
  </verify>
  <acceptance_criteria>
    - 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 `<section` tags with ids screen-welcome, screen-forest, screen-lesson, screen-reward, screen-parent
    - index.html contains `class="screen screen--active"` on screen-welcome
    - src/styles/main.css contains `--bg-cream: #FFF8F0` and `--finger-l-pinky: #E8B4C8` and `--finger-thumb: #D4CFC8`
    - src/styles/main.css contains `font-family:` with `Quicksand` and `Nunito`
    - Directories exist: src/game, src/forest, src/companion, src/api, src/storage, src/ui, src/assets/companions
    - public/config.example.json contains `geminiApiKey` and `geminiModel`
    - `npm run dev` starts without errors
  </acceptance_criteria>
  <done>Vite project runs, all directories exist per spec section 13, CSS custom properties match spec section 7.2, index.html has 5 screen sections</done>
</task>

<task type="auto" tdd="true">
  <name>Task 2: TypeScript interfaces + IndexedDB wrapper</name>
  <files>
    src/types.ts, src/storage/db.ts, src/storage/db.test.ts
  </files>
  <read_first>
    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)
  </read_first>
  <behavior>
    - 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)
  </behavior>
  <action>
    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
  </action>
  <verify>
    <automated>cd /home/dev/workspace/zauberwald && npx vitest run src/storage/db.test.ts</automated>
  </verify>
  <acceptance_criteria>
    - 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
  </acceptance_criteria>
  <done>All TypeScript interfaces exported, IndexedDB wrapper creates 5 stores, read/write for progress and settings works, all tests pass</done>
</task>

</tasks>

<verification>
- `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
</verification>

<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>

<output>
After completion, create `.planning/phases/01-grundger-st-tippmechanik/01-01-SUMMARY.md`
</output>
