An iOS app for Catholic faith formation - Scripture, liturgy, prayer, community, and AI-assisted spiritual reflection.
Built with a local-first philosophy and designed for clarity, reverence, and performance on Apple platforms.
Started by Bwire and open to creative collaboration.
- Bible - multilingual Scripture reading (English + Latin Vulgate), paged, local-first.
- Liturgy - daily Missal readings and liturgical calendar, fully available offline.
- Prayer - curated prayer content accessible without network dependency.
- Community + AI Verbum - social features and AI-assisted reflection built on a modular foundation.
- Swift + SwiftUI
- SwiftData (or Core Data fallback where needed)
- Combine / Async-Await (structured concurrency)
- URLSession for networking
- Codable for serialization
- Modular architecture using Swift Packages (SPM)
- App/ -> App entry point, navigation, dependency wiring
- Core/ -> Shared infrastructure (UI, networking, persistence, utilities)
- Features/ -> Self-contained feature modules (Bible, Liturgy, Prayer, AI, etc.)
- Resources/ -> Assets (Bible, Missal, Prayers)
- English Bible source (pg1581) bundled in app resources.
- Latin Vulgate source (vulsearch_vulgate) bundled locally.
- Canonical mappings and metadata for all supported books.
- Locale-aware language resolution with user override.
- On first launch, Bible content is seeded into local storage (SwiftData/Core Data).
- Language selection resolves in this order:
- Explicit user selection
- Compatible device locale
- English fallback
- Latin fallback (if English unavailable)
- Scripture access is repository-driven, paginated, and cached.
- Batch inserts used during initial seeding.
- Indexed storage for fast verse lookup.
- Lazy loading for chapters/verses.
- In-memory caching to reduce repeated disk access.
- Missal readings and liturgical calendar assets under Resources/Missal/.
- Multi-year static JSON datasets.
- Calendar logic implemented in feature domain layer.
Local-first with layered fallback:
- Return cached local data when available.
- Fall back to bundled assets when cache is missing.
- Optionally refresh from network sources.
- Persist refreshed data locally.
Ensures full offline usability with optional freshness when online.
- Bible: Verbum/Resources/Bible/
- Missal: Verbum/Resources/Missal/
- Prayers: Verbum/Resources/prayers.json
Seeding is orchestrated during app launch using a bootstrap coordinator to ensure early data availability.
- Open Verbum.xcodeproj or Verbum.xcworkspace.
- Select Verbum scheme.
- Run (Cmd+R).
xcodebuild -project Verbum.xcodeproj -scheme Verbum -configuration Debug -destination 'platform=iOS Simulator,OS=latest,name=iPhone 15' build CODE_SIGNING_ALLOWED=NO
xcodebuild -project Verbum.xcodeproj -scheme Verbum -configuration Debug -destination 'platform=iOS Simulator,OS=latest,name=iPhone 15' test CODE_SIGNING_ALLOWED=NO
bash Scripts/Verification/verify_verbum_guidelines.sh
Contributors work on feature branches and open PRs to dev. Promotion across environments and App Store distribution is handled by the maintainer.
Same philosophy applies: you focus on clean, complete work - deployment is centralized.
All PRs to dev must originate from:
| Prefix | Example |
|---|---|
| feature- | feature-bible-search |
| ft- | ft-prayer-detail |
Non-compliant branches are rejected by CI.
Ensure:
- Project builds successfully in Xcode.
- No warnings or errors.
- Previews render correctly.
- Tests pass.
This is the contributor contract for verbum-ios.
- App: App lifecycle, navigation, dependency injection only.
- Core: Shared utilities (UI system, networking, persistence, helpers).
- Features/*: Feature-isolated modules (UI, ViewModel, domain, data).
Allowed dependency direction:
- App -> Features, Core
- Features -> Core
- Core -> no Features
Forbidden:
- Feature -> Feature dependencies
- View layer -> direct persistence access
- View layer -> direct networking calls
- Use FeatureView + FeatureContent pattern:
- FeatureView: state + orchestration
- FeatureContent: pure UI
- Keep state in ObservableObject or @StateObject ViewModels.
- Use @MainActor and structured concurrency correctly.
- Route data through UseCase -> Repository layers.
- Use strong typing (struct, enum, Result, etc.).
- Centralize design via a theme system (colors, typography, spacing).
- Provide SwiftUI previews for every screen.
- Keep ViewModels focused and small.
- Isolate AI logic inside Features/AI.
- Validate inputs in UseCases before repository calls.
- Write unit tests for domain and data layers.
- Use dependency injection (protocol-based, constructor injection).
- Do not access persistence directly from Views or ViewModels.
- Do not use force unwraps (!).
- Do not hardcode colors or fonts inside Views.
- Do not place business logic inside SwiftUI views.
- Do not create feature-to-feature dependencies.
- Do not introduce UIKit unless absolutely necessary.
- Do not create massive ViewModels handling multiple domains.
- Do not use global mutable state.
- Do not skip previews for UI work.
- Do not bypass repository/use-case layers.
- Do not mix async patterns inconsistently (Combine + async/await without reason).
| Component | Convention |
|---|---|
| Screen | FeatureView.swift |
| UI Content | FeatureContent.swift |
| ViewModel | FeatureViewModel.swift |
| Use Case | ActionThingUseCase.swift |
| Repository | ThingRepository.swift / ThingRepositoryImpl.swift |
| UI State | FeatureUiState |
- Prefer composition over inheritance.
- Keep Views declarative and side-effect free.
- Use @State, @StateObject, @ObservedObject correctly.
- Avoid deeply nested view hierarchies.
- Extract reusable components into Core/UI.
- Build succeeds (Cmd+B)
- App runs (Cmd+R)
- Previews render
- Tests pass
verbum-ios is built like a liturgy:
- Structured
- Intentional
- Minimal where necessary
- Rich where meaningful
Every line of code should serve clarity, not complexity.