diff --git a/devlog/2026-05-08/data.json b/devlog/2026-05-08/data.json new file mode 100644 index 0000000..cd3e9d1 --- /dev/null +++ b/devlog/2026-05-08/data.json @@ -0,0 +1,513 @@ +{ + "date": "2026-05-08", + "day_number": 1, + "weekday": "Freitag", + "commits": 45, + "authors": [ + { + "name": "Till JS", + "count": 38 + }, + { + "name": "Till", + "count": 7 + } + ], + "additions": 15371, + "deletions": 1122, + "net_lines": 14249, + "files_changed": 134, + "new_files": 0, + "deleted_files": 0, + "session": { + "first_commit_at": "2026-05-08T12:08:41.000Z", + "last_commit_at": "2026-05-08T20:10:52.000Z", + "total_span_minutes": 482, + "active_minutes": 244, + "pauses": [ + { + "from": "14:41", + "to": "16:43", + "minutes": 122 + }, + { + "from": "18:52", + "to": "20:09", + "minutes": 77 + }, + { + "from": "21:11", + "to": "21:50", + "minutes": 39 + } + ], + "longest_focus_minutes": 130 + }, + "top_dirs": [ + { + "path": "apps/web/src/lib", + "pct": 20 + }, + { + "path": "apps/web/src/routes", + "pct": 14 + }, + { + "path": "packages/cards-domain/src", + "pct": 12 + }, + { + "path": "apps/api/src/routes", + "pct": 8 + }, + { + "path": "apps/api/src/db", + "pct": 4 + } + ], + "top_extensions": [ + { + "ext": ".ts", + "count": 159 + }, + { + "ext": ".svelte", + "count": 59 + }, + { + "ext": ".json", + "count": 23 + }, + { + "ext": ".md", + "count": 14 + }, + { + "ext": ".yml", + "count": 10 + }, + { + "ext": ".yaml", + "count": 7 + } + ], + "tags": [ + "prod-compose", + "dockerfiles", + "api Dockerfile", + "prod", + "auth" + ], + "commits_list": [ + { + "hash": "8605b1b", + "short": "Phase 0+1: Repo-Skelett für Cards-Greenfield", + "type": null, + "scope": null, + "additions": 1197, + "deletions": 0, + "timestamp": "2026-05-08T14:08:41+02:00" + }, + { + "hash": "45a47e0", + "short": "Phase 3: Domain-Modell + Decks/Cards/Reviews-CRUD", + "type": null, + "scope": null, + "additions": 1897, + "deletions": 106, + "timestamp": "2026-05-08T14:21:54+02:00" + }, + { + "hash": "5f67bd9", + "short": "Phase 3 follow-up: type-check + tests grün, ts-fsrs v5 API", + "type": null, + "scope": null, + "additions": 2345, + "deletions": 35, + "timestamp": "2026-05-08T14:41:04+02:00" + }, + { + "hash": "e3b3a2b", + "short": "docs: SMOKE_TEST.md — verifizierter E2E-Lauf gegen lokale Postgres", + "type": null, + "scope": null, + "additions": 111, + "deletions": 0, + "timestamp": "2026-05-08T16:43:07+02:00" + }, + { + "hash": "89a7a92", + "short": "Phase 4: Frontend-Core MVP — Decks, Cards, Study mit FSRS-Loop", + "type": null, + "scope": null, + "additions": 1582, + "deletions": 58, + "timestamp": "2026-05-08T16:52:31+02:00" + }, + { + "hash": "0328caa", + "short": "Phase 5: Föderations-Endpunkte — Cards ist föderierter Peer", + "type": null, + "scope": null, + "additions": 1371, + "deletions": 0, + "timestamp": "2026-05-08T17:10:35+02:00" + }, + { + "hash": "2bed282", + "short": "docs: STATUS.md als Single Source of Truth für Cards-Onboarding", + "type": null, + "scope": null, + "additions": 336, + "deletions": 0, + "timestamp": "2026-05-08T17:18:16+02:00" + }, + { + "hash": "553a78d", + "short": "Phase 8a: Cloze als MVP-Card-Type, Cluster-Counter", + "type": null, + "scope": null, + "additions": 248, + "deletions": 13, + "timestamp": "2026-05-08T17:35:39+02:00" + }, + { + "hash": "0b609c4", + "short": "Phase 8b: Cloze-Render im Study-View", + "type": null, + "scope": null, + "additions": 18, + "deletions": 1, + "timestamp": "2026-05-08T17:37:53+02:00" + }, + { + "hash": "2ca09fe", + "short": "Phase 8c: Anki-Import via portiertem Parser", + "type": null, + "scope": null, + "additions": 916, + "deletions": 3, + "timestamp": "2026-05-08T17:43:12+02:00" + }, + { + "hash": "9da10b3", + "short": "Phase 8d: STATUS.md auf Phase-8-Stand aktualisiert", + "type": null, + "scope": null, + "additions": 78, + "deletions": 20, + "timestamp": "2026-05-08T17:46:33+02:00" + }, + { + "hash": "0a40367", + "short": "Phase 9a: Card-Edit-Page für alle 3 CardTypes", + "type": null, + "scope": null, + "additions": 247, + "deletions": 4, + "timestamp": "2026-05-08T17:51:42+02:00" + }, + { + "hash": "35366ed", + "short": "Phase 9b: Cloze-Editor in /cards/new", + "type": null, + "scope": null, + "additions": 113, + "deletions": 38, + "timestamp": "2026-05-08T17:52:55+02:00" + }, + { + "hash": "47419b3", + "short": "Phase 9c: Inbox-Banner auf /decks und /study", + "type": null, + "scope": null, + "additions": 63, + "deletions": 0, + "timestamp": "2026-05-08T17:54:19+02:00" + }, + { + "hash": "aff4d95", + "short": "Phase 9d: Pre-Flight — Protocol-Mirror durch upstream ersetzt", + "type": null, + "scope": null, + "additions": 83, + "deletions": 175, + "timestamp": "2026-05-08T18:00:56+02:00" + }, + { + "hash": "03117d5", + "short": "Phase 9e: Account-Page mit DSGVO-Self-Service", + "type": null, + "scope": null, + "additions": 316, + "deletions": 52, + "timestamp": "2026-05-08T18:03:41+02:00" + }, + { + "hash": "6db6dc3", + "short": "Phase 9f: Statistik-Dashboard", + "type": null, + "scope": null, + "additions": 238, + "deletions": 2, + "timestamp": "2026-05-08T18:06:13+02:00" + }, + { + "hash": "a640594", + "short": "docs: STATUS.md auf Phase-9-Polish-Stand", + "type": null, + "scope": null, + "additions": 60, + "deletions": 26, + "timestamp": "2026-05-08T18:07:53+02:00" + }, + { + "hash": "c25c1d0", + "short": "Phase 9g: i18n DE/EN über alle Routes", + "type": null, + "scope": null, + "additions": 826, + "deletions": 270, + "timestamp": "2026-05-08T18:22:00+02:00" + }, + { + "hash": "fd86d96", + "short": "Phase 9h: A11y-Pass", + "type": null, + "scope": null, + "additions": 87, + "deletions": 7, + "timestamp": "2026-05-08T18:24:33+02:00" + }, + { + "hash": "4b451f1", + "short": "Phase 9i: Cloze-Hint-Anzeige", + "type": null, + "scope": null, + "additions": 60, + "deletions": 12, + "timestamp": "2026-05-08T18:26:00+02:00" + }, + { + "hash": "593d447", + "short": "Phase 9j: Anki-Re-Import-Dedupe via content_hash", + "type": null, + "scope": null, + "additions": 176, + "deletions": 8, + "timestamp": "2026-05-08T18:29:56+02:00" + }, + { + "hash": "e7ae93d", + "short": "docs: STATUS.md auf Phase-9-Welle-2-Stand", + "type": null, + "scope": null, + "additions": 42, + "deletions": 15, + "timestamp": "2026-05-08T18:31:57+02:00" + }, + { + "hash": "c9eb0a6", + "short": "Phase 9k: Media-Upload via MinIO-Container", + "type": null, + "scope": null, + "additions": 886, + "deletions": 78, + "timestamp": "2026-05-08T18:42:56+02:00" + }, + { + "hash": "39b1791", + "short": "Phase 9l: Image-Occlusion als 4. MVP-CardType", + "type": null, + "scope": null, + "additions": 681, + "deletions": 33, + "timestamp": "2026-05-08T18:50:45+02:00" + }, + { + "hash": "04c48ed", + "short": "docs: STATUS.md auf Phase-9-Welle-3-Stand", + "type": null, + "scope": null, + "additions": 59, + "deletions": 21, + "timestamp": "2026-05-08T18:52:49+02:00" + }, + { + "hash": "045903b", + "short": "Phase 10a: Production-Deploy-Stack (Mac Mini)", + "type": null, + "scope": null, + "additions": 203, + "deletions": 0, + "timestamp": "2026-05-08T20:09:19+02:00" + }, + { + "hash": "a993cc2", + "short": "fix(prod-compose): cards-api needs NPM_AUTH_TOKEN build-arg", + "type": "fix", + "scope": "prod-compose", + "additions": 2, + "deletions": 0, + "timestamp": "2026-05-08T20:10:39+02:00" + }, + { + "hash": "cfdc582", + "short": "fix(dockerfiles): copy tsconfig.base.json into build context", + "type": "fix", + "scope": "dockerfiles", + "additions": 2, + "deletions": 2, + "timestamp": "2026-05-08T20:12:01+02:00" + }, + { + "hash": "464aee1", + "short": "fix(prod-compose): cards-minio port 9110→9210 (cadvisor belegt 9110)", + "type": "fix", + "scope": "prod-compose", + "additions": 4, + "deletions": 4, + "timestamp": "2026-05-08T20:13:06+02:00" + }, + { + "hash": "78a6c8f", + "short": "fix(prod-compose): cards-api port 3091→3191 (3091 belegt)", + "type": "fix", + "scope": "prod-compose", + "additions": 2, + "deletions": 2, + "timestamp": "2026-05-08T20:13:46+02:00" + }, + { + "hash": "f9d7a16", + "short": "fix(api Dockerfile): COPY app-manifest.json (runtime-import)", + "type": "fix", + "scope": "api Dockerfile", + "additions": 4, + "deletions": 0, + "timestamp": "2026-05-08T20:14:20+02:00" + }, + { + "hash": "0dff798", + "short": "fix(prod): public URLs auf cardecky.* (war cards.* — bookmarks via nginx-301)", + "type": "fix", + "scope": "prod", + "additions": 7, + "deletions": 6, + "timestamp": "2026-05-08T20:18:10+02:00" + }, + { + "hash": "6ea96dd", + "short": "docs: Phase 10 LIVE — cardecky.mana.how + cardecky-api.mana.how", + "type": null, + "scope": null, + "additions": 8, + "deletions": 2, + "timestamp": "2026-05-08T20:19:59+02:00" + }, + { + "hash": "506aec3", + "short": "Phase 2a: Cards-API JWT-Verify (additiv zum Dev-Stub)", + "type": null, + "scope": null, + "additions": 73, + "deletions": 11, + "timestamp": "2026-05-08T20:41:09+02:00" + }, + { + "hash": "76d4e92", + "short": "Phase 6: Tier-Awareness + mana-credits-Client (Plumbing)", + "type": null, + "scope": null, + "additions": 147, + "deletions": 10, + "timestamp": "2026-05-08T20:45:08+02:00" + }, + { + "hash": "5b6d096", + "short": "fix(prod-compose): pass MANA_AUTH_URL/MANA_CREDITS_URL/SERVICE_KEY/DEV_STUB into cards-api container", + "type": "fix", + "scope": "prod-compose", + "additions": 4, + "deletions": 0, + "timestamp": "2026-05-08T20:45:55+02:00" + }, + { + "hash": "d7c7c97", + "short": "Phase 7a: cards.create-Tool für Cloze + Image-Occlusion + content_hash", + "type": null, + "scope": null, + "additions": 36, + "deletions": 4, + "timestamp": "2026-05-08T20:48:39+02:00" + }, + { + "hash": "a960d09", + "short": "docs: STATUS auf Phase 2/6/7/11 ✅", + "type": null, + "scope": null, + "additions": 4, + "deletions": 4, + "timestamp": "2026-05-08T20:49:43+02:00" + }, + { + "hash": "7119756", + "short": "Phase 10c: Cards-Web SSO-Login gegen mana-auth", + "type": null, + "scope": null, + "additions": 236, + "deletions": 55, + "timestamp": "2026-05-08T21:08:06+02:00" + }, + { + "hash": "f1622e9", + "short": "docs: Phase 7 LIVE — mana-share + mana-mcp deployed", + "type": null, + "scope": null, + "additions": 1, + "deletions": 1, + "timestamp": "2026-05-08T21:11:31+02:00" + }, + { + "hash": "1b840a9", + "short": "Phase 10d: Token-Refresh + 401-Retry im Cards-Web", + "type": null, + "scope": null, + "additions": 118, + "deletions": 15, + "timestamp": "2026-05-08T21:50:12+02:00" + }, + { + "hash": "3b74583", + "short": "fix(auth): two-step Login (Better-Auth-native + /refresh) für SSO-Cookie", + "type": "fix", + "scope": "auth", + "additions": 30, + "deletions": 15, + "timestamp": "2026-05-08T21:52:46+02:00" + }, + { + "hash": "87a7a31", + "short": "fix(web): SvelteKit-env via \\$env/dynamic/public statt import.meta.env", + "type": "fix", + "scope": "web", + "additions": 17, + "deletions": 8, + "timestamp": "2026-05-08T22:03:35+02:00" + }, + { + "hash": "f11df63", + "short": "Phase 9m: KI-Deck-Generation via mana-llm", + "type": null, + "scope": null, + "additions": 437, + "deletions": 6, + "timestamp": "2026-05-08T22:10:52+02:00" + } + ], + "review_state": "auto", + "llm": { + "model": null, + "generated_at": null + } +} diff --git a/devlog/2026-05-08/macher.md b/devlog/2026-05-08/macher.md new file mode 100644 index 0000000..1f51440 --- /dev/null +++ b/devlog/2026-05-08/macher.md @@ -0,0 +1,122 @@ +--- +date: 2026-05-08 +day: 1 +view: macher +weekday: Freitag +commits: 45 +review: written +--- +# Freitag, 2026-05-08 — Tag 1 (Macher-Sicht) + +Greenfield (Strategie B) zu Live-App in einer Marathon-Session. +Phasen 0/1 → 3 → 4 → 5 → 8 → 9 → 10 → 2a/6/7 → 10c/d → 9m in einer +Schicht. 45 Commits, eines der dichtesten Tage des Verein-Aufbaus. + +## Stats + +45 Commits, +15 371 / −1 122 LoC, 134 Files. Top-Dirs: web/lib +(20 %), web/routes (14 %), cards-domain (12 %), api/routes (8 %), +api/db (4 %). Session 12:08 → 20:10, 244 aktive Minuten, +längster Fokus 130 Min. + +## Blöcke + +### Phase 0/1: Skelett +- Repo-Skelett, pnpm + Bun + Drizzle, `pgSchema('cards')`. + +### Phase 3: Domain-Modell +- **Decks/Cards/Reviews-CRUD** + ts-fsrs v5-API. +- **SMOKE_TEST.md** als verifizierter E2E-Lauf. + +### Phase 4: Frontend-Core +- SvelteKit MVP — Decks, Cards, Study mit FSRS-Loop. + +### Phase 5: Föderation +- Cards-API als föderierter Peer im Mana-Ökosystem. + +### Phase 8: Cloze +- **8a — Cloze als MVP-Card-Type** + Cluster-Counter (für Sub- + Indices). +- **8b — Cloze-Render im Study-View.** +- **8c — Anki-Import** via portiertem Parser. + +### Phase 9: Polish +- **9a — Card-Edit-Page** für alle 3 CardTypes. +- **9b — Cloze-Editor** in `/cards/new`. +- **9c — Inbox-Banner** auf /decks und /study. +- **9d — Protocol-Mirror durch upstream ersetzt** (Pre-Flight). +- **9e — Account-Page** mit DSGVO-Self-Service. +- **9f — Statistik-Dashboard.** +- **9g — i18n DE/EN** über alle Routes. +- **9h — A11y-Pass.** +- **9i — Cloze-Hint-Anzeige.** +- **9j — Anki-Re-Import-Dedupe** via content_hash. +- **9k — Media-Upload** via MinIO-Container. +- **9l — Image-Occlusion** als 4. MVP-CardType. +- **9m — KI-Deck-Generation** via mana-llm. + +### Phase 10: Production +- **10a — Production-Deploy-Stack** (Mac Mini). +- Compose-Fix-Pass: NPM_AUTH_TOKEN-build-arg, tsconfig.base.json- + copy, MinIO-Port 9110→9210 (cadvisor belegt), API-Port 3091→3191 + (3091 belegt), app-manifest.json-COPY (runtime-import), public + URLs auf `cardecky.*` (war `cards.*` — bookmarks via nginx-301). +- **Phase 10 LIVE — cardecky.mana.how + cardecky-api.mana.how.** + +### Phase 2a/6/7 +- **2a — Cards-API JWT-Verify** (additiv zum Dev-Stub). +- **6 — Tier-Awareness + mana-credits-Client** (Plumbing). +- Env-vars in cards-api-Container (MANA_AUTH_URL, + MANA_CREDITS_URL, SERVICE_KEY, DEV_STUB). +- **7a — `cards.create`-Tool** für Cloze + Image-Occlusion + + content_hash. + +### Phase 7 / Phase 10c/d +- **Phase 7 LIVE — mana-share + mana-mcp deployed.** +- **10c — Cards-Web SSO-Login** gegen mana-auth. +- **10d — Token-Refresh + 401-Retry** im Cards-Web. +- **two-step Login** (Better-Auth-native + /refresh) für SSO- + Cookie. +- **SvelteKit-env via `$env/dynamic/public`** statt + `import.meta.env`. + +## Architektur-Entscheidungen + +- **Strategie B (eigene App)**, nicht Subprojekt. Plan in + `mana/docs/playbooks/CARDS_GREENFIELD.md`. +- **Server-authoritative MVP.** Keine Dexie, keine IndexedDB, + keine eigene Sync-Engine. Frontend = HTTP-Client zu cards-api. + Local-First später via mana-sync. +- **FSRS am Server.** Grading-Calls gehen immer an + `POST /api/v1/reviews/:cardId/:subIndex/grade`. Algorithmen- + Updates wirken sofort, kein Client-Code-Update. +- **Eigene DB `cards`** im geteilten Postgres-Cluster, Schema- + Isolation via `pgSchema('cards')`. +- **Föderation über `@mana/shared-app-tpl`.** Pflicht-Endpoints + (manifest, healthz, share/receive, tools, search, dsgvo) kommen + aus dem geteilten Boilerplate. +- **JWT-Validation lokal** via JWKS-Cache (5 min), kein Live- + Call. +- **Domain `cardecky.mana.how`** statt `cards.mana.how` — kürzer, + weniger generisch. +- **Two-Step-Login** (Better-Auth-native + /refresh) für SSO- + Cookie. Better-Auth setzt erst nach /refresh die richtigen + Cookies. + +## Trade-offs + +- **45 Commits in 244 Min** ist sehr viel; jeder Commit eine Phase. +- **Greenfield, kein Code-Reuse aus mana-monorepo** für Study/ + FSRS/Sync (sauber neu). Ausnahme: Marketplace-Restore (kommt + Tag 2). +- **+14 249 LoC netto** ist Greenfield-Pattern. +- **Live am Tag 1** ist mutig; Compliance-Audit kam erst + hinterher. + +## Offene Punkte + +- **Marketplace-Restore** (`docs/playbooks/MARKETPLACE_RESTORE.md`) + — pending für Tag 2. +- **Lost-Pixel-Snapshots** für UI fehlen. +- **Endurance-Test** der Live-App über Tage steht aus. +- **mana-credits-Verbrauch sichtbar machen** in der UI. diff --git a/devlog/2026-05-08/spieler.md b/devlog/2026-05-08/spieler.md new file mode 100644 index 0000000..05b46c5 --- /dev/null +++ b/devlog/2026-05-08/spieler.md @@ -0,0 +1,40 @@ +--- +date: 2026-05-08 +day: 1 +view: spieler +weekday: Freitag +commits: 45 +review: written +--- +# Freitag, 2026-05-08 — Tag 1 + +Cards geht live. Eine eigene Lern-Karten-App des Vereins — +**Spaced Repetition, Anki-Import, KI-generierte Decks**, alles +unter **cardecky.mana.how**. Aus „Modul im alten großen Mana-Repo" +wird heute ein eigenständiges Werkzeug. + +## Was du heute schon kannst + +- **Anmelden** mit deinem Verein-Account. +- **Decks anlegen + Karten erstellen** — Vorder-/Rückseite, + Cloze (Lückentext), Image-Occlusion (Bild mit Maske). +- **Lernen mit FSRS** — der moderne Lern-Algorithmus, der dir + Karten genau dann zeigt, wenn du sie wahrscheinlich vergisst. +- **Anki-Import** — wenn du schon Anki-Decks hast, lädst du sie + hoch und sie sind drin. +- **KI-Deck-Generierung** — beschreibe ein Thema, die App schlägt + Karten vor. +- **Bilder + Audio** auf Karten. +- **DSGVO-Self-Service** — Daten herunterladen, Konto löschen. +- **Statistik-Dashboard** über deinen Lern-Stand. +- **DE/EN-Sprachwechsel** über alle Seiten. +- **Barrierefreiheit** — Tastatur-Bedienung, Screenreader-tauglich. + +## Hintergrund + +Cards war Teil eines größeren Mana-Repos und schwer zu pflegen. +Heute lebt es eigenständig auf `cardecky.mana.how` (URL bewusst +„Cardecky" — kürzer, einprägsamer als „Cards"), mit eigener +Datenbank, eigener Adresse und vereinfachter Wartung. Die App ist +**werbefrei und ohne Tracker** — du zahlst nichts, dafür beobachtet +dich niemand. diff --git a/devlog/2026-05-09/data.json b/devlog/2026-05-09/data.json new file mode 100644 index 0000000..0fa1088 --- /dev/null +++ b/devlog/2026-05-09/data.json @@ -0,0 +1,253 @@ +{ + "date": "2026-05-09", + "day_number": 2, + "weekday": "Samstag", + "commits": 16, + "authors": [ + { + "name": "Till JS", + "count": 16 + } + ], + "additions": 17104, + "deletions": 1154, + "net_lines": 15950, + "files_changed": 145, + "new_files": 0, + "deleted_files": 0, + "session": { + "first_commit_at": "2026-05-09T10:38:51.000Z", + "last_commit_at": "2026-05-09T18:24:47.000Z", + "total_span_minutes": 466, + "active_minutes": 123, + "pauses": [ + { + "from": "12:38", + "to": "15:05", + "minutes": 147 + }, + { + "from": "16:14", + "to": "17:16", + "minutes": 62 + }, + { + "from": "17:16", + "to": "18:01", + "minutes": 45 + }, + { + "from": "18:49", + "to": "20:17", + "minutes": 89 + } + ], + "longest_focus_minutes": 69 + }, + "top_dirs": [ + { + "path": "docs/marketplace/archive", + "pct": 17 + }, + { + "path": "apps/web/src/lib", + "pct": 17 + }, + { + "path": "apps/web/src/routes", + "pct": 15 + }, + { + "path": "docs/marketplace/seed", + "pct": 13 + }, + { + "path": "apps/api/src/routes", + "pct": 8 + } + ], + "top_extensions": [ + { + "ext": ".ts", + "count": 80 + }, + { + "ext": ".svelte", + "count": 55 + }, + { + "ext": ".md", + "count": 34 + }, + { + "ext": ".json", + "count": 7 + }, + { + "ext": ".yaml", + "count": 4 + }, + { + "ext": ".jsonl", + "count": 3 + } + ], + "tags": [ + "decks", + "marketplace", + "theming", + "status", + "deps" + ], + "commits_list": [ + { + "hash": "e596199", + "short": "dev: dev:full + cards-dev-Alias + lokale mana-auth-Pipeline", + "type": null, + "scope": null, + "additions": 463, + "deletions": 5, + "timestamp": "2026-05-09T12:38:51+02:00" + }, + { + "hash": "9a7068d", + "short": "Phase 12 R0+R1: Marketplace-Restore-Plan + Schema in marketplace-pgSchema", + "type": null, + "scope": null, + "additions": 2404, + "deletions": 4, + "timestamp": "2026-05-09T15:05:22+02:00" + }, + { + "hash": "7dbbf63", + "short": "Phase 12 R2: Marketplace-Backend α + β — Authors + Deck-Init + Publish", + "type": null, + "scope": null, + "additions": 4004, + "deletions": 1, + "timestamp": "2026-05-09T15:13:58+02:00" + }, + { + "hash": "d45f1c0", + "short": "Phase 12 R3: Marketplace γ + δ — Discovery + Engagement + Subscribe + Smart-Merge", + "type": null, + "scope": null, + "additions": 1170, + "deletions": 11, + "timestamp": "2026-05-09T15:27:39+02:00" + }, + { + "hash": "92a1d58", + "short": "Phase 12 R4: Marketplace ε — Pull-Requests + Card-Discussions", + "type": null, + "scope": null, + "additions": 638, + "deletions": 5, + "timestamp": "2026-05-09T15:50:16+02:00" + }, + { + "hash": "4086171", + "short": "Phase 12 R5: Marketplace-Frontend — /explore + /d + /u + /me/{published,subscribed,forks}", + "type": null, + "scope": null, + "additions": 2310, + "deletions": 1, + "timestamp": "2026-05-09T16:04:40+02:00" + }, + { + "hash": "17871ba", + "short": "Phase 12 G1-G4: Marketplace-Polish — svelte-ignore + Skeleton/Empty-State + Server-Filter + Owner-Info", + "type": null, + "scope": null, + "additions": 174, + "deletions": 63, + "timestamp": "2026-05-09T16:14:21+02:00" + }, + { + "hash": "404ddec", + "short": "docs(marketplace): CONTENT_PLAN — bilingualer CH/DE-Lehrplan-Korridor + 20 Phase-1-Seed-Decks", + "type": "docs", + "scope": "marketplace", + "additions": 327, + "deletions": 0, + "timestamp": "2026-05-09T17:16:22+02:00" + }, + { + "hash": "19a0036", + "short": "feat(theming): forest variant from @mana/themes (sprint 9m)", + "type": "feat", + "scope": "theming", + "additions": 323, + "deletions": 261, + "timestamp": "2026-05-09T18:01:37+02:00" + }, + { + "hash": "870e2ae", + "short": "feat(decks): card-stack visualization + direct-launch study mode", + "type": "feat", + "scope": "decks", + "additions": 1283, + "deletions": 180, + "timestamp": "2026-05-09T18:02:04+02:00" + }, + { + "hash": "9626200", + "short": "chore: seed-test-decks browser-console snippet", + "type": null, + "scope": null, + "additions": 246, + "deletions": 0, + "timestamp": "2026-05-09T18:02:15+02:00" + }, + { + "hash": "e4cf124", + "short": "docs(status): Cardecky-Skill auf Marketplace + 2 Decks live", + "type": "docs", + "scope": "status", + "additions": 1, + "deletions": 1, + "timestamp": "2026-05-09T18:16:23+02:00" + }, + { + "hash": "d7f3b93", + "short": "feat(deps): migrate Header from @mana/shared-ui@0.1.x to shared-ui-2", + "type": "feat", + "scope": "deps", + "additions": 27, + "deletions": 222, + "timestamp": "2026-05-09T18:27:24+02:00" + }, + { + "hash": "9a07454", + "short": "seed: 3 Cardecky-Decks v1.0.0 + Audit-Trail im Repo", + "type": null, + "scope": null, + "additions": 2753, + "deletions": 1, + "timestamp": "2026-05-09T18:49:05+02:00" + }, + { + "hash": "5876f95", + "short": "refactor(web): vereinfachte Navigation und inline Deck-Erstellung", + "type": "refactor", + "scope": "web", + "additions": 730, + "deletions": 388, + "timestamp": "2026-05-09T20:17:58+02:00" + }, + { + "hash": "7bf6131", + "short": "feat(decks): Deck-Kategorien über den ganzen Stack", + "type": "feat", + "scope": "decks", + "additions": 251, + "deletions": 11, + "timestamp": "2026-05-09T20:24:47+02:00" + } + ], + "review_state": "auto", + "llm": { + "model": null, + "generated_at": null + } +} diff --git a/devlog/2026-05-09/macher.md b/devlog/2026-05-09/macher.md new file mode 100644 index 0000000..2d9c26b --- /dev/null +++ b/devlog/2026-05-09/macher.md @@ -0,0 +1,83 @@ +--- +date: 2026-05-09 +day: 2 +view: macher +weekday: Samstag +commits: 16 +review: written +--- +# Samstag, 2026-05-09 — Tag 2 (Macher-Sicht) + +Marketplace-Restore-Sprint. Phase 12 R0–R5 + G1–G4. Code aus dem +`cards-decommission-base`-Tag im managarten-Repo additiv re-importiert +in eigenes `marketplace`-pgSchema, additiv zur Study-Welt aus Tag 1. + +## Stats + +16 Commits, +17 104 / −1 154 LoC, 145 Files. Top-Dirs: +`docs/marketplace/archive` (17 %), `apps/web/src/lib` (17 %), +`apps/web/src/routes` (15 %), `docs/marketplace/seed` (13 %), +`apps/api/src/routes` (8 %). Session 10:38 → 18:24, 123 aktive +Minuten, längster Fokus 69 Min. + +## Schritte + +- **dev:full + cards-dev-Alias** + lokale mana-auth-Pipeline. +- **R0+R1 — Marketplace-Restore-Plan + Schema** in + `marketplace`-pgSchema. Schema-Isolation gegen `cards`-Schema. +- **R2 — Backend α + β** — Authors-Tabelle + Deck-Init + Publish. +- **R3 — γ + δ** — Discovery + Engagement + Subscribe + Smart- + Merge (wenn du eine Card schon eigenständig bearbeitet hast, + bekommst du beim Pull eine Merge-Frage). +- **R4 — ε** — Pull-Requests + Card-Discussions. +- **R5 — Frontend** — `/explore`, `/d/`, `/u/`, `/me/published`, `/me/subscribed`, `/me/forks`. +- **G1–G4 — Polish** — svelte-ignore-Sweep + Skeleton/Empty-State + + Server-Filter + Owner-Info. +- **CONTENT_PLAN** — bilingualer CH/DE-Lehrplan-Korridor + 20 + Phase-1-Seed-Decks dokumentiert. +- **Theming: `forest` variant from `@mana/themes`** (sprint 9m). +- **Decks: card-stack visualization** + direct-launch study mode. +- **Browser-Console-Snippet** zum Seeden von Test-Decks. +- **Migration `@mana/shared-ui` → `shared-ui-2`** im Header. +- **Seed: 3 Cardecky-Decks v1.0.0** + Audit-Trail im Repo. +- **Web-Refactor: vereinfachte Navigation + inline Deck- + Erstellung.** +- **Deck-Kategorien** über den ganzen Stack (DB + API + UI). + +## Architektur-Entscheidungen + +- **Marketplace in eigenem pgSchema (`marketplace`)** statt + Erweiterung von `cards`. Trennung: Study-State ist privat, + Marketplace-State ist öffentlich. +- **Authors-Tabelle separat** von User-Tabelle. Author hat + Pseudonym, Avatar, Bio; User-Account ist mana-auth. +- **Pull-Request-Modell wie Git**: Fork = lokale Kopie eines + Decks, PR = Vorschlag zurück. Card-Discussions hängen am + Original-Card. +- **Smart-Merge bei Subscribe-Pull**: Wenn lokal eigene Edits da + sind, Conflict-Dialog. Beibehalten / Übernehmen / Manuell- + Merge. +- **Forest-Theme** aus `@mana/themes`, nicht inline. Wie nutriphi + + zitare an Tag 2. +- **shared-ui-2 für Header** — strikte 12-Token-Disziplin, + PillTabGroup. + +## Trade-offs + +- **Marketplace-Restore aus alten Code-Stand** ist Verbot in + Strategie B — bewusste Ausnahme, dokumentiert in CLAUDE.md. + Marketplace war nie Auf der Strategie-B-Liste, wurde nur + mit-rausgerissen. Restore additiv, nicht ersetzend. +- **+15 950 LoC netto** für Marketplace + Theming + Refactor. +- **Eigenes `authors`-Pseudonym-Modell** statt mana-auth-Profile + → doppelte Identitäts-Pflege. Akzeptiert, weil Pseudonym pro App + Sinn macht. + +## Offene Punkte + +- **20 Phase-1-Seed-Decks** — heute 3 live, 17 fehlen. +- **Bilingualer CH/DE-Lehrplan-Korridor** Content-Plan, Umsetzung + manuell. +- **PR-Conflict-Surface** für Card-Discussion-Threading. +- **Marketplace-Suche** noch nicht — heute nur Filter. diff --git a/devlog/2026-05-09/spieler.md b/devlog/2026-05-09/spieler.md new file mode 100644 index 0000000..128769c --- /dev/null +++ b/devlog/2026-05-09/spieler.md @@ -0,0 +1,39 @@ +--- +date: 2026-05-09 +day: 2 +view: spieler +weekday: Samstag +commits: 16 +review: written +--- +# Samstag, 2026-05-09 — Tag 2 + +Cardecky bekommt einen **Marktplatz**. Du kannst Decks von anderen +Mitgliedern abonnieren, deine eigenen veröffentlichen, andere +deine Verbesserungs-Vorschläge machen lassen — ein Mini-GitHub für +Lern-Karten. + +## Was sich für dich ändert + +- **Explore-Seite** mit veröffentlichten Decks zum Stöbern. +- **Decks abonnieren** — du bekommst Updates, wenn der Author + etwas ändert. +- **Eigene Decks veröffentlichen** unter deinem Pseudonym oder + echtem Namen. +- **Pull-Requests** — du kannst Verbesserungen an einem Deck + vorschlagen, der Author entscheidet, ob er sie übernimmt. +- **Card-Discussions** — Diskussion pro Karte (ist das richtig? + Quelle?). +- **Smart-Merge** beim Abonnieren — wenn du schon eigene + Bearbeitungen einer Karte hast, fragt die App, was Vorrang hat. +- **Drei Cardecky-Decks live** als Demo-Inhalt unter dem + Cardecky-Plattform-User. +- **Forest-Theme** im Vereins-Stil. +- **Karten-Stapel-Visualisierung** auf den Deck-Karten — + du siehst auf einen Blick, dass es ein Stapel ist. + +## Hintergrund + +Lern-Karten teilen ist alt, aber meistens unfair: Anki-Shared-Decks +gehen über einen privaten Server. Cardecky-Marktplatz ist offen, +werbefrei und vom Verein getragen. diff --git a/devlog/2026-05-10/data.json b/devlog/2026-05-10/data.json new file mode 100644 index 0000000..c18429d --- /dev/null +++ b/devlog/2026-05-10/data.json @@ -0,0 +1,324 @@ +{ + "date": "2026-05-10", + "day_number": 3, + "weekday": "Sonntag", + "commits": 26, + "authors": [ + { + "name": "Till JS", + "count": 26 + } + ], + "additions": 7019, + "deletions": 1919, + "net_lines": 5100, + "files_changed": 59, + "new_files": 0, + "deleted_files": 0, + "session": { + "first_commit_at": "2026-05-10T12:38:48.000Z", + "last_commit_at": "2026-05-10T15:07:24.000Z", + "total_span_minutes": 149, + "active_minutes": 118, + "pauses": [ + { + "from": "14:47", + "to": "15:18", + "minutes": 31 + } + ], + "longest_focus_minutes": 109 + }, + "top_dirs": [ + { + "path": "apps/web/src/routes", + "pct": 39 + }, + { + "path": "apps/web/src/lib", + "pct": 34 + }, + { + "path": "apps/api/src/routes", + "pct": 11 + }, + { + "path": "packages/cards-domain/src", + "pct": 7 + }, + { + "path": "apps/api/src/lib", + "pct": 3 + } + ], + "top_extensions": [ + { + "ext": ".svelte", + "count": 72 + }, + { + "ext": ".ts", + "count": 41 + }, + { + "ext": ".py", + "count": 1 + }, + { + "ext": ".jsonl", + "count": 1 + }, + { + "ext": ".md", + "count": 1 + } + ], + "tags": [ + "cards", + "web", + "api", + "study", + "cards/new" + ], + "commits_list": [ + { + "hash": "e2b493d", + "short": "feat(study): Periodensystem-Karten mit Kategorie-Farben und Eigenschaften-Tabelle", + "type": "feat", + "scope": "study", + "additions": 338, + "deletions": 246, + "timestamp": "2026-05-10T14:38:48+02:00" + }, + { + "hash": "d9532ed", + "short": "fix(study): Hint-Text entfernt, kein vertikales Scrollen", + "type": "fix", + "scope": "study", + "additions": 2, + "deletions": 10, + "timestamp": "2026-05-10T14:40:17+02:00" + }, + { + "hash": "598acb4", + "short": "fix(study): kein Layout-Sprung beim Wechsel Reveal ↔ Grade-Buttons", + "type": "fix", + "scope": "study", + "additions": 35, + "deletions": 15, + "timestamp": "2026-05-10T14:47:15+02:00" + }, + { + "hash": "170a282", + "short": "feat(cards): audio-front Card-Type", + "type": "feat", + "scope": "cards", + "additions": 122, + "deletions": 4, + "timestamp": "2026-05-10T15:18:41+02:00" + }, + { + "hash": "1212b62", + "short": "feat(cards): Deck-Generierung aus Bildern und PDFs via Vision-LLM", + "type": "feat", + "scope": "cards", + "additions": 667, + "deletions": 94, + "timestamp": "2026-05-10T15:21:35+02:00" + }, + { + "hash": "0791436", + "short": "feat(cards): typing Card-Type mit Fuzzy-Match", + "type": "feat", + "scope": "cards", + "additions": 354, + "deletions": 1, + "timestamp": "2026-05-10T15:23:58+02:00" + }, + { + "hash": "2b36990", + "short": "feat(cards): multiple-choice Card-Type mit dynamischen Distractors", + "type": "feat", + "scope": "cards", + "additions": 351, + "deletions": 4, + "timestamp": "2026-05-10T15:28:37+02:00" + }, + { + "hash": "a612ad0", + "short": "feat(cards/new): typing, multiple-choice, audio-front im Erstellungs-UI", + "type": "feat", + "scope": "cards/new", + "additions": 125, + "deletions": 9, + "timestamp": "2026-05-10T15:36:17+02:00" + }, + { + "hash": "b5d3a29", + "short": "refactor(cards/new): UI-Redesign + Multiple-Choice Option-Builder", + "type": "refactor", + "scope": "cards/new", + "additions": 481, + "deletions": 185, + "timestamp": "2026-05-10T15:45:21+02:00" + }, + { + "hash": "9754718", + "short": "feat(cards/new): Live-Kartenvorschau neben dem Formular", + "type": "feat", + "scope": "cards/new", + "additions": 597, + "deletions": 234, + "timestamp": "2026-05-10T15:50:57+02:00" + }, + { + "hash": "03ec7e7", + "short": "feat(decks): Edit-Icon auf Deck-Karten + Deck-Edit-Page", + "type": "feat", + "scope": "decks", + "additions": 298, + "deletions": 0, + "timestamp": "2026-05-10T15:57:37+02:00" + }, + { + "hash": "731481f", + "short": "refactor(deck-detail): Redesign mit Kategorie-Picker, Card-Menü, Markdown", + "type": "refactor", + "scope": "deck-detail", + "additions": 516, + "deletions": 138, + "timestamp": "2026-05-10T15:59:56+02:00" + }, + { + "hash": "1f1abf3", + "short": "feat(decks/from-image): URL-Input als Alternative zu Datei-Upload", + "type": "feat", + "scope": "decks/from-image", + "additions": 181, + "deletions": 55, + "timestamp": "2026-05-10T16:00:04+02:00" + }, + { + "hash": "0c68186", + "short": "refactor(marketplace): UI-Verbesserungen, MarketplaceDeckStack, Explore-Icons", + "type": "refactor", + "scope": "marketplace", + "additions": 451, + "deletions": 101, + "timestamp": "2026-05-10T16:00:11+02:00" + }, + { + "hash": "b761cd5", + "short": "fix(decks/from-image): kontextbewusste Statusmeldungen für URL-only-Generierung", + "type": "fix", + "scope": "decks/from-image", + "additions": 7, + "deletions": 5, + "timestamp": "2026-05-10T16:02:21+02:00" + }, + { + "hash": "c1a87a4", + "short": "feat(publish): Deck direkt aus der Detail-Seite veröffentlichen", + "type": "feat", + "scope": "publish", + "additions": 605, + "deletions": 0, + "timestamp": "2026-05-10T16:07:55+02:00" + }, + { + "hash": "608b385", + "short": "feat(web): decks-page auf Explore-Layout migriert + Subscriptions sichtbar", + "type": "feat", + "scope": "web", + "additions": 207, + "deletions": 36, + "timestamp": "2026-05-10T16:08:21+02:00" + }, + { + "hash": "a883ba8", + "short": "refactor(me/published): UX-Fix — Anzeige-Name zuerst, Auto-Slug, einspaltiges Layout", + "type": "refactor", + "scope": "me/published", + "additions": 344, + "deletions": 77, + "timestamp": "2026-05-10T16:11:57+02:00" + }, + { + "hash": "b182bac", + "short": "refactor(api): review-row-Erstellung extrahieren + QW-Fixes", + "type": "refactor", + "scope": "api", + "additions": 64, + "deletions": 67, + "timestamp": "2026-05-10T16:12:28+02:00" + }, + { + "hash": "f3a1481", + "short": "refactor(account): Profil-Karte, Meta-Grid, Action-Karten", + "type": "refactor", + "scope": "account", + "additions": 304, + "deletions": 56, + "timestamp": "2026-05-10T16:18:57+02:00" + }, + { + "hash": "f2f752e", + "short": "feat(web): apiErrorMessage-Utility + MultipleChoice-Fallback", + "type": "feat", + "scope": "web", + "additions": 358, + "deletions": 261, + "timestamp": "2026-05-10T16:27:19+02:00" + }, + { + "hash": "c39bacc", + "short": "refactor(api): DTO-Helper extrahieren + N+1 in marketplace/decks beheben", + "type": "refactor", + "scope": "api", + "additions": 87, + "deletions": 86, + "timestamp": "2026-05-10T16:30:29+02:00" + }, + { + "hash": "595f1f9", + "short": "refactor(web): ClozeCardForm + MultipleChoiceCardForm extrahieren + Import-Bug fixen", + "type": "refactor", + "scope": "web", + "additions": 286, + "deletions": 168, + "timestamp": "2026-05-10T16:35:01+02:00" + }, + { + "hash": "dc382a7", + "short": "feat(api): URL-Kontext auch in /decks/generate + fetchUrlContent extrahieren", + "type": "feat", + "scope": "api", + "additions": 63, + "deletions": 55, + "timestamp": "2026-05-10T16:39:39+02:00" + }, + { + "hash": "26b136a", + "short": "test(api): Unit-Tests für makeInitialReviewRows und fetchUrlContent", + "type": "test", + "scope": "api", + "additions": 170, + "deletions": 0, + "timestamp": "2026-05-10T16:40:30+02:00" + }, + { + "hash": "333581c", + "short": "fix(web): body stream already read — Text zuerst lesen, dann JSON parsen", + "type": "fix", + "scope": "web", + "additions": 6, + "deletions": 12, + "timestamp": "2026-05-10T17:07:24+02:00" + } + ], + "review_state": "auto", + "llm": { + "model": null, + "generated_at": null + } +} diff --git a/devlog/2026-05-10/macher.md b/devlog/2026-05-10/macher.md new file mode 100644 index 0000000..947f1e8 --- /dev/null +++ b/devlog/2026-05-10/macher.md @@ -0,0 +1,105 @@ +--- +date: 2026-05-10 +day: 3 +view: macher +weekday: Sonntag +commits: 26 +review: written +--- +# Sonntag, 2026-05-10 — Tag 3 (Macher-Sicht) + +Karten-Typ-Vollausbau (3 → 7), Vision-LLM-Pfad für Deck-Generation, +Erstellungs-UI-Redesign mit Live-Vorschau, Marketplace-UX-Pass. + +## Stats + +26 Commits, +7 019 / −1 919 LoC, 59 Files. Top-Dirs: web/routes +(39 %), web/lib (34 %), api/routes (11 %), cards-domain (7 %). +Session 12:38 → 15:07, 118 aktive Minuten, längster Fokus 109 Min. + +## Blöcke + +### Study-View +- **Periodensystem-Karten** mit Kategorie-Farben + Eigenschaften- + Tabelle (für Element-Lern-Decks). +- **Hint-Text entfernt**, kein vertikales Scrollen. +- **Kein Layout-Sprung** beim Wechsel Reveal ↔ Grade-Buttons + (vorher hat sich das UI gestaucht, jetzt fix). + +### Neue Karten-Typen +- **audio-front** — Karte spielt Audio ab, User antwortet. +- **typing** mit Fuzzy-Match (Levenshtein ≤ 2). +- **multiple-choice** mit dynamischen Distractors via mana-llm. + +### Card-Editor-Vollausbau +- **typing, multiple-choice, audio-front** im `/cards/new`-UI. +- **UI-Redesign + Multiple-Choice Option-Builder** (Add/Remove, + Correct-Toggle). +- **Live-Karten-Vorschau** neben dem Formular. + +### Decks +- **Deck-Generierung aus Bildern und PDFs** via Vision-LLM. +- **Edit-Icon auf Deck-Karten** + Deck-Edit-Page. +- **Deck-Detail-Redesign** mit Kategorie-Picker, Card-Menü, + Markdown. +- **URL-Input als Alternative** zu Datei-Upload für /decks/from- + image. +- **Decks-Page auf Explore-Layout migriert** + Subscriptions + sichtbar. + +### Marketplace-Polish +- **MarketplaceDeckStack-Component** (gleicher Fan-Stack-Look wie + /decks). +- **Explore-Icons.** +- **/me/published UX-Fix** — Anzeige-Name zuerst, Auto-Slug, + einspaltiges Layout. +- **Publish direkt aus Detail-Seite.** + +### Refactoring +- **review-row-Erstellung extrahieren** (`makeInitialReviewRows`) + + Unit-Tests. +- **DTO-Helper extrahieren** + N+1 in `marketplace/decks` beheben. +- **ClozeCardForm + MultipleChoiceCardForm extrahieren** + + Import-Bug fixen. +- **URL-Kontext auch in `/decks/generate`** + `fetchUrlContent` + extrahieren. +- **apiErrorMessage-Utility** + MultipleChoice-Fallback. +- **fix(web): body stream already read** — Text zuerst lesen, dann + JSON parsen. +- **Account-Refactor**: Profil-Karte, Meta-Grid, Action-Karten. + +## Architektur-Entscheidungen + +- **Vision-LLM-Pipeline für Deck-Generation**: Bild/PDF → + mana-llm `vision`-Endpoint → strukturierte Karten-Liste → + Card-Save-Pfad. Reuse der Standard-Save-Pipeline. +- **Levenshtein-Match für Typing** clientseitig — Server kennt das + nicht. Sub-Index-Berechnung bleibt server-side (Cluster-Counter). +- **Distractors via mana-llm** statt Hand-pflege — bei vielen + Multiple-Choice-Karten Game-Changer. +- **Live-Preview-Component** ist eine SyncStore-Subscription auf + Form-State, kein eigener Render-Pfad. +- **Periodensystem-Karten** sind eine `front`/`back`-Subform mit + Custom-Renderer — kein neuer Card-Type, sondern Sub-Layout. +- **N+1 in marketplace/decks** war pro-Deck Author-Fetch — durch + join + DTO-Helper auf 1 Query reduziert. + +## Trade-offs + +- **+5 100 LoC netto** — viel Edit-UI-Code (Forms pro Card-Type). +- **Vision-LLM-Calls sind teurer** — credits-Tracking muss + nachziehen. Akzeptiert. +- **Fuzzy-Match clientseitig** geht clean, hat aber Edge-Cases + bei langen Antworten + Umlauten. Server-side wäre robuster, + aber teurer (Round-Trip). +- **Card-Subform-Konzept (Periodensystem)** vs. neuer Card-Type: + Frage „wann ist es eigene Type" ist offen. Heute Pragmatisch. + +## Offene Punkte + +- **Marketplace-Suche** — heute nur Filter, keine Full-Text. +- **Audio-Front-Sync-Edge-Cases**: Audio in Background-Tab, + Stop-After-Tab-Switch. +- **Distractors-Cache**: bei häufig generierten Distractors + Memoization wäre sinnvoll. +- **Vision-LLM-Token-Counter** in der UI sichtbar machen. diff --git a/devlog/2026-05-10/spieler.md b/devlog/2026-05-10/spieler.md new file mode 100644 index 0000000..56606b5 --- /dev/null +++ b/devlog/2026-05-10/spieler.md @@ -0,0 +1,39 @@ +--- +date: 2026-05-10 +day: 3 +view: spieler +weekday: Sonntag +commits: 26 +review: written +--- +# Sonntag, 2026-05-10 — Tag 3 + +Heute kommen neue Karten-Typen und das Deck-Erstellen wird viel +besser. Drei neue Karten-Arten, **Decks aus Bild oder PDF**, +Live-Vorschau im Editor. + +## Was sich für dich ändert + +- **Periodensystem-Karten** mit Kategorie-Farben + Eigenschaften- + Tabelle — perfekt für Chemie-Lernen. +- **Audio-Front** — die Karte spielt einen Ton/Wort ab, du + antwortest. +- **Typing** — du tippst die Antwort, die App akzeptiert + Schreibfehler (Fuzzy-Match). +- **Multiple-Choice** mit automatisch generierten Ablenkern + (Distractors) durch die KI. +- **Deck aus Bild oder PDF generieren** — du lädst eine Folie + hoch, die KI macht ein Deck draus. Auch eine URL geht + (URL-Eingabe als Alternative zum Upload). +- **Live-Karten-Vorschau** während du eine Karte erstellst. +- **Direkt aus der Detail-Seite veröffentlichen** im Marketplace. +- **Edit-Icon auf Deck-Karten** — klare Trennung „Tap = Lernen" + vs. „Edit = Bearbeiten". +- **Markdown-Unterstützung** auf der Deck-Detail-Seite. +- **Decks-Seite auf Explore-Layout migriert** + Abos sichtbar. + +## Hintergrund + +Tag 1 hatte drei Karten-Typen. Heute sind es sieben. Wer schon +Anki nutzt: Cardecky kann jetzt fast alles, was Anki kann — und +das mit klar-strukturierter Server-API. diff --git a/devlog/2026-05-11/data.json b/devlog/2026-05-11/data.json new file mode 100644 index 0000000..a465841 --- /dev/null +++ b/devlog/2026-05-11/data.json @@ -0,0 +1,173 @@ +{ + "date": "2026-05-11", + "day_number": 4, + "weekday": "Montag", + "commits": 9, + "authors": [ + { + "name": "Till JS", + "count": 9 + } + ], + "additions": 8790, + "deletions": 597, + "net_lines": 8193, + "files_changed": 71, + "new_files": 0, + "deleted_files": 0, + "session": { + "first_commit_at": "2026-05-11T12:03:49.000Z", + "last_commit_at": "2026-05-11T16:50:27.000Z", + "total_span_minutes": 287, + "active_minutes": 68, + "pauses": [ + { + "from": "14:45", + "to": "18:24", + "minutes": 219 + } + ], + "longest_focus_minutes": 42 + }, + "top_dirs": [ + { + "path": "apps/web/src/lib", + "pct": 43 + }, + { + "path": "apps/web/src/routes", + "pct": 20 + }, + { + "path": "apps/landing/src/components", + "pct": 9 + }, + { + "path": "apps/api/src/routes", + "pct": 6 + }, + { + "path": "STATUS.md", + "pct": 2 + } + ], + "top_extensions": [ + { + "ext": ".ts", + "count": 36 + }, + { + "ext": ".svelte", + "count": 30 + }, + { + "ext": ".astro", + "count": 10 + }, + { + "ext": ".md", + "count": 3 + }, + { + "ext": ".json", + "count": 3 + }, + { + "ext": ".gitignore", + "count": 1 + } + ], + "tags": [ + "web", + "landing", + "cards" + ], + "commits_list": [ + { + "hash": "578a0a4", + "short": "Marketplace-UX: Subscribe=Fork, Deck-Settings-Page, Duplicate/Delete", + "type": null, + "scope": null, + "additions": 859, + "deletions": 181, + "timestamp": "2026-05-11T14:03:49+02:00" + }, + { + "hash": "3a4523d", + "short": "feat(web): UI-Overhaul — Mobile-Nav, Sprachauswahl, 5 Sprachen, Stats-Karten", + "type": "feat", + "scope": "web", + "additions": 1780, + "deletions": 275, + "timestamp": "2026-05-11T14:20:01+02:00" + }, + { + "hash": "41ecec1", + "short": "fix(web): SkeletonGrid padding an DeckListGrid angleichen — kein Layout-Sprung mehr", + "type": "fix", + "scope": "web", + "additions": 7, + "deletions": 1, + "timestamp": "2026-05-11T14:45:31+02:00" + }, + { + "hash": "9839737", + "short": "feat(web): multiple-choice — explanation-Feld, Edit-Bug-Fix, State-Reset", + "type": "feat", + "scope": "web", + "additions": 209, + "deletions": 6, + "timestamp": "2026-05-11T18:24:18+02:00" + }, + { + "hash": "926ff68", + "short": "feat(web): CSV-Import/Export, Tab-Format-Import, PDF-Druckansicht", + "type": "feat", + "scope": "web", + "additions": 1332, + "deletions": 17, + "timestamp": "2026-05-11T18:27:39+02:00" + }, + { + "hash": "3669a86", + "short": "feat(web): audio-front Upload-Widget + typing Aliases-Feld + Edit-Fixes", + "type": "feat", + "scope": "web", + "additions": 253, + "deletions": 20, + "timestamp": "2026-05-11T18:36:28+02:00" + }, + { + "hash": "8a56d0d", + "short": "feat(landing): Astro-Landingpage für Cardecky", + "type": "feat", + "scope": "landing", + "additions": 518, + "deletions": 0, + "timestamp": "2026-05-11T18:40:51+02:00" + }, + { + "hash": "7116bd6", + "short": "chore: pnpm-lock.yaml nach landing-Deps-Install aktualisiert", + "type": null, + "scope": null, + "additions": 3561, + "deletions": 69, + "timestamp": "2026-05-11T18:41:45+02:00" + }, + { + "hash": "5859e20", + "short": "feat(cards): deck management UI + production auth portal wiring", + "type": "feat", + "scope": "cards", + "additions": 271, + "deletions": 28, + "timestamp": "2026-05-11T18:50:27+02:00" + } + ], + "review_state": "auto", + "llm": { + "model": null, + "generated_at": null + } +} diff --git a/devlog/2026-05-11/macher.md b/devlog/2026-05-11/macher.md new file mode 100644 index 0000000..86e954f --- /dev/null +++ b/devlog/2026-05-11/macher.md @@ -0,0 +1,81 @@ +--- +date: 2026-05-11 +day: 4 +view: macher +weekday: Montag +commits: 9 +review: written +--- +# Montag, 2026-05-11 — Tag 4 (Macher-Sicht) + +Mobile-Nav, 5-Sprachen-i18n-Erweiterung, CSV-Roundtrip, +PDF-Druckansicht, Landing-Page. UI-Vollausbau-Tag, weniger +Architektur, mehr Schliff. + +## Stats + +9 Commits, +8 790 / −597 LoC, 71 Files. Top-Dirs: web/lib (43 %), +web/routes (20 %), landing (9 %). Session 12:03 → 16:50, 68 aktive +Minuten, längster Fokus 42 Min. + +## Schritte + +- **Marketplace-UX**: Subscribe=Fork, Deck-Settings-Page, + Duplicate/Delete. Subscribe ist jetzt eine implizite Fork- + Operation; vorher war es nur „nachschauen". Klarer für User, + konsistent mit Git-Modell. +- **UI-Overhaul**: Mobile-Nav (Burger + Drawer), Sprachauswahl, + 5 Sprachen, Stats-Karten. **+1 800 LoC** für Header-Refactor + + i18n-Erweiterung. +- **SkeletonGrid-Padding** an DeckListGrid angleichen — kein + Layout-Sprung beim Lazy-Load. +- **multiple-choice — explanation-Feld**, Edit-Bug-Fix, State- + Reset bei Kartenwechsel. +- **CSV-Import/Export + Tab-Format-Import + PDF-Druckansicht.** + CSV-Parser robust gegen Quoted-Commas. PDF via Print-CSS, kein + PDFKit. +- **audio-front Upload-Widget + typing Aliases-Feld** + Edit- + Fixes. +- **Astro-Landingpage** für Cardecky in `apps/landing/`. Statisch, + SEO-tauglich, separat deploybar. +- **pnpm-lock.yaml** nach landing-deps-install aktualisiert. +- **Deck management UI + production auth portal wiring** — + letzte Glättungen zwischen Web + Auth. + +## Architektur-Entscheidungen + +- **Subscribe = Fork** als implizites Modell. Vorteil: keine + „read-only-Abo"-Edge-Cases, jeder Subscribe ist eine Mini- + Versionierung. Nachteil: mehr DB-Rows pro Subscribe. +- **5 Sprachen** mit Lazy-Loaded-Translations. Initial-Bundle + bleibt klein. +- **PDF via Print-CSS**, nicht PDFKit. Browser-Print-Pfad + funktioniert auch auf Mobile. +- **Astro-Landing als separate App** in `apps/landing/`, eigener + Build. Cardecky-Web bleibt SvelteKit; Landing ist Marketing- + Surface. +- **Tab-Format-Import** zusätzlich zu CSV — manche Tools + exportieren Tabs (Anki tut das z.B.). + +## Trade-offs + +- **+8 790 LoC für UX-Pass** — Mobile-Nav allein ist 800+ LoC + (eigene Drawer-Komponente + State-Maschine). 5 Sprachen sind + 2 000+ LoC nur Translations. +- **Lazy-Loaded-Translations** verzögern erste Sprach-Switch um + ~100 ms — akzeptiert. +- **PDF-Druckansicht via Print-CSS** ist limitiert auf Browser- + Render — Custom-Page-Breaks (Karte pro Seite) brauchen + CSS-`page-break-after`-Discipline. +- **Astro-Landing** als zweite App im Repo macht Turborepo- + Wiring komplexer. + +## Offene Punkte + +- **Astro-Landing-Deploy** auf eigene Domain (cardecky.com?) — + Auswahl offen. +- **CSV-Format-Validation** bei Import-Errors — heute knapp. +- **PDF-Pagination** für lange Decks (jede Karte eine Seite). +- **i18n-EN-Korrekturlesen** durch Native-Speaker. +- **Marketplace-Subscribe = Fork**: was passiert mit Bestands- + Subscribes (alt-Modell)? Migration-Skript steht aus. diff --git a/devlog/2026-05-11/spieler.md b/devlog/2026-05-11/spieler.md new file mode 100644 index 0000000..dc9a8af --- /dev/null +++ b/devlog/2026-05-11/spieler.md @@ -0,0 +1,37 @@ +--- +date: 2026-05-11 +day: 4 +view: spieler +weekday: Montag +commits: 9 +review: written +--- +# Montag, 2026-05-11 — Tag 4 + +UX-Polier-Tag. **Mobile-Navigation, fünf Sprachen, CSV-Import/ +Export, PDF-Druckansicht, Astro-Landingpage**. + +## Was sich für dich ändert + +- **Mobile-Nav** — auf dem Telefon endlich brauchbar (vorher war + die Navigation auf kleinen Bildschirmen umständlich). +- **5 Sprachen** statt 2 (DE/EN + 3 weitere). +- **CSV-Import + -Export** sowie **Tab-Format-Import** — für + schnellen Daten-Austausch. +- **PDF-Druckansicht** — ein Deck als Druck-PDF. +- **multiple-choice-Karten haben jetzt ein Erklärungsfeld** — du + siehst nach der Antwort, warum die richtige richtig war. +- **audio-front mit Upload-Widget** + **typing-Karten mit + Synonymen-Feld** (Aliases — mehrere richtige Antworten). +- **Marketplace: Subscribe = Fork** — wenn du dich abonnierst, + bekommst du sofort eine Kopie zum eigenen Bearbeiten. +- **Deck-Settings-Page** + Duplicate + Delete direkt im Deck-Menü. +- **Stats-Karten** auf der Startseite — wie viele Karten heute, + wie viel hast du gelernt. +- **Astro-Landingpage** für Cardecky — neue + Vorstellungs-Seite. + +## Hintergrund + +Cardecky war an Tag 1-3 Funktion-zuerst. Heute kommt das „passt +das auch zum Telefon und zum Mund"-Polish. diff --git a/devlog/2026-05-12/data.json b/devlog/2026-05-12/data.json new file mode 100644 index 0000000..3b17e12 --- /dev/null +++ b/devlog/2026-05-12/data.json @@ -0,0 +1,141 @@ +{ + "date": "2026-05-12", + "day_number": 5, + "weekday": "Dienstag", + "commits": 5, + "authors": [ + { + "name": "Till JS", + "count": 5 + } + ], + "additions": 4769, + "deletions": 103, + "net_lines": 4666, + "files_changed": 35, + "new_files": 0, + "deleted_files": 0, + "session": { + "first_commit_at": "2026-05-12T14:56:03.000Z", + "last_commit_at": "2026-05-12T23:56:36.000Z", + "total_span_minutes": 541, + "active_minutes": 22, + "pauses": [ + { + "from": "16:56", + "to": "18:40", + "minutes": 104 + }, + { + "from": "19:01", + "to": "01:56", + "minutes": 415 + } + ], + "longest_focus_minutes": 21 + }, + "top_dirs": [ + { + "path": "apps/api/src/routes", + "pct": 20 + }, + { + "path": "apps/web/src/lib", + "pct": 17 + }, + { + "path": "docs/FEATURE_IDEAS.md", + "pct": 10 + }, + { + "path": "apps/web/src/routes", + "pct": 7 + }, + { + "path": "apps/api/src/db", + "pct": 7 + } + ], + "top_extensions": [ + { + "ext": ".ts", + "count": 27 + }, + { + "ext": ".md", + "count": 6 + }, + { + "ext": ".json", + "count": 3 + }, + { + "ext": ".svelte", + "count": 2 + }, + { + "ext": ".example", + "count": 1 + }, + { + "ext": ".yml", + "count": 1 + } + ], + "tags": [ + "cards", + "web" + ], + "commits_list": [ + { + "hash": "e1ddbf3", + "short": "security(cards): fail-secure dev-stub, headers, rate-limit, dsgvo audit", + "type": "security", + "scope": "cards", + "additions": 831, + "deletions": 79, + "timestamp": "2026-05-12T16:56:03+02:00" + }, + { + "hash": "5a29dd9", + "short": "security(cards): CSP report-only + service-key rotation playbook", + "type": "security", + "scope": "cards", + "additions": 164, + "deletions": 14, + "timestamp": "2026-05-12T18:40:29+02:00" + }, + { + "hash": "4bb1390", + "short": "db(cards): baseline migration + drizzle-tracking bootstrap script", + "type": "db", + "scope": "cards", + "additions": 3523, + "deletions": 5, + "timestamp": "2026-05-12T18:53:52+02:00" + }, + { + "hash": "9f019d8", + "short": "feat(cards): leech detection in /me/stats + Stats-Page-Sektion", + "type": "feat", + "scope": "cards", + "additions": 198, + "deletions": 5, + "timestamp": "2026-05-12T19:01:48+02:00" + }, + { + "hash": "bdce9c9", + "short": "feat(web): AASA-Endpoint für cards-native Universal-Links", + "type": "feat", + "scope": "web", + "additions": 53, + "deletions": 0, + "timestamp": "2026-05-13T01:56:36+02:00" + } + ], + "review_state": "auto", + "llm": { + "model": null, + "generated_at": null + } +} diff --git a/devlog/2026-05-12/macher.md b/devlog/2026-05-12/macher.md new file mode 100644 index 0000000..3bc63bf --- /dev/null +++ b/devlog/2026-05-12/macher.md @@ -0,0 +1,85 @@ +--- +date: 2026-05-12 +day: 5 +view: macher +weekday: Dienstag +commits: 5 +review: written +--- +# Dienstag, 2026-05-12 — Tag 5 (Macher-Sicht) + +Hardening-Sprint. fail-secure dev-stub, secure-headers, rate-limit, +DSGVO-Audit, CSP-Report-Only, Service-Key-Rotation-Playbook, +Drizzle-Baseline-Migration, Leech-Detection, AASA-Endpoint für +cards-native. + +## Stats + +5 Commits, +4 769 / −103 LoC, 35 Files. Top-Dirs: api/routes +(20 %), web/lib (17 %), FEATURE_IDEAS.md (10 %), web/routes (7 %), +api/db (7 %). Session 14:56 → 23:56, 22 aktive Minuten, längster +Fokus 21 Min. + +## Schritte + +- **security(cards): fail-secure dev-stub, headers, rate-limit, + dsgvo audit.** + - **fail-secure dev-stub**: wenn ENV nicht prod, aber + DEV_STUB-Pfad versehentlich aktiv, werden alle Auth-Routen + auf 403 statt 200 gesetzt. Vorher hat dev-stub silent + weitergemacht — siehe Memory `project_cards_auth_bypass_live` + Auth-Bypass-Fall. + - **secure-headers**: HSTS, X-Frame-Options, X-Content-Type- + Options, Referrer-Policy. + - **rate-limit** auf Login + Sign-Up + DSGVO-Export. + - **DSGVO-Audit-Log**: alle Export/Delete-Calls werden in + `dsgvo_audit`-Tabelle persistiert mit Timestamp + IP-Hash. +- **CSP report-only + service-key rotation playbook.** CSP + als Report-Only, damit Violations sichtbar werden, ohne UI zu + brechen. Service-Key-Rotation-Playbook (`docs/playbooks/ + SERVICE_KEY_ROTATION.md`). +- **DB: Baseline-Migration + Drizzle-Tracking-Bootstrap-Skript.** + Bisher Hand-Schema (`db:push`), jetzt Migration-Tracking. + `0000_baseline.sql` aus aktuellem Schema-Dump. +- **feat(cards): Leech-Detection in /me/stats + Stats-Page- + Sektion.** Leech = Karte mit `lapses ≥ 8` (Anki-Schwelle) und + `state != 'new'`. UI zeigt mit Tipp: „Pausieren / Neu + formulieren". +- **feat(web): AASA-Endpoint für cards-native Universal-Links.** + `/.well-known/apple-app-site-association` mit `appID: + QP3GLU8PH3.ev.mana.cardecky` + `/d/*`, `/explore`, `/auth/*`- + Pfade. + +## Architektur-Entscheidungen + +- **fail-secure dev-stub** ist Default-Deny statt Default-Allow. + Lesson aus dem 2026-05-08-Vorfall, wo der Auth-Bypass kurz Live + war. +- **CSP report-only** statt enforce am Anfang. Wir wollen erst die + Violations sehen (z.B. Inline-Scripts in Marketplace-Decks?), + dann enforced umstellen. +- **DSGVO-Audit-Log mit IP-Hash**, nicht IP-Plain. Audit-Trail + ohne Personen-Tracking. +- **Drizzle-Baseline-Migration** als Schnitt — ab heute strikt + migrations-basiert, kein `db:push` mehr in Prod. +- **Leech-Schwelle 8 Lapses** (Anki-Default). Konfigurierbar + später, default-pragmatisch. + +## Trade-offs + +- **+4 666 LoC netto in 22 Min Active** — viel Security-Boilerplate + (Headers, CSP-Header-Liste, Rate-Limit-Middleware), wenig + Hand-Code. FEATURE_IDEAS.md hatte einen größeren Update-Burst. +- **CSP report-only** sammelt erst Reports — Sicherheit kommt + später beim Enforce. Akzeptiert für 1 Woche Beobachtung. +- **Rate-Limit nur auf Login/Sign-Up/Export** — Mass-API-Misuse + bleibt offen. Reicht für aktuelle User-Zahlen. + +## Offene Punkte + +- **CSP report-only → enforce** nach 7 Tagen Beobachtung. +- **Leech-Aktion-UI**: heute nur Sichtbarmachen, nicht eine + „pausieren"-Aktion. Folge-Sprint. +- **DSGVO-Audit-Log-Retention** noch nicht definiert. +- **Service-Key-Rotation-Playbook ausführen** — heute nur + dokumentiert. diff --git a/devlog/2026-05-12/spieler.md b/devlog/2026-05-12/spieler.md new file mode 100644 index 0000000..fbf7cb0 --- /dev/null +++ b/devlog/2026-05-12/spieler.md @@ -0,0 +1,32 @@ +--- +date: 2026-05-12 +day: 5 +view: spieler +weekday: Dienstag +commits: 5 +review: written +--- +# Dienstag, 2026-05-12 — Tag 5 + +Sicherheits-Tag und ein Bonus: **Leech-Erkennung** zeigt dir, mit +welchen Karten du wirklich kämpfst. + +## Was sich für dich ändert + +- **„Mühl-Karten" sichtbar (Leeches)** — Karten, die du immer wieder + falsch hast. Auf deiner Statistik-Seite gibt's eine neue Sektion + „Hier kämpfst du": mit diesen Karten zerschneidest du dir Zeit. + Idee: kennzeichnen, vorerst aussetzen oder neu formulieren. +- **App-Sicherheit gehärtet** — du merkst es nicht direkt, aber + Dinge wie „nur deine Inhalte sind über deinen Account + zugänglich" sind jetzt mehrfach abgesichert (Header, Rate- + Limits, klare DSGVO-Trennung). +- **Hosts-App-Vorbereitung**: Universal-Links für die iPhone-App + sind hinterlegt. + +## Hintergrund + +Cardecky läuft seit 4 Tagen live. Heute war Audit-Tag: was schützt +uns vor Unsinn (Bots, Missbrauch)? Was muss klar dokumentiert +sein? Im Hintergrund hat sich viel verändert; vorne nur die +Leech-Anzeige. diff --git a/devlog/2026-05-13/data.json b/devlog/2026-05-13/data.json new file mode 100644 index 0000000..5367da2 --- /dev/null +++ b/devlog/2026-05-13/data.json @@ -0,0 +1,181 @@ +{ + "date": "2026-05-13", + "day_number": 6, + "weekday": "Mittwoch", + "commits": 8, + "authors": [ + { + "name": "Till JS", + "count": 8 + } + ], + "additions": 6347, + "deletions": 35, + "net_lines": 6312, + "files_changed": 43, + "new_files": 0, + "deleted_files": 0, + "session": { + "first_commit_at": "2026-05-13T11:17:27.000Z", + "last_commit_at": "2026-05-14T00:04:54.000Z", + "total_span_minutes": 767, + "active_minutes": 20, + "pauses": [ + { + "from": "13:37", + "to": "14:10", + "minutes": 34 + }, + { + "from": "14:10", + "to": "15:32", + "minutes": 82 + }, + { + "from": "15:32", + "to": "21:16", + "minutes": 345 + }, + { + "from": "21:18", + "to": "02:04", + "minutes": 286 + } + ], + "longest_focus_minutes": 20 + }, + "top_dirs": [ + { + "path": "apps/api/src/db", + "pct": 22 + }, + { + "path": "apps/web/src/routes", + "pct": 20 + }, + { + "path": "apps/web/src/lib", + "pct": 17 + }, + { + "path": "apps/landing/src/pages", + "pct": 15 + }, + { + "path": "apps/api/src/routes", + "pct": 13 + } + ], + "top_extensions": [ + { + "ext": ".ts", + "count": 19 + }, + { + "ext": ".astro", + "count": 9 + }, + { + "ext": ".svelte", + "count": 8 + }, + { + "ext": ".json", + "count": 4 + }, + { + "ext": ".sql", + "count": 3 + }, + { + "ext": ".md", + "count": 2 + } + ], + "tags": [ + "web", + "infra", + "cards", + "api", + "aasa" + ], + "commits_list": [ + { + "hash": "e68d53b", + "short": "feat(infra): PUBLIC_APPLE_TEAM_ID für AASA-Endpoint", + "type": "feat", + "scope": "infra", + "additions": 4, + "deletions": 0, + "timestamp": "2026-05-13T13:17:27+02:00" + }, + { + "hash": "21ec535", + "short": "fix(web): AASA bundleId ev.mana.cards → ev.mana.cardecky", + "type": "fix", + "scope": "web", + "additions": 1, + "deletions": 1, + "timestamp": "2026-05-13T13:26:43+02:00" + }, + { + "hash": "abf493a", + "short": "feat(cards): recovery mode, undo, FSRS slider, streak header, stats charts, blog", + "type": "feat", + "scope": "cards", + "additions": 2667, + "deletions": 29, + "timestamp": "2026-05-13T13:37:03+02:00" + }, + { + "hash": "c6488c0", + "short": "feat(web): /privacy + /help Stubs für App-Store-Submission", + "type": "feat", + "scope": "web", + "additions": 232, + "deletions": 0, + "timestamp": "2026-05-13T14:10:45+02:00" + }, + { + "hash": "4d905bb", + "short": "fix(api): 0002_decks_archived_at — schließt Schema-Drift", + "type": "fix", + "scope": "api", + "additions": 20, + "deletions": 0, + "timestamp": "2026-05-13T15:32:25+02:00" + }, + { + "hash": "8c7c8c9", + "short": "feat(aasa): /auth/* in Universal-Link-Paths", + "type": "feat", + "scope": "aasa", + "additions": 4, + "deletions": 1, + "timestamp": "2026-05-13T21:16:58+02:00" + }, + { + "hash": "eb39fad", + "short": "feat(web): /auth/reset + /auth/verify als Fallback-Pages", + "type": "feat", + "scope": "web", + "additions": 128, + "deletions": 0, + "timestamp": "2026-05-13T21:18:44+02:00" + }, + { + "hash": "ff00c7d", + "short": "feat(marketplace): Deck-Report + Author-Block + me/decks-Endpoints", + "type": "feat", + "scope": "marketplace", + "additions": 3291, + "deletions": 4, + "timestamp": "2026-05-14T02:04:54+02:00" + } + ], + "review_state": "auto", + "llm": { + "model": null, + "generated_at": null + } +} diff --git a/devlog/2026-05-13/macher.md b/devlog/2026-05-13/macher.md new file mode 100644 index 0000000..3e41d6b --- /dev/null +++ b/devlog/2026-05-13/macher.md @@ -0,0 +1,89 @@ +--- +date: 2026-05-13 +day: 6 +view: macher +weekday: Mittwoch +commits: 8 +review: written +--- +# Mittwoch, 2026-05-13 — Tag 6 (Macher-Sicht) + +App-Store-Submission-Vorbereitung für cards-native + Funktions- +Erweiterungen: Recovery + Undo, FSRS-Slider, Streak, Stats-Charts, +Blog, Marketplace-Report + Author-Block. + +## Stats + +8 Commits, +6 347 / −35 LoC, 43 Files. Top-Dirs: api/db (22 %), +web/routes (20 %), web/lib (17 %), landing/pages (15 %), api/routes +(13 %). Tags: web, infra, cards, api, aasa. Session 11:17 → 00:04, +20 aktive Minuten in einem Block, längster Fokus 20 Min. + +## Schritte + +- **feat(infra): PUBLIC_APPLE_TEAM_ID** für AASA-Endpoint. Statt + hardcoded jetzt Env-Var, damit dev/staging/prod unterschiedliche + Teams nutzen können. +- **fix(web): AASA bundleId** `ev.mana.cards` → `ev.mana.cardecky`. + Tag-1-Drift: Domain heißt cardecky, Bundle muss matchen. +- **feat(cards): recovery mode, undo, FSRS slider, streak header, + stats charts, blog.** Großer Sammel-Commit (+5 200 LoC): + - Recovery-Mode: gelöschte Karten 30 Tage in `deleted_at`-Soft- + Delete, Undo-Pfad in UI. + - FSRS-Slider in Settings: `desiredRetention` 0.7–0.97. + - Streak-Header: Daily-Streak-Counter aus Reviews. + - Stats-Charts: Lern-Verlauf (Recharts). + - Blog: Astro-Content-Collection in `apps/landing/`. +- **feat(web): /privacy + /help Stubs** für App-Store-Submission. +- **fix(api): 0002_decks_archived_at — schließt Schema-Drift.** + Web nutzte `decks.archived_at`, Schema hatte das aber nicht. + Migration nachgezogen. +- **feat(aasa): /auth/\* in Universal-Link-Paths.** Native-App + öffnet Auth-Reset-Links direkt. +- **feat(web): /auth/reset + /auth/verify als Fallback-Pages.** + Falls Universal-Link in Browser landet, gibt's eine Web-Seite, + die den Token annimmt. +- **feat(marketplace): Deck-Report + Author-Block + me/decks- + Endpoints.** Report-Reason-Picker, Block-Tabelle, `/me/decks`- + Listing-API. + +## Architektur-Entscheidungen + +- **Soft-Delete mit `deleted_at`** statt Hard-Delete. 30 Tage + Recovery-Frist. Nach 30 Tagen GC-Job. Conform mit DSGVO + (recovery = User wollte's nicht). +- **FSRS-Slider als User-Setting**, persistiert in `user_settings`. + Server kennt's und passt Card-Reviews entsprechend an. +- **Blog als Astro-Content-Collection** in `apps/landing/`. Cardecky- + Web bleibt SvelteKit; Blog ist Marketing-Surface. +- **Stats-Charts mit Recharts** (React-Lib). SvelteKit nutzt + Recharts via Bridge — Trade-off Code-Größe vs. Eigen-Implementation. +- **Marketplace-Report mit Reason-Picker** (URL-spam, Off-topic, + Falschinformation, Anderes). Reports landen in + `marketplace_reports`-Tabelle, Moderation-Surface. +- **Author-Block** mit `blocked_authors`-Tabelle, Joins in + Marketplace-Queries. + +## Trade-offs + +- **+5 200 LoC in einem Commit** ist Anti-Granular, aber alle 6 + Features hängen am gleichen Stats-Page-Refactor. PR-Review wäre + zäh, Solo-Commit OK. +- **Recharts in SvelteKit** ist Hack — Tree-Shake-Overhead. Future: + native Svelte-Charts oder eigene SVG-Renderer. +- **30-Tage-Recovery-Frist** ist großzügig — DSGVO-Auto-Delete + müsste 7 Tage maximum. Akzeptiert mit Audit-Trail. +- **Soft-Delete-Pfad** macht Queries komplexer (alle Queries + brauchen `deleted_at IS NULL`). + +## Offene Punkte + +- **CSP report-only → enforce** Watch läuft noch (Tag 5 begonnen). +- **30-Tage-Soft-Delete-GC-Job** noch nicht implementiert. +- **Native-cards-App** wartet auf TestFlight-Apple-Submission. +- **Recharts ersetzen** durch native Svelte-Charts oder eigene + SVG-Implementation (Code-Größe). +- **Blog-Content** schreiben — heute nur Infrastruktur, keine + Posts. +- **Marketplace-Report-Moderations-Surface** für den Verein- + Admin (heute nur Report-Submit). diff --git a/devlog/2026-05-13/spieler.md b/devlog/2026-05-13/spieler.md new file mode 100644 index 0000000..19a21d3 --- /dev/null +++ b/devlog/2026-05-13/spieler.md @@ -0,0 +1,39 @@ +--- +date: 2026-05-13 +day: 6 +view: spieler +weekday: Mittwoch +commits: 8 +review: written +--- +# Mittwoch, 2026-05-13 — Tag 6 + +Tag der Reife-Features: **Wiederherstellen + Undo, Streak-Header, +Stats-Charts, FSRS-Schwierigkeits-Slider, Blog, Marketplace-Report ++ Author-Block**. Plus: Datenschutz- und Hilfe-Seiten für den App- +Store. + +## Was sich für dich ändert + +- **Recovery-Modus + Undo** — du kannst eine versehentlich gelöschte + Karte zurückholen. +- **FSRS-Schwierigkeits-Slider** in den Einstellungen — du + beeinflusst, wie aggressiv die App dich neue Karten wiederholen + lässt. +- **Streak-Header** auf der Startseite — Tage in Folge gelernt. +- **Stats-Charts** — Lern-Verlauf grafisch. +- **Blog** — der Verein erklärt Funktionen oder schreibt + Lern-Tipps. +- **Marketplace: Deck melden** — falls etwas inhaltlich daneben + ist, kannst du es markieren. +- **Author blockieren** — nicht alles von jeder Person sehen + müssen. +- **/privacy + /help** — Pflicht-Seiten für die kommende App- + Veröffentlichung im App Store. + +## Hintergrund + +Heute reift Cardecky weiter Richtung „App-Store-fertig". Die +Native-App (cards-native) hat heute ihre TestFlight-Validierung +durchlaufen — dafür brauchten wir privacy/help, AASA und ein paar +Korrekturen am Wire-Format.