# lasangnya/snaptric architecture

> Architecture diagram of the GitHub repository lasangnya/snaptric, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-15). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/lasangnya/snaptric
- Repository: https://github.com/lasangnya/snaptric

## Overview

1. **Project shape**
   - Snaptric is a single Android app module, organized as a Clean Architecture-style codebase rather than a multi-module Gradle build.
   - The main boundaries are `core` for shared domain/data/infrastructure, `feature` for user-facing screens, `navigation` for routing, and `ai` for OCR/image-processing helpers.

2. **App entry and composition root**
   - `SnaptricApplication`, `AppModule`, and `DatabaseModule` are the main startup/DI entry points.
   - `MainActivity` hosts the Compose UI, and `AppNavHost` wires the screen graph starting from top-level destinations defined in `TopLevelDestination`.

3. **UI architecture**
   - The app is Compose-only with Material 3 styling from the `core/designsystem` package.
   - Screens are split into stateful/state-holder layers and stateless UI surfaces, which is why there are separate `ui` and `viewmodel` packages for each feature.

4. **Feature subsystems**
   - `feature/home` is the landing/dashboard area.
   - `feature/properties` manages the hierarchy of properties, utilities, and property details.
   - `feature/capture` handles the camera-based meter reading flow.
   - These features are intentionally isolated so each screen group owns its own state, UI, and navigation concerns.

5. **Domain model and data flow**
   - The core domain revolves around `Reading` plus a `ReadingRepository` abstraction and `MeterReadingAnalyzer`.
   - The primary user flow is: UI interaction → ViewModel → repository/domain logic → persistence or OCR analysis → UI state update.
   - `CaptureUiState` centralizes the capture screen state so camera/OCR results can be represented consistently.

6. **Persistence layer**
   - Room is the local persistence backbone via `SnaptricDatabase`, `MeterDao`, entity classes, and type converters.
   - The database schema is relational: `PropertyEntity` → `UtilityEntity` → `ReadingEntity`, matching the app’s property/utility/meter structure.
   - The README’s note about cascading deletes is reflected in the design: removing a property should clean up dependent utilities and readings.

7. **Repository strategy**
   - `InMemoryReadingRepository` exists alongside the database-backed path, which suggests the app uses an abstraction to support tests, previews, or simplified runtime behavior.
   - This keeps ViewModels insulated from the storage implementation and makes the core logic easier to test.

8. **Capture and OCR pipeline**
   - The capture subsystem combines CameraX-style image acquisition with image preprocessing and ML Kit OCR.
   - The `ai/helper/CopyAssetToFiles` utility indicates model or asset setup work, while `ai/mlkit/MlKitReadingAnalyzer` performs text recognition.
   - The README describes a deliberate image-cropping step before analysis, which is an important boundary: camera frame → crop/rotate preprocess → OCR → extracted reading.

9. **Property and utility management**
   - `PropertyViewModel`, `UtilityViewModel`, and `PropertyDetailViewModel` manage CRUD and selection logic for the hierarchy of tracked locations and meters.
   - `PropertiesScreen`, `UtilityScreen`, and `PropertyDetailScreen` are the corresponding presentation surfaces.
   - This subsystem is the app’s structure-management layer, feeding the capture and home flows with metadata like utility type and units.

10. **Home/dashboard layer**
   - `HomeViewModel` and `HomeScreen` likely aggregate the current state of tracked properties, recent readings, or summary information.
   - It acts as a navigation and overview entry point rather than owning core persistence rules.

11. **Design system and shared UI**
   - `core/designsystem` contains reusable Compose components, tokens, spacing, shapes, colors, typography, and the app theme.
   - This is a shared presentation boundary used across features to keep visual behavior consistent without coupling screens to one another.

12. **Testing strategy**
   - Unit tests cover ViewModels, the in-memory repository, and property icon logic, which points to logic-heavy code being tested outside Android runtime.
   - Instrumented tests cover Room DAO behavior and Compose UI/navigation flows, indicating the repo validates both persistence integrity and end-to-end screen behavior.

13. **Infrastructure and runtime dependencies that affect architecture**
   - The important runtime pieces are Jetpack Compose, Hilt, Room, CameraX, Kotlin Coroutines/Flow, and Google ML Kit.
   - These choices drive the architecture: asynchronous state streams in ViewModels, injected repositories/DB, and a dedicated capture/OCR pipeline instead of server-side processing.

14. **Overall architectural boundary**
   - Snaptric is explicitly local-first: all user data stays on-device, and AI processing is performed on-device.
   - The main system boundary is therefore between the UI/domain layer and local device services: camera frames, ML analysis, and Room persistence.

Main entry points: [`app/src/main/java/com/snaptric/feature/capture/viewmodel/CaptureViewModel.kt`](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/feature/capture/viewmodel/CaptureViewModel.kt) (Capture VM), [`app/src/main/java/com/snaptric/navigation/AppNavHost.kt`](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/navigation/AppNavHost.kt) (Nav host), [`app/src/main/java/com/snaptric/core/database/dao/MeterDao.kt`](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/database/dao/MeterDao.kt) (Meter DAO), [`app/src/main/java/com/snaptric/core/domain/ReadingRepository.kt`](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/domain/ReadingRepository.kt) (Repository)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_app["App shell"]
  node_snaptric_application(("App"))
  node_app_module["App module<br/>di module<br/>[AppModule.kt]"]
  node_main_activity["MainActivity<br/>compose host<br/>[MainActivity.kt]"]
  node_app_nav_host["Nav host<br/>navigation host<br/>[AppNavHost.kt]"]
  node_top_level_destination["Top level<br/>nav destinations"]
end

subgraph group_core["Core"]
  node_reading["Reading<br/>domain model<br/>[Reading.kt]"]
  node_reading_repository["Repository<br/>domain port"]
  node_meter_analyzer["Analyzer<br/>domain port"]
  node_capture_ui_state["Capture state<br/>ui state<br/>[CaptureUiState.kt]"]
  node_in_memory_repo["In-memory repo<br/>repo impl"]
  node_snaptric_database[("Database")]
  node_meter_dao["Meter DAO<br/>room dao<br/>[MeterDao.kt]"]
  node_db_module["DB module<br/>di module<br/>[DatabaseModule.kt]"]
  node_design_system["Design system"]
end

subgraph group_features["Features"]
  node_home_screen["Home screen<br/>compose screen<br/>[HomeScreen.kt]"]
  node_home_vm["Home VM<br/>viewmodel<br/>[HomeViewModel.kt]"]
  node_properties_screens["Properties UI<br/>compose screens"]
  node_properties_vms["Properties VMs<br/>viewmodels"]
  node_capture_screen["Capture screen<br/>compose screen<br/>[CaptureScreen.kt]"]
  node_capture_vm["Capture VM<br/>viewmodel"]
end

subgraph group_ai["AI pipeline"]
  node_asset_helper["Asset helper<br/>android helper"]
  node_mlkit_analyzer["ML Kit OCR<br/>ocr analyzer"]
end

subgraph group_tests["Tests"]
  node_property_dao_test["DAO test<br/>instrumented test<br/>[MeterDaoTest.kt]"]
  node_capture_vm_test["Capture VM test<br/>unit test"]
end

node_snaptric_application -->|"starts"| node_app_module
node_app_module -->|"includes"| node_db_module
node_snaptric_application -->|"launches"| node_main_activity
node_main_activity -->|"hosts"| node_app_nav_host
node_app_nav_host -->|"routes"| node_top_level_destination
node_app_nav_host -->|"shows"| node_home_screen
node_app_nav_host -->|"shows"| node_properties_screens
node_app_nav_host -->|"shows"| node_capture_screen
node_home_vm -->|"reads"| node_reading_repository
node_home_screen -->|"observes"| node_home_vm
node_properties_vms -->|"uses"| node_reading_repository
node_properties_vms -->|"persists"| node_meter_dao
node_properties_screens -->|"observes"| node_properties_vms
node_capture_vm -->|"updates"| node_capture_ui_state
node_capture_vm -->|"analyzes"| node_meter_analyzer
node_capture_vm -->|"stores"| node_reading_repository
node_capture_vm -->|"implements"| node_mlkit_analyzer
node_mlkit_analyzer -->|"depends on"| node_asset_helper
node_capture_screen -->|"observes"| node_capture_vm
node_design_system -->|"styles"| node_home_screen
node_design_system -->|"styles"| node_properties_screens
node_design_system -->|"styles"| node_capture_screen
node_db_module -->|"provides"| node_snaptric_database
node_snaptric_database -->|"exposes"| node_meter_dao
node_meter_dao -->|"maps"| node_reading
node_in_memory_repo -->|"implements"| node_reading_repository
node_capture_vm_test -.->|"verifies"| node_capture_vm
node_property_dao_test -.->|"verifies"| node_meter_dao

click node_snaptric_application "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/SnaptricApplication.kt"
click node_app_module "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/AppModule.kt"
click node_main_activity "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/MainActivity.kt"
click node_app_nav_host "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/navigation/AppNavHost.kt"
click node_top_level_destination "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/navigation/TopLevelDestination.kt"
click node_reading "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/domain/Reading.kt"
click node_reading_repository "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/domain/ReadingRepository.kt"
click node_meter_analyzer "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/domain/MeterReadingAnalyzer.kt"
click node_capture_ui_state "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/data/CaptureUiState.kt"
click node_in_memory_repo "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/data/InMemoryReadingRepository.kt"
click node_snaptric_database "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/database/SnaptricDatabase.kt"
click node_meter_dao "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/database/dao/MeterDao.kt"
click node_db_module "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/database/di/DatabaseModule.kt"
click node_design_system "https://github.com/lasangnya/snaptric/tree/main/app/src/main/java/com/snaptric/core/designsystem"
click node_home_screen "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/feature/home/ui/HomeScreen.kt"
click node_home_vm "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/feature/home/viewmodel/HomeViewModel.kt"
click node_properties_screens "https://github.com/lasangnya/snaptric/tree/main/app/src/main/java/com/snaptric/feature/properties/ui"
click node_properties_vms "https://github.com/lasangnya/snaptric/tree/main/app/src/main/java/com/snaptric/feature/properties/viewmodel"
click node_capture_screen "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/feature/capture/ui/CaptureScreen.kt"
click node_capture_vm "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/feature/capture/viewmodel/CaptureViewModel.kt"
click node_asset_helper "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/ai/helper/CopyAssetToFiles.kt"
click node_mlkit_analyzer "https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/ai/mlkit/MlKitReadingAnalyzer.kt"
click node_property_dao_test "https://github.com/lasangnya/snaptric/blob/main/app/src/androidTest/java/com/snaptric/core/database/dao/MeterDaoTest.kt"
click node_capture_vm_test "https://github.com/lasangnya/snaptric/blob/main/app/src/test/java/com/snaptric/feature/capture/viewmodel/CaptureViewModelTest.kt"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_snaptric_application,node_app_module,node_main_activity,node_app_nav_host,node_top_level_destination toneBlue
class node_reading,node_reading_repository,node_meter_analyzer,node_capture_ui_state,node_in_memory_repo,node_snaptric_database,node_meter_dao,node_db_module,node_design_system toneAmber
class node_home_screen,node_home_vm,node_properties_screens,node_properties_vms,node_capture_screen,node_capture_vm toneMint
class node_asset_helper,node_mlkit_analyzer toneRose
class node_property_dao_test,node_capture_vm_test toneIndigo
```

## Components

### App shell

Startup, activity, and navigation composition root.

- [App](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/SnaptricApplication.kt): android application · Process entry point and app setup. · `app/src/main/java/com/snaptric/SnaptricApplication.kt`
- [App module](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/AppModule.kt): di module · Top-level dependency wiring for the app. · `app/src/main/java/com/snaptric/AppModule.kt`
- [MainActivity](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/MainActivity.kt): compose host · Hosts the Compose UI tree. · `app/src/main/java/com/snaptric/MainActivity.kt`
- [Nav host](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/navigation/AppNavHost.kt): navigation host · Wires top-level destinations and screen graph. · `app/src/main/java/com/snaptric/navigation/AppNavHost.kt`
- [Top level](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/navigation/TopLevelDestination.kt): nav destinations · Defines the app's top-level routes. · `app/src/main/java/com/snaptric/navigation/TopLevelDestination.kt`

### Core

Shared domain, persistence, and design system.

- [Reading](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/domain/Reading.kt): domain model · Core meter reading value object. · `app/src/main/java/com/snaptric/core/domain/Reading.kt`
- [Repository](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/domain/ReadingRepository.kt): domain port · Abstraction for persisting and loading readings. · `app/src/main/java/com/snaptric/core/domain/ReadingRepository.kt`
- [Analyzer](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/domain/MeterReadingAnalyzer.kt): domain port · Interface for meter-reading extraction from images. · `app/src/main/java/com/snaptric/core/domain/MeterReadingAnalyzer.kt`
- [Capture state](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/data/CaptureUiState.kt): ui state · Shared state model for capture flow results and progress. · `app/src/main/java/com/snaptric/core/data/CaptureUiState.kt`
- [In-memory repo](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/data/InMemoryReadingRepository.kt): repo impl · Lightweight repository implementation for tests and simple runtime use. · `app/src/main/java/com/snaptric/core/data/InMemoryReadingRepository.kt`
- [Database](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/database/SnaptricDatabase.kt): room database · Room database entry point for local persistence. · `app/src/main/java/com/snaptric/core/database/SnaptricDatabase.kt`
- [Meter DAO](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/database/dao/MeterDao.kt): room dao · Database access for properties, utilities, and readings. · `app/src/main/java/com/snaptric/core/database/dao/MeterDao.kt`
- [DB module](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/core/database/di/DatabaseModule.kt): di module · Provides Room database and DAO dependencies. · `app/src/main/java/com/snaptric/core/database/di/DatabaseModule.kt`
- [Design system](https://github.com/lasangnya/snaptric/tree/main/app/src/main/java/com/snaptric/core/designsystem): compose design system · Shared components, theme tokens, and styling. · `app/src/main/java/com/snaptric/core/designsystem`

### Features

User-facing screens and their state holders.

- [Home screen](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/feature/home/ui/HomeScreen.kt): compose screen · Landing and overview UI. · `app/src/main/java/com/snaptric/feature/home/ui/HomeScreen.kt`
- [Home VM](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/feature/home/viewmodel/HomeViewModel.kt): viewmodel · Aggregates overview state for the home screen. · `app/src/main/java/com/snaptric/feature/home/viewmodel/HomeViewModel.kt`
- [Properties UI](https://github.com/lasangnya/snaptric/tree/main/app/src/main/java/com/snaptric/feature/properties/ui): compose screens · Property, utility, and detail presentation surfaces. · `app/src/main/java/com/snaptric/feature/properties/ui`
- [Properties VMs](https://github.com/lasangnya/snaptric/tree/main/app/src/main/java/com/snaptric/feature/properties/viewmodel): viewmodels · CRUD and selection logic for properties and utilities. · `app/src/main/java/com/snaptric/feature/properties/viewmodel`
- [Capture screen](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/feature/capture/ui/CaptureScreen.kt): compose screen · Camera-based meter reading flow UI. · `app/src/main/java/com/snaptric/feature/capture/ui/CaptureScreen.kt`
- [Capture VM](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/feature/capture/viewmodel/CaptureViewModel.kt): viewmodel · Coordinates camera, preprocessing, OCR, and capture state. · `app/src/main/java/com/snaptric/feature/capture/viewmodel/CaptureViewModel.kt`

### AI pipeline

On-device image preprocessing and OCR analysis.

- [Asset helper](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/ai/helper/CopyAssetToFiles.kt): android helper · Copies bundled assets into app files for runtime setup. · `app/src/main/java/com/snaptric/ai/helper/CopyAssetToFiles.kt`
- [ML Kit OCR](https://github.com/lasangnya/snaptric/blob/main/app/src/main/java/com/snaptric/ai/mlkit/MlKitReadingAnalyzer.kt): ocr analyzer · Performs on-device text recognition for readings. · `app/src/main/java/com/snaptric/ai/mlkit/MlKitReadingAnalyzer.kt`

### Tests

Representative unit and instrumented coverage areas.

- [DAO test](https://github.com/lasangnya/snaptric/blob/main/app/src/androidTest/java/com/snaptric/core/database/dao/MeterDaoTest.kt): instrumented test · Representative Room persistence coverage. · `app/src/androidTest/java/com/snaptric/core/database/dao/MeterDaoTest.kt`
- [Capture VM test](https://github.com/lasangnya/snaptric/blob/main/app/src/test/java/com/snaptric/feature/capture/viewmodel/CaptureViewModelTest.kt): unit test · Representative capture flow logic coverage. · `app/src/test/java/com/snaptric/feature/capture/viewmodel/CaptureViewModelTest.kt`

## Connections

- App → App module: starts · Application bootstraps app-wide dependencies.
- App module → DB module: includes · Top-level DI wiring pulls in persistence bindings.
- App → MainActivity: launches · App entry launches the Compose host activity.
- MainActivity → Nav host: hosts · Activity renders the navigation graph.
- Nav host → Top level: routes · Navigation is organized around top-level destinations.
- Nav host → Home screen: shows · Home is one of the primary destinations.
- Nav host → Properties UI: shows · Property management screens are part of the graph.
- Nav host → Capture screen: shows · Capture flow is reachable from the app graph.
- Home VM → Repository: reads · Home state is derived from repository data.
- Home screen → Home VM: observes · UI renders state from its ViewModel.
- Properties VMs → Repository: uses · Property and utility logic depends on the repository abstraction.
- Properties VMs → Meter DAO: persists · Repository-backed flows ultimately reach Room access.
- Properties UI → Properties VMs: observes · Property UI is driven by feature ViewModels.
- Capture VM → Capture state: updates · Capture flow centralizes screen state in one model.
- Capture VM → Analyzer: analyzes · ViewModel delegates OCR extraction to analyzer logic.
- Capture VM → Repository: stores · Successful readings flow into the repository boundary.
- Capture VM → ML Kit OCR: implements · ML Kit is the concrete OCR backend.
- ML Kit OCR → Asset helper: depends on · OCR setup relies on bundled assets/files preparation.
- Capture screen → Capture VM: observes · Camera UI is state-driven from the ViewModel.
- Design system → Home screen: styles · Shared Compose theme and components are used across screens.
- Design system → Properties UI: styles · Property screens reuse the common visual system.
- Design system → Capture screen: styles · Capture UI is also themed by the shared design system.
- DB module → Database: provides · DI creates the Room database instance.
- Database → Meter DAO: exposes · Database surfaces DAO access.
- Meter DAO → Reading: maps · DAO persists the core reading domain data through entities.
- In-memory repo → Repository: implements · In-memory implementation satisfies the repository contract.
- Capture VM test → Capture VM: verifies · Unit coverage targets capture orchestration logic.
- DAO test → Meter DAO: verifies · Instrumented tests validate Room behavior.
