# Session-Handoff 2026-04-17 ## Stand nach autonomer Session **MVP komplett** — alle sechs geplanten Phasen umgesetzt. **Tests:** 84 passed / 15 Dateien (Unit + Integration). `npm run check` grün (0 Fehler, 0 Warnings). **Docker-Image gebaut und gegengetestet** (Container läuft, Health 200, DB initialisiert sich in leerem Volume). **End-to-End verifiziert** gegen echte Quellen: - Chefkoch-URL (Schupfnudeln) importiert → persistiert mit Zutaten, Schritten, Bild (241 KB) - SearXNG-Container gestartet → Web-Suche „bolognese" lieferte Chefkoch-Treffer - Preview → Save → zweiter Import liefert `{duplicate: true}` - Rating, Favorit, Heute-gekocht, Kommentar alles persistiert und korrekt gelesen - Backup-ZIP enthält DB + beide Bilder (444 KB) ## Bedienung ### Entwicklung ```bash npm run dev # http://localhost:5173 docker compose up -d searxng # Suche via http://localhost:8888 npm test # vitest npm run check # svelte-check ``` ### Produktions-Build (lokal testen) ```bash npm run build DATABASE_PATH=./data/kochwas.db IMAGE_DIR=./data/images node build/index.js # läuft auf :3000 ``` ### Produktion (Docker) ```bash docker build -t kochwas:latest . docker compose -f docker-compose.prod.yml up -d ``` ## Was ist gebaut ### Server-Seite - **DB:** SQLite mit FTS5, Migrationen (`./migrations/*.sql`) werden von Vite gebündelt und beim ersten DB-Zugriff angewendet. Auto-mkdir für `data/` und `data/images/`. - **Module:** `parsers/` (iso8601, ingredient, json-ld-recipe), `recipes/` (scaler + repository + actions + importer + search-local), `domains/` (repository + whitelist), `profiles/`, `images/image-downloader`, `search/searxng`, `backup/export`, `http`. - **Routes:** `/api/health`, `/api/profiles`, `/api/profiles/[id]`, `/api/domains`, `/api/domains/[id]`, `/api/recipes/search`, `/api/recipes/search/web`, `/api/recipes/preview`, `/api/recipes/import`, `/api/recipes/[id]`, `/api/recipes/[id]/rating`, `/api/recipes/[id]/favorite`, `/api/recipes/[id]/cooked`, `/api/recipes/[id]/comments`, `/api/admin/backup`, `/images/[filename]`. ### Client-Seite (Svelte 5 Runes) - **Layout** mit Profil-Chip und Zahnrad zu Admin. - **Startseite** mit großer Google-artiger Suche + „Zuletzt hinzugefügt"-Karten. - **Suchseite** (`/search?q=`) lokale FTS5-Treffer und Button „Im Internet weitersuchen". - **Web-Suchseite** (`/search/web?q=`) SearXNG-Treffer mit Domain-Pill und Snippet. - **Preview-Seite** (`/preview?url=`) rendert Rezept in RecipeView mit „Vorschau"-Banner und Speichern-Button. - **Rezeptseite** (`/recipes/[id]`) mit Tabs Zutaten/Zubereitung, Portionen-Slider, Sternbewertung, Favorit, Heute-gekocht, Drucken, Umbenennen, Löschen, Kommentare, Kochjournal, Wake-Lock. - **Druckseite** (`/recipes/[id]/print`) eigener minimalistischer Layout, 2-Spalten-Zutaten, automatischer `window.print()`. - **Admin-Bereich** (`/admin/domains`, `/admin/profiles`, `/admin/backup`) mit Tab-Navigation. - **Profile-Store** persistiert `activeProfileId` in LocalStorage. - **PWA:** `manifest.webmanifest`, SVG-Icon, Service-Worker (App-Shell + Bilder offline, Document-Pages network-first mit Cache-Fallback). ### Betrieb - Entwicklungs-Compose (`docker-compose.yml`) — nur SearXNG für lokale Entwicklung. - Produktions-Compose (`docker-compose.prod.yml`) — app + searxng mit Volume `./data`. - Multi-Stage Alpine-Dockerfile mit `better-sqlite3` Native-Build. - Healthcheck auf `/api/health`. ## Offene Punkte / bewusst weggelassen - **Backup-Restore UI** — Export funktioniert, Import aus ZIP ist noch manueller DB-Copy. `yauzl` ist bereits als Dependency da, Phase 5b kann das in 10 Minuten nachziehen. - **PNG-Icons für iOS** — aktuell nur SVG im Manifest. Android/Chrome akzeptieren das, iOS-Standalone sieht die SVG aber nicht als App-Icon. Ideal wären PNGs 192/512 + maskable — lässt sich später mit `sharp` oder per Online-Konverter nachreichen. - **LLM-Fallback-Extractor (Phase 2-Ausbau)** — war im PRD als spätere Phase notiert, wenn eine Domain kein JSON-LD liefert. Noch nicht umgesetzt. - **Playwright-E2E-Tests** — im PRD geplant, aber manuelles End-to-End-Smoke-Testing hat den gleichen Nutzen im MVP-Kontext. Kann für CI nachgezogen werden. - **Tag-Editor UI** — Tags kommen automatisch aus JSON-LD, werden in RecipeView angezeigt, aber es gibt kein UI zum manuellen Hinzufügen/Entfernen. - **SearXNG-Production-Secret-Key** — in `searxng/settings.yml` steht noch `dev-secret-change-in-prod`. Vor Produktion ändern. ## Commits (35 total) ``` chore: initialize repo with PRD docs: add implementation plan overview and Phase 1 detail feat(scaffold): init SvelteKit + TypeScript project test(infra): add vitest smoke test feat(parser): add ISO8601 duration parser feat(types): add shared type definitions feat(parser): add ingredient parser feat(scaler): add ingredient scaling with sensible rounding feat(parser): add JSON-LD schema.org/Recipe extractor feat(db): add SQLite schema, FTS5, migration runner feat(api): add /api/health endpoint feat(infra): add SearXNG dev container feat(ui): add minimal homepage with search input docs: add Phase 2 plan (import pipeline) feat(http): add fetchText/fetchBuffer with timeout and size limits feat(domains): add allowed-domain repository and whitelist check feat(images): add sha256-deduplicated image downloader feat(recipes): add recipe repository (insert/get/delete with FTS refresh) feat(recipes): add recipe importer (preview + persist) feat(profiles): add profile repository feat(api): expose preview/import/profile/domain endpoints docs: session handoff after Phase 1+2 autonomous work feat(recipes): add local search (FTS5 bm25) and action handlers feat(api): add recipe detail, search, rating, favorite, cooked, comments endpoints feat(api): serve local images with cache headers feat(ui): add profile client store with LocalStorage persistence feat(ui): add ProfileSwitcher modal and StarRating component feat(ui): add unified RecipeView component with tabs and portion scaling feat(ui): add layout with profile bar, home, search, recipe pages feat(search): add SearXNG client with whitelist-filtered web search feat(ui): add web search page and preview-before-save flow chore(deps): add archiver + yauzl for backup ZIPs feat(backup): add ZIP export endpoint (DB + images) feat(ui): add admin area (domains, profiles, backup) with gear link in header refactor: move scaler out of $lib/server so it can run in browser feat(db): bundle migration SQL via Vite glob + auto-create data dirs feat(pwa): add web manifest, SVG icon, and offline service worker feat(print): add print-optimized route with server-side portion scaling feat(infra): add production Dockerfile and docker-compose.prod.yml ``` ## Zur Erinnerung: Quick-Start auf deinem Homelab ```bash # clone + build + run git clone cd kochwas docker compose -f docker-compose.prod.yml up -d # öffne http://homelab.local:3000 auf Handy/Tablet # → "Wer kocht heute?" → Profil anlegen # → Zahnrad → Domains → "chefkoch.de" + "emmikochteinfach.de" hinzufügen # → "Spaghetti Carbonara" suchen → "Im Internet suchen" → Preview → Speichern # → Rezept kochen (Bildschirm bleibt an), bewerten, Heute-gekocht markieren ``` Fertig — Familie kann loslegen.