# gazi2050/dohabit architecture

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

- Interactive diagram: https://gitdiagram.com/gazi2050/dohabit
- Repository: https://github.com/gazi2050/dohabit

## Overview

1. **Overall architecture**
   This is a **local-first PWA habit tracker** built with **React + TypeScript + Vite**. The codebase follows a **feature-sliced layering** pattern: `shared` → `entities` → `features` → `widgets` → `pages` → `app`. That boundary structure is the main thing to capture in an architecture diagram.

2. **App composition**
   The entry point is `src/main.tsx`, which renders `src/app/App.tsx`. The `app` layer wires together cross-cutting providers for **routing** and **i18n**, plus global styles and error fallback UI. This layer is intentionally thin; it does not own domain logic.

3. **Routing and screen boundaries**
   Routing lives under `src/app/providers/router` and `src/shared/lib/router`. The app has multiple top-level pages: **main**, **archive**, **diary**, **habit editor**, **habit statistics**, **achievements**, **appearance**, **menu**, **data management**, and **storage info**. These pages are the main user-facing boundaries and each page composes widgets rather than directly implementing domain behavior.

4. **Domain entities**
   The core data model is split into entities:
   - **habit**: the central aggregate, with progress, streaks, archive state, ordering, and history calculations.
   - **note**: habit-linked journal entries.
   - **achievement**: derived badges and milestone state.
   - **settings**: app-wide preferences like theme and language-related state.
   Each entity has its own store, reducer/handlers, types, and UI pieces, so domain state is isolated by concern.

5. **State management and updates**
   The architecture uses **Zustand-style stores** and reducer/handler modules inside each entity or feature. Habit, note, achievement, settings, dialog, drawer, and PWA install state all have dedicated stores. Updates flow through small action handlers such as add/edit/delete/archive/toggle-progress, which keeps mutations localized and makes state transitions easy to diagram.

6. **Feature layer as user actions**
   The `features` layer contains reusable user intents that operate on entities:
   - archive/remove/restore habits
   - manage notes
   - import/export/clear application data
   - check achievements
   - update habit progress
   - handle PWA install prompts
   These are not full screens; they are action modules that orchestrate entity updates and side effects.

7. **Widgets as screen-level composites**
   The `widgets` layer assembles entities and features into larger UI blocks such as:
   - **habit-list**, **habit-form**, **habit-stats**
   - **note-list**, **note-form**
   - **achievement-list**
   - **app-header**, **calendar-settings**, **interface-settings**
   - **welcome-view**
   These are the main composition units used inside pages. A diagram should show widgets as the bridge between page shell and domain logic.

8. **Data and analytics flow**
   Habit data is transformed through a substantial set of domain helpers in `src/entities/habit/lib` and `src/shared/lib/date-time`. These compute streaks, completion counts by day/month, gaps, progress for today, reorderings, and duplicate/title checks. The statistics pages and widgets are therefore **derived-data consumers**, not separate sources of truth.

9. **Persistence and portability**
   The app is explicitly **offline-first / privacy-first**. The readme says data stays on-device in **IndexedDB**, and the codebase also includes local storage helpers plus data-management flows for **export, import, and clear**. The architecture therefore has a local persistence boundary, with portability features designed around that storage model.

10. **PWA and offline behavior**
   The `public` folder includes a **service worker**, `_redirects`, `robots.txt`, and sitemap assets, indicating PWA deployment and SPA hosting support. There are also PWA-specific hooks and state (`pwa-install`, `usePwaStatus`, `PWABadge.tsx`). Offline availability and installability are first-class architectural concerns, not an afterthought.

11. **Cross-cutting UI infrastructure**
   Shared UI primitives live under `src/shared/ui` and include cards, dialogs, drawers, overlays, calendars, segmented controls, switches, year picker, menu lists, and modal layout components. These primitives are reused by widgets/pages to keep design consistent and to centralize animation and accessibility behavior.

12. **Internationalization and theming**
   The app supports multiple locales via `src/shared/lib/i18n/locales` (`de`, `en`, `es`, `ja`, `ru`, `zh`) and a dedicated i18n provider/config. Theme handling is also centralized through shared theme helpers and settings hooks. In the diagram, these are cross-cutting services applied across the whole app, not page-specific logic.

13. **Platform utilities**
   Shared libraries cover date math, DOM helpers, text/tag extraction, animation, clipboard, screenshots, scroll-to-top, native back-close behavior, intersection observation, and system motion preferences. These are infrastructural utilities that support the product experience, especially calendar/streak visualization and mobile-like interactions.

14. **Practical diagram shape**
   A useful architecture diagram would show:
   - **App shell/providers** at the top
   - **Pages** as route targets
   - **Widgets** composing each page
   - **Features** performing user actions
   - **Entities** as domain state and business logic
   - **Shared** as the foundation for UI, routing, storage, i18n, and utility functions
   The main system boundary is the browser itself: all meaningful state and behavior stay client-side.

Main entry points: [`src/app/providers/router/ui/AppRouter.tsx`](https://github.com/gazi2050/dohabit/blob/main/src/app/providers/router/ui/AppRouter.tsx) (Router), [`src/shared`](https://github.com/gazi2050/dohabit/tree/main/src/shared) (Shared), [`src/app/App.tsx`](https://github.com/gazi2050/dohabit/blob/main/src/app/App.tsx) (App), [`src/widgets/habit-list/ui/main/HabitList.tsx`](https://github.com/gazi2050/dohabit/blob/main/src/widgets/habit-list/ui/main/HabitList.tsx) (Habit list)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_app["App shell"]
  node_main["Main<br/>entry point<br/>[main.tsx]"]
  node_app_shell["App<br/>composition shell<br/>[App.tsx]"]
  node_router_provider["Router<br/>routing provider<br/>[AppRouter.tsx]"]
  node_i18n_provider["i18n<br/>locale provider<br/>[i18nConfig.ts]"]
  node_error_fallback["Error UI<br/>fallback ui<br/>[ErrorFallback.tsx]"]
end

subgraph group_pages["Pages"]
  node_main_page["Main page<br/>route screen<br/>[MainPage.tsx]"]
  node_archive_page["Archive page<br/>route screen<br/>[ArchivePage.tsx]"]
  node_diary_page["Diary page<br/>route screen<br/>[DiaryPage.tsx]"]
  node_editor_page["Habit editor<br/>route screen"]
  node_stats_page["Habit stats<br/>route screen"]
  node_data_page["Data management<br/>route screen"]
end

subgraph group_widgets["Widgets"]
  node_habit_list["Habit list<br/>widget composite<br/>[HabitList.tsx]"]
  node_habit_form["Habit form<br/>widget composite<br/>[HabitForm.tsx]"]
  node_note_list["Note list<br/>widget composite<br/>[NoteList.tsx]"]
  node_habit_stats["Habit stats<br/>widget composite<br/>[StreakOverview.tsx]"]
  node_app_header["App header<br/>navigation widget<br/>[AppHeader.tsx]"]
end

subgraph group_features["Features"]
  node_archive_habit["Archive habit<br/>action feature<br/>[archiveHabit.ts]"]
  node_progress_update["Update progress<br/>action feature"]
  node_notes_feature["Manage notes<br/>action feature"]
  node_data_ops["Data ops<br/>action feature<br/>[exportAppData.ts]"]
end

subgraph group_entities["Entities"]
  node_habit_entity[("Habit<br/>domain entity<br/>[store.ts]")]
  node_note_entity[("Note<br/>domain entity<br/>[store.ts]")]
  node_achievement_entity[("Achievement<br/>derived entity<br/>[store.ts]")]
  node_settings_entity[("Settings<br/>preferences entity<br/>[store.ts]")]
end

subgraph group_shared["Shared"]
  node_shared_foundation{{"Shared<br/>platform foundation"}}
end

node_main -->|"renders"| node_app_shell
node_app_shell -->|"routes"| node_router_provider
node_app_shell -->|"locales"| node_i18n_provider
node_app_shell -->|"fallback"| node_error_fallback
node_router_provider -->|"route"| node_main_page
node_router_provider -->|"route"| node_archive_page
node_router_provider -->|"route"| node_diary_page
node_router_provider -->|"route"| node_editor_page
node_router_provider -->|"route"| node_stats_page
node_router_provider -->|"route"| node_data_page
node_main_page -->|"uses"| node_app_header
node_main_page -->|"composes"| node_habit_list
node_editor_page -->|"composes"| node_habit_form
node_diary_page -->|"composes"| node_note_list
node_stats_page -->|"composes"| node_habit_stats
node_archive_page -->|"composes"| node_habit_list
node_habit_list -->|"actions"| node_progress_update
node_habit_list -->|"actions"| node_archive_habit
node_note_list -->|"actions"| node_notes_feature
node_data_page -->|"actions"| node_data_ops
node_habit_list -->|"reads"| node_habit_entity
node_habit_form -->|"writes"| node_habit_entity
node_note_list -->|"reads"| node_note_entity
node_habit_stats -->|"derives"| node_habit_entity
node_habit_stats -->|"derives"| node_achievement_entity
node_app_shell -->|"preferences"| node_settings_entity
node_habit_entity -->|"uses"| node_shared_foundation
node_note_entity -->|"uses"| node_shared_foundation
node_settings_entity -->|"uses"| node_shared_foundation
node_data_ops -->|"storage"| node_shared_foundation
node_router_provider -->|"routes"| node_shared_foundation
node_i18n_provider -->|"locales"| node_shared_foundation

click node_main "https://github.com/gazi2050/dohabit/blob/main/src/main.tsx"
click node_app_shell "https://github.com/gazi2050/dohabit/blob/main/src/app/App.tsx"
click node_router_provider "https://github.com/gazi2050/dohabit/blob/main/src/app/providers/router/ui/AppRouter.tsx"
click node_i18n_provider "https://github.com/gazi2050/dohabit/blob/main/src/app/providers/i18n/config/i18nConfig.ts"
click node_error_fallback "https://github.com/gazi2050/dohabit/blob/main/src/app/components/error-fallback/ErrorFallback.tsx"
click node_main_page "https://github.com/gazi2050/dohabit/blob/main/src/pages/main/ui/MainPage.tsx"
click node_archive_page "https://github.com/gazi2050/dohabit/blob/main/src/pages/archive/ui/ArchivePage.tsx"
click node_diary_page "https://github.com/gazi2050/dohabit/blob/main/src/pages/diary/ui/DiaryPage.tsx"
click node_editor_page "https://github.com/gazi2050/dohabit/blob/main/src/pages/habit-editor/ui/HabitEditorPage.tsx"
click node_stats_page "https://github.com/gazi2050/dohabit/blob/main/src/pages/habit-statistics/ui/HabitStatisticsPage.tsx"
click node_data_page "https://github.com/gazi2050/dohabit/blob/main/src/pages/data-management/ui/DataManagementPage.tsx"
click node_habit_list "https://github.com/gazi2050/dohabit/blob/main/src/widgets/habit-list/ui/main/HabitList.tsx"
click node_habit_form "https://github.com/gazi2050/dohabit/blob/main/src/widgets/habit-form/ui/HabitForm.tsx"
click node_note_list "https://github.com/gazi2050/dohabit/blob/main/src/widgets/note-list/ui/NoteList.tsx"
click node_habit_stats "https://github.com/gazi2050/dohabit/blob/main/src/widgets/habit-stats/streak-overview/ui/StreakOverview.tsx"
click node_app_header "https://github.com/gazi2050/dohabit/blob/main/src/widgets/app-header/ui/AppHeader.tsx"
click node_archive_habit "https://github.com/gazi2050/dohabit/blob/main/src/features/archive-habit/model/archiveHabit.ts"
click node_progress_update "https://github.com/gazi2050/dohabit/blob/main/src/features/update-habit-progress/ui/main/UpdateHabitProgress.tsx"
click node_notes_feature "https://github.com/gazi2050/dohabit/blob/main/src/features/manage-note/model/useNoteFormStore.ts"
click node_data_ops "https://github.com/gazi2050/dohabit/blob/main/src/features/data-management/export-data/model/exportAppData.ts"
click node_habit_entity "https://github.com/gazi2050/dohabit/blob/main/src/entities/habit/model/store.ts"
click node_note_entity "https://github.com/gazi2050/dohabit/blob/main/src/entities/note/model/store.ts"
click node_achievement_entity "https://github.com/gazi2050/dohabit/blob/main/src/entities/achievement/model/store.ts"
click node_settings_entity "https://github.com/gazi2050/dohabit/blob/main/src/entities/settings/model/store.ts"
click node_shared_foundation "https://github.com/gazi2050/dohabit/tree/main/src/shared"

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_main,node_app_shell,node_router_provider,node_i18n_provider,node_error_fallback toneBlue
class node_main_page,node_archive_page,node_diary_page,node_editor_page,node_stats_page,node_data_page toneAmber
class node_habit_list,node_habit_form,node_note_list,node_habit_stats,node_app_header toneMint
class node_archive_habit,node_progress_update,node_notes_feature,node_data_ops toneRose
class node_habit_entity,node_note_entity,node_achievement_entity,node_settings_entity toneIndigo
class node_shared_foundation toneTeal
```

## Components

### App shell

Entry point, providers, and global wiring

- [Main](https://github.com/gazi2050/dohabit/blob/main/src/main.tsx): entry point · Bootstraps the React app · `src/main.tsx`
- [App](https://github.com/gazi2050/dohabit/blob/main/src/app/App.tsx): composition shell · Top-level app composition and global UI wiring · `src/app/App.tsx`
- [Router](https://github.com/gazi2050/dohabit/blob/main/src/app/providers/router/ui/AppRouter.tsx): routing provider · Route configuration and navigation boundaries · `src/app/providers/router/ui/AppRouter.tsx`
- [i18n](https://github.com/gazi2050/dohabit/blob/main/src/app/providers/i18n/config/i18nConfig.ts): locale provider · Internationalization setup and locale loading · `src/app/providers/i18n/config/i18nConfig.ts`
- [Error UI](https://github.com/gazi2050/dohabit/blob/main/src/app/components/error-fallback/ErrorFallback.tsx): fallback ui · Global error boundary fallback component · `src/app/components/error-fallback/ErrorFallback.tsx`

### Pages

Route-level screen boundaries

- [Main page](https://github.com/gazi2050/dohabit/blob/main/src/pages/main/ui/MainPage.tsx): route screen · Primary habit overview and default landing page · `src/pages/main/ui/MainPage.tsx`
- [Archive page](https://github.com/gazi2050/dohabit/blob/main/src/pages/archive/ui/ArchivePage.tsx): route screen · Archived habit browser · `src/pages/archive/ui/ArchivePage.tsx`
- [Diary page](https://github.com/gazi2050/dohabit/blob/main/src/pages/diary/ui/DiaryPage.tsx): route screen · Habit-linked notes and journal view · `src/pages/diary/ui/DiaryPage.tsx`
- [Habit editor](https://github.com/gazi2050/dohabit/blob/main/src/pages/habit-editor/ui/HabitEditorPage.tsx): route screen · Create and edit habit details · `src/pages/habit-editor/ui/HabitEditorPage.tsx`
- [Habit stats](https://github.com/gazi2050/dohabit/blob/main/src/pages/habit-statistics/ui/HabitStatisticsPage.tsx): route screen · Habit analytics and streak summaries · `src/pages/habit-statistics/ui/HabitStatisticsPage.tsx`
- [Data management](https://github.com/gazi2050/dohabit/blob/main/src/pages/data-management/ui/DataManagementPage.tsx): route screen · Import, export, and clear local data · `src/pages/data-management/ui/DataManagementPage.tsx`

### Widgets

Screen-level composites

- [Habit list](https://github.com/gazi2050/dohabit/blob/main/src/widgets/habit-list/ui/main/HabitList.tsx): widget composite · Main habit collection and list interactions · `src/widgets/habit-list/ui/main/HabitList.tsx`
- [Habit form](https://github.com/gazi2050/dohabit/blob/main/src/widgets/habit-form/ui/HabitForm.tsx): widget composite · Habit editing form and field set · `src/widgets/habit-form/ui/HabitForm.tsx`
- [Note list](https://github.com/gazi2050/dohabit/blob/main/src/widgets/note-list/ui/NoteList.tsx): widget composite · Diary note collection with filters and sorting · `src/widgets/note-list/ui/NoteList.tsx`
- [Habit stats](https://github.com/gazi2050/dohabit/blob/main/src/widgets/habit-stats/streak-overview/ui/StreakOverview.tsx): widget composite · Derived analytics blocks for habits · `src/widgets/habit-stats/streak-overview/ui/StreakOverview.tsx`
- [App header](https://github.com/gazi2050/dohabit/blob/main/src/widgets/app-header/ui/AppHeader.tsx): navigation widget · Top-level navigation and page actions · `src/widgets/app-header/ui/AppHeader.tsx`

### Features

Reusable user actions

- [Archive habit](https://github.com/gazi2050/dohabit/blob/main/src/features/archive-habit/model/archiveHabit.ts): action feature · Moves habits between active and archived states · `src/features/archive-habit/model/archiveHabit.ts`
- [Update progress](https://github.com/gazi2050/dohabit/blob/main/src/features/update-habit-progress/ui/main/UpdateHabitProgress.tsx): action feature · Records habit completion and progress state · `src/features/update-habit-progress/ui/main/UpdateHabitProgress.tsx`
- [Manage notes](https://github.com/gazi2050/dohabit/blob/main/src/features/manage-note/model/useNoteFormStore.ts): action feature · Create, edit, and remove habit notes · `src/features/manage-note/model/useNoteFormStore.ts`
- [Data ops](https://github.com/gazi2050/dohabit/blob/main/src/features/data-management/export-data/model/exportAppData.ts): action feature · Import, export, and clear application data · `src/features/data-management/export-data/model/exportAppData.ts`

### Entities

Domain state and business logic

- [Habit](https://github.com/gazi2050/dohabit/blob/main/src/entities/habit/model/store.ts): domain entity · Core habit aggregate, lifecycle, ordering, and progress · `src/entities/habit/model/store.ts`
- [Note](https://github.com/gazi2050/dohabit/blob/main/src/entities/note/model/store.ts): domain entity · Habit-linked journal entry state · `src/entities/note/model/store.ts`
- [Achievement](https://github.com/gazi2050/dohabit/blob/main/src/entities/achievement/model/store.ts): derived entity · Badge and milestone state derived from habit activity · `src/entities/achievement/model/store.ts`
- [Settings](https://github.com/gazi2050/dohabit/blob/main/src/entities/settings/model/store.ts): preferences entity · Theme and language preferences · `src/entities/settings/model/store.ts`

### Shared

Foundation: UI, utilities, storage, and cross-cutting services

- [Shared](https://github.com/gazi2050/dohabit/tree/main/src/shared): platform foundation · Reusable UI, storage, router, i18n, and utilities · `src/shared`

## Connections

- Main → App: renders · Entry point mounts the application shell
- App → Router: routes · App shell delegates screen selection to the router
- App → i18n: locales · App shell initializes internationalization
- App → Error UI: fallback · Global error boundary uses the fallback UI
- Router → Main page: route · Routing resolves to the main page
- Router → Archive page: route · Routing resolves to archive page
- Router → Diary page: route · Routing resolves to diary page
- Router → Habit editor: route · Routing resolves to habit editor
- Router → Habit stats: route · Routing resolves to habit statistics
- Router → Data management: route · Routing resolves to data management
- Main page → App header: uses · Main page includes global navigation chrome
- Main page → Habit list: composes · Main page is built from habit list widgets
- Habit editor → Habit form: composes · Editor page is centered on the habit form
- Diary page → Note list: composes · Diary page surfaces note management widgets
- Habit stats → Habit stats: composes · Stats page displays derived analytics widgets
- Archive page → Habit list: composes · Archive page reuses the habit list shell
- Habit list → Update progress: actions · Habit list triggers progress updates
- Habit list → Archive habit: actions · Habit list triggers archive and restore flows
- Note list → Manage notes: actions · Note widgets orchestrate note editing flows
- Data management → Data ops: actions · Data management page exposes import/export/clear
- Habit list → Habit: reads · Habit list consumes core habit state
- Habit form → Habit: writes · Form updates habit state through entity handlers
- Note list → Note: reads · Diary notes render from note entity state
- Habit stats → Habit: derives · Statistics are computed from habit history
- Habit stats → Achievement: derives · Achievement-related views consume derived milestones
- App → Settings: preferences · App shell and providers apply theme and language state
- Habit → Shared: uses · Domain logic relies on shared date-time and storage helpers
- Note → Shared: uses · Notes rely on shared storage and text utilities
- Settings → Shared: uses · Settings depend on shared theme and locale infrastructure
- Data ops → Shared: storage · Portability features operate on the local persistence layer
- Router → Shared: routes · Routing primitives live in shared router helpers
- i18n → Shared: locales · Locale definitions and i18n helpers are shared infrastructure
