Habit tracker Β· reflection journal Β· analytics Β· AI chat β a Flutter Web Telegram Mini App.
English Β· Π ΡΡΡΠΊΠΈΠΉ
π€ Live bot β @habit_flow_app_bot
Flutter Web Mini App that runs inside Telegram. It authenticates with
initData, talks to Supabase over PostgREST, and renders the full HabitFlow experience β Today, Habits, Journal, Analytics, AI, and Profile. Also ships an Android build (login via bot deep-link) from the same codebase. The companion notification bot lives in habit_flow_bot.
πΈ Screenshots coming soon.
- Today β only habits due now, one-tap done/skip, all-done celebration
- Habits β CRUD with emoji / Telegram-photo icons, colors, schedules, swipe-to-archive/delete
- Habit detail β calendar heatmap, history, streaks & recovery, anti-habit "days since"
- Journal β reflection entries with optional templates
- Analytics β completion rate, trends, activity heatmap (
fl_chart+table_calendar) - AI β chat, periodic summaries, and ready-made prompt buttons (OpenRouter, bring your own key)
- Profile β settings, AI key, donations (Telegram Stars), about/contact
- Bilingual RU + EN, Material 3 theme overridden from
Telegram.WebApp.themeParams
flutter pub get
flutter run -d chrome --web-port=5173 \
--dart-define=SUPABASE_URL=https://xxx.supabase.co \
--dart-define=SUPABASE_ANON_KEY=xxxRelease web build:
flutter build web --release \
--dart-define=SUPABASE_URL=https://xxx.supabase.co \
--dart-define=SUPABASE_ANON_KEY=xxx \
--dart-define=ENV=productionCommon dev commands:
flutter analyze
flutter test
dart run build_runner build --delete-conflicting-outputs # freezed / json / riverpod
flutter gen-l10n # after editing .arb filesEnv.assertValid() runs in main.dart before runApp and fails fast with a clear
StateError if a required value is missing.
| Key | Required | Default | Purpose |
|---|---|---|---|
SUPABASE_URL |
β | β | Supabase project URL |
SUPABASE_ANON_KEY |
β | β | Supabase public anon key |
OPENROUTER_BASE_URL |
β | https://openrouter.ai/api/v1 |
OpenRouter base URL |
OPENROUTER_DEFAULT_MODEL |
β | openai/gpt-oss-120b:free |
default AI model |
ENV |
β | development |
production enables strict modes (Env.isProduction) |
APP_BASE_URL |
β | https://habitflow.app |
canonical Mini App URL (HTTP-Referer) |
BOT_PUBLIC_CHANNEL |
β | https://t.me/habitflow_dev |
public Telegram channel/chat |
OPENROUTER_KEYS_URL |
β | https://openrouter.ai/keys |
OpenRouter keys dashboard |
π The OpenRouter API key is the user's own, stored in
flutter_secure_storage(WebCrypto on Web).BOT_TOKENandSUPABASE_SERVICE_ROLE_KEYnever live here.
Feature-first. Each feature owns data/ (models + repository), domain/ (pure
functions), and presentation/ (screens + widgets).
lib/
βββ main.dart, app.dart
βββ core/
β βββ config/ # env, theme
β βββ routing/ # go_router
β βββ services/ # supabase, telegram, openrouter, notifications
β βββ localization/ # .arb + generated
β βββ utils/
βββ features/
β βββ auth/ # splash + initData β JWT
β βββ habits/ # CRUD, Today, Habits
β βββ journal/ # reflection journal
β βββ analytics/ # Analytics tab
β βββ ai/ # chat, summaries, prompts
β βββ profile/ # settings, donations
β βββ onboarding/
βββ shared/widgets/
- State β Riverpod, preferably
@riverpodcodegen. - Models β
freezed+json_serializable. - Routing β
go_router. Deep links?screen=...&id=...are required for the bot. - Theme β Material 3, overridden by
Telegram.WebApp.themeParamsviaTelegramService. - Localization β
AppLocalizations.of(context)!.<key>. No hard-coded UI strings. - Telegram Mini App limits β no background API; habit timers are frontend, resumed from
last_active_at. - Comments β only "why", never "what the code does".
- Design β mockups arrive separately and are copied 1:1, never interpreted.
BOT_TOKEN,SUPABASE_SERVICE_ROLE_KEYβ never on the client.initDatais logged masked only.- Authorization is server-side
initDatavalidation.tg.initDataUnsafeis for UI params (name, avatar) only β never for auth.
- CLAUDE.md β agent guide for this package
- PLATFORMS.md Β· PERF.md Β· RATE_LIMITS.md Β· MANUAL_QA.md
- Companion bot β habit_flow_bot
MIT Β© 2026 zFannur.