devlog: 6 Tage geschrieben (Greenfield → Hardening + Cardecky-Native-Vorbereitung)
Some checks failed
CI / validate (push) Has been cancelled
Some checks failed
CI / validate (push) Has been cancelled
Tag 1: Phase 0–10c Marathon, Live-Cut auf cardecky.mana.how. Tag 2: Marketplace-Restore (Phase 12 R0–R5 + G1–G4). Tag 3: Karten-Typ-Vollausbau (Periodensystem, audio, typing, multiple-choice, Vision-LLM-Deck-Generation). Tag 4: Mobile-Nav + 5 Sprachen + CSV/PDF + Astro-Landing. Tag 5: Security-Hardening (fail-secure, CSP, DSGVO-Audit, rate-limit) + Leech-Detection + AASA. Tag 6: Recovery + Undo + FSRS-Slider + Streak + Stats-Charts + Blog + Marketplace-Report + Privacy/Help. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ff00c7d961
commit
ac05afa93e
18 changed files with 2376 additions and 0 deletions
513
devlog/2026-05-08/data.json
Normal file
513
devlog/2026-05-08/data.json
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
122
devlog/2026-05-08/macher.md
Normal file
122
devlog/2026-05-08/macher.md
Normal file
|
|
@ -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.
|
||||
40
devlog/2026-05-08/spieler.md
Normal file
40
devlog/2026-05-08/spieler.md
Normal file
|
|
@ -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.
|
||||
253
devlog/2026-05-09/data.json
Normal file
253
devlog/2026-05-09/data.json
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
83
devlog/2026-05-09/macher.md
Normal file
83
devlog/2026-05-09/macher.md
Normal file
|
|
@ -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/<deck-slug>`, `/u/<user-
|
||||
slug>`, `/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.
|
||||
39
devlog/2026-05-09/spieler.md
Normal file
39
devlog/2026-05-09/spieler.md
Normal file
|
|
@ -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.
|
||||
324
devlog/2026-05-10/data.json
Normal file
324
devlog/2026-05-10/data.json
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
105
devlog/2026-05-10/macher.md
Normal file
105
devlog/2026-05-10/macher.md
Normal file
|
|
@ -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.
|
||||
39
devlog/2026-05-10/spieler.md
Normal file
39
devlog/2026-05-10/spieler.md
Normal file
|
|
@ -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.
|
||||
173
devlog/2026-05-11/data.json
Normal file
173
devlog/2026-05-11/data.json
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
81
devlog/2026-05-11/macher.md
Normal file
81
devlog/2026-05-11/macher.md
Normal file
|
|
@ -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.
|
||||
37
devlog/2026-05-11/spieler.md
Normal file
37
devlog/2026-05-11/spieler.md
Normal file
|
|
@ -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.
|
||||
141
devlog/2026-05-12/data.json
Normal file
141
devlog/2026-05-12/data.json
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
85
devlog/2026-05-12/macher.md
Normal file
85
devlog/2026-05-12/macher.md
Normal file
|
|
@ -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.
|
||||
32
devlog/2026-05-12/spieler.md
Normal file
32
devlog/2026-05-12/spieler.md
Normal file
|
|
@ -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.
|
||||
181
devlog/2026-05-13/data.json
Normal file
181
devlog/2026-05-13/data.json
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
89
devlog/2026-05-13/macher.md
Normal file
89
devlog/2026-05-13/macher.md
Normal file
|
|
@ -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).
|
||||
39
devlog/2026-05-13/spieler.md
Normal file
39
devlog/2026-05-13/spieler.md
Normal file
|
|
@ -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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue