How xpavle00/habo works
1. Product shape
Habo is a Flutter 3.x mobile app for iOS and Android, with desktop shells present for Linux and macOS but the core product is clearly mobile-first. The app is offline-first and centers on local habit tracking, with optional cloud sync and encrypted backups.
2. Top-level architecture
The Dart app is organized in a fairly clean layered split:
- lib/screens, lib/habits, lib/statistics, lib/settings, lib/onboarding, lib/widgets for UI
- lib/services for cross-cutting capabilities
- lib/repositories for persistence and sync data access
- lib/model for domain/data objects
- lib/navigation for app flow
This makes the repo diagram easier to draw as UI → managers/services → repositories → storage/sync.
3. Core domain: habits
The main domain objects live in lib/model and lib/habits. The habit area includes the list screen, edit screen, calendar visualization, day selectors, empty states, and a HabitsManager that likely coordinates business rules such as completion updates, ordering, archiving, and reminder behavior. This is the heart of the app.
4. Local persistence boundary
Persistence is abstracted behind repositories:
- habit_repository
- category_repository
- event_repository
- backup_repository
with SQLite-backed implementations in the sqlite_* files.
The architecture suggests repositories as the boundary between domain/UI code and the local database, allowing sync and backup layers to work on the same model without coupling to UI.
5. Sync and backup subsystem
The app has a separate sync stack in lib/services and lib/screens/sync_*:
- SyncManager coordinates sync state and orchestration
- SyncService handles remote operations
- BackupService / BackupResult handle encrypted backup creation and restore
- SyncError captures failures
The README clarifies that sync is end-to-end encrypted: data is encrypted locally with a master password before leaving the device. That means the cloud boundary only sees ciphertext.
6. Backend dependency: Supabase
The cloud side lives under supabase/ and is not a generic web backend; it’s specifically Supabase:
- SQL migrations define the remote schema
- an Edge Function delete-account handles account deletion
- supabase/config.toml and README indicate self-hosting support
So the mobile app talks to a Supabase project configured by the user, rather than a fixed proprietary backend.
7. Encryption and authentication flow
Security-sensitive features are split into services:
- encryption_service
- biometric_auth_service
- sync/password-related screens and widgets
- master password views in the sync flow
The intended boundary is: user authenticates locally, data is encrypted locally, then synchronized. Biometrics appear to gate access, while the master password protects sync material and backups.
8. Device integrations
Several services bridge the app to native platform features:
- notification_service for reminders
- home_widget_service plus Android/iOS widget code for home screen widgets
- ui_feedback_service for haptics/sounds/UX feedback
- subscription_service for monetization or entitlement checks
These are the main places where Flutter crosses into native capabilities.
9. Platform-specific UI extensions
The repo includes full native project trees for Android, iOS, macOS, and Linux, but the notable app-specific platform work is Android/iOS widgets:
- Android HaboWidget.kt, WidgetUpdateWorker.kt, and widget layout/resources
- iOS HaboWidget Swift extension and widget bundle
This indicates the app pushes habit status to platform home screen widgets via platform-native extensions, likely fed by shared widget data from Flutter.
10. Navigation and app flow
Navigation is custom rather than purely declarative screen-to-screen calls. The navigation folder contains:
- app_router
- route_information_parser
- app_state_manager
- route definitions
This suggests a centralized routing/state model, probably supporting onboarding, auth/sync setup, settings, and deep links.
11. Onboarding and sync setup
The onboarding and screens/sync_* areas indicate multiple entry flows:
- initial app onboarding
- sync onboarding
- server configuration
- login/master password/profile flows
That means the app has a distinct setup path for sync-enabled users separate from normal local usage.
12. Statistics and visualization
lib/statistics contains monthly graphs, summary cards, and empty states. This is a read-only analytics slice built on top of habit/event data. It likely reads from repositories rather than mutating state, which is a clean separation from the core habit editing flow.
13. Localization and asset pipeline
The app is heavily internationalized:
- ARB source files in lib/l10n
- generated Dart localization in lib/generated/intl
- many translated storefront metadata files under fastlane/metadata
Assets include onboarding images and UI sounds. This means the diagram should show localized UI and static assets as shared input across multiple screens, not as separate subsystems.
14. Quality, build, and release infrastructure
The repo includes:
- GitHub Actions CI
- Flutter tests covering models, repositories, services, widgets, and integration flows
- Fastlane metadata for app-store distribution
- Android/iOS platform build scaffolding
This indicates a mature mobile release pipeline, with test coverage focused especially on sync, backup, encryption, and repository behavior.
15. Key architectural summary
The simplest accurate diagram is:
Flutter UI and navigation drive habit, settings, onboarding, and sync flows; those call into services and managers; services use SQLite repositories for local state and Supabase sync services for remote encrypted sync; platform services handle notifications, biometrics, widgets, and feedback; everything is wrapped by local-first, end-to-end encrypted data handling.
Main entry points: app_router.dart App router · repository_factory.dart Repo factory · habits_manager.dart Habits manager · service_locator.dart Service locator
Components 25
App shell
Entry point, routing, onboarding, and shared app flow.
- Main app · Bootstraps the mobile app and initializes shared services.
lib/main.dart - App router · Centralized route and flow coordination for the app.
lib/navigation/app_router.dart - App state · Holds routing state and app-level navigation decisions.
lib/navigation/app_state_manager.dart
Feature UI
Primary user-facing screens for habits, statistics, settings, and sync.
- Onboarding · Initial setup flow for new users.
lib/onboarding/onboarding_screen.dart - Habits UI · Primary habit list and editing entry point.
lib/habits/habits_screen.dart - Statistics · Read-only habit analytics and summaries.
lib/statistics/statistics_screen.dart - Settings · Configuration, account, and app preferences screens.
lib/settings/settings_screen.dart - Sync setup · User-facing sync onboarding, login, and account setup flow.
lib/screens/sync_screen.dart
Core services
Managers and cross-cutting services for sync, encryption, backups, notifications, and platform integrations.
- Habits manager · Coordinates habit state, ordering, completion, and reminders.
lib/habits/habits_manager.dart - Biometric gate · Wraps protected flows with local biometric authentication.
lib/widgets/biometric_auth_wrapper.dart - Service locator · Builds and shares app services and repositories.
lib/services/service_locator.dart - Encryption · Encrypts and decrypts local backup and sync payloads.
lib/services/encryption_service.dart - Sync manager · Coordinates sync state, orchestration, and error handling.
lib/services/sync_manager.dart - Sync service · Performs remote operations against the cloud backend.
lib/services/sync_service.dart - Backup service · Creates and restores encrypted local backups.
lib/services/backup_service.dart - Notifications · Schedules and manages habit reminder notifications.
lib/services/notification_service.dart - Widget bridge · Feeds shared data to native home screen widgets.
lib/services/home_widget_service.dart - Widget data · Data model for syncing app state to widgets.
lib/widgets/home_widget_data.dart - Android widget · Android app widget extension and update worker.
android/app/src/main/java/com/pavlenko/Habo/HaboWidget.kt - iOS widget · iOS widget extension used to render habit status.
ios/HaboWidget/HaboWidget.swift
Data & backend
Domain model, repositories, local SQLite persistence, and Supabase backend contract.
- Repo factory · Selects and assembles repository implementations.
lib/repositories/repository_factory.dart - SQLite repos · Concrete SQLite-backed repositories for habits, categories, events, and backups.
lib/repositories/sqlite_repositories.dart - Domain model · Shared habit, category, settings, and backup data structures.
lib/model/habo_model.dart - Remote schema · Defines the server-side schema used by sync.
supabase/migrations/20260313191900_remote_schema.sql - Delete account · Supabase function for remote account deletion.
supabase/functions/delete-account/index.ts
Connections 34
- Main app → App router: starts · App entry hands control to centralized navigation.
- Main app → Service locator: initializes · Bootstraps shared services and repositories.
- App router → App state: uses · Router depends on app state for flow decisions.
- App router → Onboarding: routes to · Onboarding is one of the major app flows.
- App router → Habits UI: routes to · Main habit workflow entry.
- App router → Statistics: routes to · Statistics flow.
- App router → Settings: routes to · Settings flow.
- App router → Sync setup: routes to · Sync setup and account flow.
- Habits UI → Habits manager: reads/writes · Habit UI delegates business logic to the manager.
- Habits manager → Repo factory: uses · Habit logic accesses persistence through repositories.
- Habits manager → Notifications: updates · Habit changes drive reminder scheduling.
- Habits manager → Widget bridge: publishes · Habit state is exposed to widgets.
- Habits manager → Encryption: protects data · Encrypted data handling is shared across sensitive flows.
- Statistics → Repo factory: reads · Statistics are derived from stored habit/event data.
- Sync setup → Sync manager: orchestrates · Sync UI is driven by the sync manager.
- Sync setup → Backup service: uses · Backup and restore are part of sync setup.
- Sync setup → Biometric gate: gates · Sensitive sync steps require local biometric auth.
- Sync manager → Sync service: coordinates · Manager delegates remote sync operations.
- Sync manager → Encryption: encrypts · Sync payloads are encrypted locally before upload.
- Sync manager → Repo factory: syncs from · Sync reads and writes through repositories.
- Backup service → Encryption: encrypts · Backups are protected before export.
- Backup service → Repo factory: reads/writes · Backup restore and creation use repository data.
- Service locator → Repo factory: provides · Central wiring constructs repository instances.
- Service locator → Sync manager: provides · Shares sync orchestration service.
- Service locator → Backup service: provides · Shares backup service.
- Service locator → Notifications: provides · Shares reminder service.
- Repo factory → SQLite repos: selects · Factory points to SQLite-backed implementations for offline storage.
- SQLite repos → Domain model: persists · Local storage serializes the shared domain model.
- Sync service → Remote schema: targets · Remote sync follows the Supabase schema contract.
- Sync service → Delete account: calls · Remote account lifecycle uses the Supabase edge function.
- Widget bridge → Widget data: formats · Builds the payload consumed by widgets.
- Widget bridge → Android widget: updates · Pushes widget state to the Android extension.
- Widget bridge → iOS widget: updates · Pushes widget state to the iOS extension.
- Biometric gate → Encryption: protects access · Biometric gating guards encrypted flows.