How gazi2050/dohabit works
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: AppRouter.tsx Router · shared Shared · App.tsx App · HabitList.tsx Habit list
Components 25
App shell
Entry point, providers, and global wiring
- Main · Bootstraps the React app
src/main.tsx - App · Top-level app composition and global UI wiring
src/app/App.tsx - Router · Route configuration and navigation boundaries
src/app/providers/router/ui/AppRouter.tsx - i18n · Internationalization setup and locale loading
src/app/providers/i18n/config/i18nConfig.ts - Error UI · Global error boundary fallback component
src/app/components/error-fallback/ErrorFallback.tsx
Pages
Route-level screen boundaries
- Main page · Primary habit overview and default landing page
src/pages/main/ui/MainPage.tsx - Archive page · Archived habit browser
src/pages/archive/ui/ArchivePage.tsx - Diary page · Habit-linked notes and journal view
src/pages/diary/ui/DiaryPage.tsx - Habit editor · Create and edit habit details
src/pages/habit-editor/ui/HabitEditorPage.tsx - Habit stats · Habit analytics and streak summaries
src/pages/habit-statistics/ui/HabitStatisticsPage.tsx - Data management · Import, export, and clear local data
src/pages/data-management/ui/DataManagementPage.tsx
Widgets
Screen-level composites
- Habit list · Main habit collection and list interactions
src/widgets/habit-list/ui/main/HabitList.tsx - Habit form · Habit editing form and field set
src/widgets/habit-form/ui/HabitForm.tsx - Note list · Diary note collection with filters and sorting
src/widgets/note-list/ui/NoteList.tsx - Habit stats · Derived analytics blocks for habits
src/widgets/habit-stats/streak-overview/ui/StreakOverview.tsx - App header · Top-level navigation and page actions
src/widgets/app-header/ui/AppHeader.tsx
Features
Reusable user actions
- Archive habit · Moves habits between active and archived states
src/features/archive-habit/model/archiveHabit.ts - Update progress · Records habit completion and progress state
src/features/update-habit-progress/ui/main/UpdateHabitProgress.tsx - Manage notes · Create, edit, and remove habit notes
src/features/manage-note/model/useNoteFormStore.ts - Data ops · Import, export, and clear application data
src/features/data-management/export-data/model/exportAppData.ts
Entities
Domain state and business logic
- Habit · Core habit aggregate, lifecycle, ordering, and progress
src/entities/habit/model/store.ts - Note · Habit-linked journal entry state
src/entities/note/model/store.ts - Achievement · Badge and milestone state derived from habit activity
src/entities/achievement/model/store.ts - Settings · Theme and language preferences
src/entities/settings/model/store.ts
Shared
Foundation: UI, utilities, storage, and cross-cutting services
- Shared · Reusable UI, storage, router, i18n, and utilities
src/shared
Connections 32
- 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