5.0 KiB
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:
| 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 —
ObservableObjectservice 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:
- Tasks — Today list, Calendar, Eisenhower Matrix; natural-language quick
add (with voice via
SpeechRecognizer). - Fitness — workout logging with weighted/bodyweight sets; reads/writes
Health via
HealthKitManager. - 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).