docs: add STRUCTURE.md describing targets, layout, and architecture

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
kutesir
2026-07-03 01:50:30 +03:00
parent dd22e94efe
commit 9ae94babb6

108
STRUCTURE.md Normal file
View File

@@ -0,0 +1,108 @@
# Project Structure
KisaniCal (display name **Wenza**) is a personal productivity + fitness iOS app,
built with SwiftUI and generated from `project.yml` via [XcodeGen]. It ships an
iOS app, a WidgetKit extension, and an optional watchOS companion.
## Build targets
Defined in [`project.yml`](project.yml):
| Target | Type | Platform | Bundle ID |
|---|---|---|---|
| `KisaniCal` | application | iOS 16+ | `com.kutesir.KisaniCal` |
| `KisaniCalWidgets` | app-extension | iOS 18+ | `com.kutesir.KisaniCal.KisaniCalWidgets` |
| `WenzaWatch` | application | watchOS 10+ | `com.kutesir.KisaniCal.watchkitapp` |
| `KisaniCalTests` | unit-test | iOS 16+ | — |
`WenzaWatch` is built/embedded only when the watchOS platform is installed
(see the commented `embed` note in `project.yml`).
## Directory layout
```
KisaniCal/ repo root (Gitea: kutesir/KisaniCal)
├── project.yml XcodeGen spec — source of truth for the .xcodeproj
├── KisaniCal.xcodeproj generated (do not hand-edit)
├── KisaniCal/ 📱 main iOS app target
│ ├── KisaniCalApp.swift @main entry point
│ ├── ContentView.swift root view / tab shell
│ ├── KisaniCal.entitlements
│ ├── LaunchScreen.storyboard
│ ├── Views/ SwiftUI screens (13)
│ │ ├── TodayView, CalendarView, MatrixView tasks
│ │ ├── WorkoutView, AddExerciseSheet fitness
│ │ ├── AuthView, OnboardingView, ProfileSetupView, SplashView
│ │ ├── SettingsView, TutorialView
│ │ └── TaskContextMenu, TodayMenuFeatures
│ ├── Managers/ stateful service singletons (10)
│ │ ├── AuthManager, CloudSyncManager auth + iCloud KVS
│ │ ├── HealthKitManager, SpeechRecognizer system frameworks
│ │ ├── NotificationManager, LiveActivityManager, ShortcutHandler
│ │ ├── TutorialManager
│ │ └── AppGroup, TaskActivityAttributes shared with widgets
│ ├── Models/ TaskItem, ExerciseModels, CalendarGrid
│ ├── Components/ SharedComponents, FloatingTabState
│ └── Theme/ DesignTokens
├── KisaniCalWidgets/ 🧩 WidgetKit extension (iOS 18+)
│ ├── KisaniCalWidgets.swift, MyTasksWidget, EventCountdownWidget
│ ├── TaskLiveActivity, WidgetViews, WidgetData
│ └── Info.plist, .entitlements
├── WenzaWatch/ ⌚️ watchOS companion (build-optional)
│ └── WenzaWatchApp.swift, Info.plist, .entitlements
├── KisaniCalTests/ 🧪 unit tests (the CI test target)
│ └── CalendarGridTests, RecurrenceTests, NLRecurrenceParseTests
├── .gitea/workflows/ 🔧 CI/CD (Gitea Actions)
│ ├── ci.yml build + test on PRs into main/develop
│ └── release.yml archive + export IPA on push to main
├── scripts/gitea-setup.sh Gitea branch-protection / default-branch setup
├── ExportOptions.plist IPA export template
├── CONTRIBUTING.md branch workflow + PR gate rules
├── PRODUCT.md product brief, users, design principles
├── SERVICES.md backing services / infra notes
├── ISSUES.md running issue log (KC-## ids)
└── Sanctum-Auto-FailOver-Uptime-Kuma.md
```
## Architecture
A flat SwiftUI **MVVM-lite** layout, organized by role rather than by feature:
- **Views** — SwiftUI screens, one file per screen.
- **Managers** — `ObservableObject` service singletons holding cross-cutting
state (auth, iCloud sync, HealthKit, notifications, speech, Live Activities).
- **Models** — plain data types (`TaskItem`, exercise/workout models, calendar
grid math).
- **Components / Theme** — shared UI and design tokens.
Three product domains coexist in one app:
1. **Tasks** — Today list, Calendar, Eisenhower Matrix; natural-language quick
add (with voice via `SpeechRecognizer`).
2. **Fitness** — workout logging with weighted/bodyweight sets; reads/writes
Health via `HealthKitManager`.
3. **Calendar / events** — surfaced on the dashboard, in **widgets**, and as
**Live Activities**.
### Cross-target code sharing
`KisaniCal/Managers/AppGroup.swift` and `TaskActivityAttributes.swift` are
compiled into **both** the app and the widget extension (see the widget target's
`sources` in `project.yml`), so task/activity data is shared through the App
Group container.
### Persistence & sync
State is persisted locally and mirrored to **iCloud key-value store** via
`CloudSyncManager`. Restore-on-launch rehydrates data after reinstall/update
(see ISSUES.md KC-39 for the save/restore symmetry the sync layer must keep).
[XcodeGen]: https://github.com/yonaskolb/XcodeGen