cards-native/CLAUDE.md
Till JS 28b20cd934 v0.1.0 — Phase β-0 Setup
Repo-Skelett für cards-native, native SwiftUI-Universal-App
für Cardecky (mana e.V.). Web-Parität zu cardecky.mana.how.

- project.yml mit Bundle ev.mana.cards, ManaSwiftCore-Dep via path
- AppConfig: auth.mana.how + cardecky-api.mana.how, Keychain ev.mana.cards
- CardsTheme: forest-Werte aus mana/packages/themes/.../forest.css
- LoginView (Email/PW gegen mana-auth via ManaCore.AuthClient)
- DashboardView als β-1-Placeholder mit cardecky-api-Reachability-Probe
- Log unter Subsystem ev.mana.cards
- 3 AppConfig-Tests
- iOS-Simulator-Build grün

Phasen-Plan: mana/docs/playbooks/CARDS_NATIVE_GREENFIELD.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 19:29:45 +02:00

7.3 KiB

CLAUDE.md — cards-native repo

Guidance für Claude Code in diesem Repository.

Wenn du gerade neu bist: lies zuerst 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 Cardecky, die Spaced-Repetition-Karten-App des Vereins mana e.V. Web-Parität zu cardecky.mana.how, plus native iOS- Affordances (Widgets, Notifications, Universal-Links, Pencil).

                  HTTPS/JWT      ┌──────────────────┐
   cards-api     ◄─────────────  │ cards-native     │  SwiftUI
   cardecky-api.mana.how         │ (this repo)      │  SwiftData (Cache)
                                 │ ev.mana.cards    │  WidgetKit (β-6)
                                 └──────────────────┘

Status

Phase β-0 — Setup (2026-05-12). Repo-Skelett, ManaCore + ManaTokens als Package-Dependency, Login + Cardecky-API-Reachability-Probe. Phasen β-1 bis β-7 in ../mana/docs/playbooks/CARDS_NATIVE_GREENFIELD.md.

Leitprinzip: Web-Parität

Die Web-App auf cardecky.mana.how 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.cards. Reverse-Domain mana-ev.ch. Universal-Link-Domain: cardecky.mana.how.
  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 CardsTheme.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.cards 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

Cardecky-API-Wire-Format

Wire-Format gegen https://cardecky-api.mana.how/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

cards-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/                     CardsNativeApp (@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/                 CardsAPI (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.cards)
│   │   └── Theme/               CardsTheme (forest-Werte)
│   ├── Widgets/                 (WidgetKit-Extension — ab β-6)
│   ├── ShareExtension/          (Save-as-Card — ab β-6)
│   └── Resources/
│       ├── Assets.xcassets
│       ├── Localizable.xcstrings
│       ├── Info.plist           (generiert, gitignored)
│       └── CardsNative.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:

xcodegen generate
open CardsNative.xcodeproj

Vor jedem Commit:

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.