Code + Identity-Rename zur Vorbereitung auf Apple-Dev-Portal-Aktion (Bundle ev.mana.wordeck, App-Group group.ev.mana.wordeck, AASA applinks:wordeck.com). Build bleibt funktional, aber gegen die neue text-only-API können image-occlusion-Creates 422 zurückgeben — das wird mit der Wordeck-Native v1.0-Welle (parallele Apple-Aktion) sauber gemacht. Umbenennung: - 41 Files: cardecky/Cardecky → wordeck/Wordeck (Display, Strings, Kommentare) - 57 Files: CardsNative → WordeckNative, CardsAPI → WordeckAPI, CardsTheme → WordeckTheme, CardsBrand → WordeckBrand, CardsWidget → WordeckWidget, CardsDueWidget → WordeckDueWidget - Bundle-ID ev.mana.cardecky → ev.mana.wordeck (project.yml, Info.plist, entitlements, Keychain-Service, App-Group) - AASA applinks:cardecky.mana.how → applinks:wordeck.com - API-Base cardecky-api.mana.how → api.wordeck.com - 10 Files renamed (App-Entry, API-Extensions, Theme, Widget, Entitlements, Tests) - xcodeproj regenerated via xcodegen → WordeckNative.xcodeproj - MaskRegionsTests.swift gelöscht (image-occlusion entfällt mit Wordeck text-only) Forgejo-Repo git.mana.how/till/cards-native → wordeck-native umbenannt (Auto-Redirect aktiv). Lokales Verzeichnis Code/cards-native/ bleibt vorerst — wird beim nächsten Apple-Setup mit Bundle-Test umbenannt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
183 lines
7.3 KiB
Markdown
183 lines
7.3 KiB
Markdown
# CLAUDE.md — wordeck-native repo
|
|
|
|
Guidance für Claude Code in diesem Repository.
|
|
|
|
> **Wenn du gerade neu bist:** lies zuerst [`PLAN.md`](PLAN.md) und
|
|
> `../mana/docs/playbooks/CARDS_NATIVE_GREENFIELD.md` (übergeordneter
|
|
> Greenfield-Plan). Dieses CLAUDE.md ist die Konventions- und
|
|
> Cross-Repo-Referenz.
|
|
|
|
## Was dieses Repo ist
|
|
|
|
**Cards Native** — native SwiftUI-Universal-App (iOS / iPadOS / macOS)
|
|
für **Wordeck**, die Spaced-Repetition-Karten-App des Vereins
|
|
**mana e.V.** Web-Parität zu `wordeck.com`, plus native iOS-
|
|
Affordances (Widgets, Notifications, Universal-Links, Pencil).
|
|
|
|
```
|
|
HTTPS/JWT ┌──────────────────┐
|
|
cards-api ◄───────────── │ wordeck-native │ SwiftUI
|
|
api.wordeck.com │ (this repo) │ SwiftData (Cache)
|
|
│ ev.mana.wordeck │ WidgetKit (β-6)
|
|
└──────────────────┘
|
|
```
|
|
|
|
## Status
|
|
|
|
**Phase β-0 — Setup (2026-05-12).** Repo-Skelett, ManaCore + ManaTokens
|
|
als Package-Dependency, Login + Wordeck-API-Reachability-Probe.
|
|
Phasen β-1 bis β-7 in `../mana/docs/playbooks/CARDS_NATIVE_GREENFIELD.md`.
|
|
|
|
## Leitprinzip: Web-Parität
|
|
|
|
Die Web-App auf `wordeck.com` ist Funktions-Referenz. Bei
|
|
Konflikt zwischen Native und Web → **Web gewinnt**. Native ist
|
|
Re-Implementation, kein neues Produkt.
|
|
|
|
Datenmodell, FSRS-Verhalten, Marketplace-Slugs, Sharing-URLs:
|
|
identisch zu Web.
|
|
|
|
## Architektonische Invarianten
|
|
|
|
Beschlossen. Nicht ohne explizite Diskussion antasten.
|
|
|
|
1. **Server-authoritative FSRS.** Grading-Calls gehen *immer* an
|
|
`POST /api/v1/reviews/:cardId/:subIndex/grade`. Kein lokaler
|
|
ts-fsrs-Port.
|
|
2. **Offline-Read, Online-Write.** Decks + Due-Cards via SwiftData
|
|
gecacht (offline sichtbar). Grades werden bei Offline in einer
|
|
lokalen Queue persistiert und beim Reconnect der Reihe nach
|
|
abgesendet.
|
|
3. **mana-auth via ManaCore.** `import ManaCore`,
|
|
`AuthClient(config: AppConfig.manaAppConfig)`. Eigene
|
|
Auth-Implementierung ist verboten.
|
|
4. **Pure SwiftUI.** Keine externen UI-Libraries. AppKit/UIKit nur
|
|
als Bridge wenn zwingend (z.B. `PencilKit` für Image-Occlusion).
|
|
5. **Bundle-ID `ev.mana.wordeck`.** Reverse-Domain mana-ev.ch.
|
|
Universal-Link-Domain: `wordeck.com`.
|
|
6. **Cards-Domain-Logik bleibt am Server.** SubIndex-Berechnung für
|
|
Cloze, Image-Occlusion-Mask-Validation, Content-Hash — alles
|
|
Server. Native zeigt nur, was vom Server kommt.
|
|
7. **`forest`-Theme.** Heute lokal in `WordeckTheme.swift` nachgebaut
|
|
(Werte gespiegelt aus `mana/packages/themes/src/variants/forest.css`).
|
|
Migration auf ManaTokens-Theme-Switch ist Phase ε.
|
|
8. **Web gewinnt bei Konflikt.** Eleganteres Native-Verhalten geht
|
|
zuerst in die Web-App, dann nach hier.
|
|
|
|
## Konventionen
|
|
|
|
- **Swift 6.0**, Strict Concurrency komplett
|
|
- **iOS 18 / iPadOS 18 / macOS 15** Minimum
|
|
- **SwiftUI** als einziges UI-Framework
|
|
- **XcodeGen** als SOT: `project.yml` definiert Targets, Info.plist,
|
|
Entitlements. `.xcodeproj`, generierte Info.plist und Entitlements
|
|
sind **nicht** im Git
|
|
- **SwiftFormat** mit `.swiftformat` (4-space, 120-col, sorted imports)
|
|
- **SwiftLint** mit `.swiftlint.yml`
|
|
- **Logging:** App-Subsystem `ev.mana.wordeck` via
|
|
`Sources/Core/Telemetry/Log.swift`. ManaCore loggt parallel unter
|
|
`ev.mana.core`
|
|
- **Persistenz:** SwiftData für Deck/Card-Cache (ab β-1), JWT im
|
|
Keychain (über ManaCore)
|
|
- **Lokalisierung:** DE primary, EN fallback via `Localizable.xcstrings`
|
|
|
|
## Wordeck-API-Wire-Format
|
|
|
|
Wire-Format gegen `https://api.wordeck.com/api/v1/*`. Quelle der
|
|
Wahrheit: `../cards/apps/api/src/routes/*.ts`. Bei neuem DTO
|
|
verifizieren:
|
|
|
|
1. Path + Method gegen den Hono-Handler prüfen
|
|
2. Response-Schema (`zod`) gegen `Codable`-Struct mappen
|
|
3. snake_case via `CodingKeys`, Optionale Felder explizit `Optional<T>`
|
|
4. Test-Fixture aus echtem Server-Response in `Tests/UnitTests/`
|
|
|
|
## Repo-Layout
|
|
|
|
```
|
|
wordeck-native/
|
|
├── project.yml XcodeGen-Manifest (SOT)
|
|
├── PLAN.md Phase-Tracking (gekürzt aus Greenfield-Plan)
|
|
├── CLAUDE.md dieses File
|
|
├── README.md
|
|
├── .swiftformat, .swiftlint.yml
|
|
├── Sources/
|
|
│ ├── App/ WordeckNativeApp (@main), RootView
|
|
│ ├── Features/
|
|
│ │ ├── Account/ LoginView, AccountView (ab β-1)
|
|
│ │ ├── Decks/ DashboardView (Placeholder), DeckList (β-1)
|
|
│ │ ├── Study/ (β-2)
|
|
│ │ ├── Editor/ (β-3)
|
|
│ │ ├── Marketplace/ (β-5)
|
|
│ │ ├── Stats/ (β-1)
|
|
│ │ └── Imports/ (β-3)
|
|
│ ├── Core/
|
|
│ │ ├── Auth/ AppConfig (ManaAppConfig-Provider)
|
|
│ │ ├── API/ WordeckAPI (AuthenticatedTransport-Wrapper)
|
|
│ │ ├── Domain/ (Card-Type-Enums, Rating-Enum — ab β-2)
|
|
│ │ ├── Storage/ (SwiftData-Models — ab β-1)
|
|
│ │ ├── Sync/ (ReviewQueue, MediaCache — ab β-2/β-4)
|
|
│ │ ├── Telemetry/ OSLog (Subsystem ev.mana.wordeck)
|
|
│ │ └── Theme/ WordeckTheme (forest-Werte)
|
|
│ ├── Widgets/ (WidgetKit-Extension — ab β-6)
|
|
│ ├── ShareExtension/ (Save-as-Card — ab β-6)
|
|
│ └── Resources/
|
|
│ ├── Assets.xcassets
|
|
│ ├── Localizable.xcstrings
|
|
│ ├── Info.plist (generiert, gitignored)
|
|
│ └── WordeckNative.entitlements (generiert, gitignored)
|
|
├── Tests/
|
|
│ ├── UnitTests/
|
|
│ └── UITests/
|
|
└── docs/
|
|
```
|
|
|
|
## Wichtige Cross-Repo-Doks
|
|
|
|
- `../mana/docs/playbooks/CARDS_NATIVE_GREENFIELD.md` — vollständiger
|
|
Phasen-Plan und Architektur-Entscheidungen
|
|
- `../mana/docs/MANA_SWIFT.md` — native-Plattform-SOT
|
|
- `../mana/docs/MANA_AUTH_FEDERATION.md` — Auth-Protokoll, das
|
|
ManaCore implementiert
|
|
- `../mana/docs/COMPLIANCE.md` — Telemetrie/Auth/Bezahl-Regeln, gilt
|
|
auch nativ
|
|
- `../cards/CLAUDE.md` — Cards-Repo, Web + API
|
|
- `../cards/STATUS.md` — Web-Phasenstand (Funktions-Referenz)
|
|
- `../mana-swift-core/CLAUDE.md` — geteilter Code, Konventionen
|
|
|
|
## Lokal entwickeln
|
|
|
|
**Pre-Requisites:**
|
|
- Xcode 16+
|
|
- `brew install xcodegen swiftformat swiftlint`
|
|
- `../mana-swift-core/` muss als Schwester-Verzeichnis existieren
|
|
(Package-Dependency via `path: ../mana-swift-core`)
|
|
|
|
**Workflow:**
|
|
```bash
|
|
xcodegen generate
|
|
open WordeckNative.xcodeproj
|
|
```
|
|
|
|
**Vor jedem Commit:**
|
|
```bash
|
|
swiftformat Sources Tests
|
|
swiftlint --strict
|
|
```
|
|
|
|
## Phasen-Disziplin
|
|
|
|
Jede Phase aus dem Greenfield-Plan hat ein verifizierbares
|
|
Erfolgskriterium. Nicht in die nächste Phase reinarbeiten, bevor
|
|
die vorherige abgeschlossen ist:
|
|
|
|
- β-0: leerer Build + Login + API-Reachability-Probe (**JETZT**)
|
|
- β-1: Decks-Liste mit SwiftData-Cache
|
|
- β-2: Study-Loop + Offline-Grade-Queue + Endurance-Test auf realem Gerät
|
|
- β-3: Card-/Deck-Editor (basic, cloze, typing, multiple-choice)
|
|
- β-4: Media + image-occlusion + audio-front
|
|
- β-5: Marketplace + Universal-Links
|
|
- β-6: Native-Polish (Widgets, Notifications, Share-Extension)
|
|
- β-7: App-Store-Submission
|
|
|
|
Bei Phasen-Wechsel: PLAN.md aktualisieren + Greenfield-Plan abhaken.
|