Skip to content

Repository files navigation

AURIX

AURIX is a Flutter-based strength-training and nutrition companion app: workout planning, active session logging, progress analytics, nutrition/water tracking, weekly performance reports, and an AI coach — all backed by Supabase (auth + Postgres + RLS) with Riverpod for state and GoRouter for navigation.

  • Client: Flutter (Dart SDK ^3.12.2), targets Android, iOS, macOS, Windows, Linux, and Web.
  • Backend: Supabase (Postgres, Auth, Row Level Security).
  • AI: Groq API (chat + vision models) for coaching, meal-photo estimation, post-workout feedback, and weekly report narratives.

Table of Contents


What the app does

AURIX is a full training companion rather than a single-purpose workout log:

  • Auth & onboarding — splash/session gate, email sign-up/sign-in, and a guided onboarding flow that collects goal, experience level, gym access, and body data before creating a profile.
  • Dashboard — current training status, a "Quick Start" card (including resume-in-progress-workout support), recent activity, and streak tracking.
  • Workout planning — plan templates, custom plan creation/editing, weekly schedules, and multi-day program grouping (e.g. Push/Pull/Legs saved and shown as one program).
  • Active workouts — set-by-set logging with rest timers, RPE per set, the ability to minimize/leave and resume a workout without losing progress, and an explicit Cancel Workout action.
  • Post-workout AI feedback — every completed session is reviewed by the AI coach (wins, improvements, a focus for next time) on the Workout Summary screen.
  • Exercise library & detail views — browsing by muscle/equipment/difficulty with per-exercise detail pages.
  • Progress tracking — personal records, activity history, adaptive training-streak calculation, and a body-weight log/trend chart.
  • Nutrition tracking — meal logging by free-text description or by scanning a photo of a meal (both AI-estimated), plus water intake logging and calorie/macro targets (auto-calculated from BMR/TDEE or manually overridden).
  • Weekly reports — an automatically generated, scored (consistency / nutrition / progress) Mon–Sun recap with an AI-written narrative summary, wins, improvements, and a focus for the next week.
  • AI Coach screen — a guided chat experience, with history persisted per user.
  • Achievements and utility tools (plate calculator).
  • Profile & settings — units (kg/lb), notification preferences, and a Danger Zone "Clear All Workout Data" option that wipes plans/sessions/PRs/streak data/body-weight log while keeping the account and profile.

Tech stack

Concern Package
State management flutter_riverpod
Navigation go_router
Backend supabase_flutter
Local secrets flutter_dotenv
Local notifications flutter_local_notifications
Charts fl_chart
Fonts / UI polish google_fonts, flutter_animate, shimmer, flutter_svg
Images (nutrition scan) image_picker
Sharing share_plus
Misc intl, uuid, shared_preferences, http, path_provider
Lints flutter_lints

See pubspec.yaml for exact version constraints.

Project structure

lib/
├── main.dart                # Bootstraps Flutter, loads .env, initializes Supabase & notifications, starts the app
├── app.dart                 # Root MaterialApp.router + global theme
├── app_router.dart          # GoRouter route tree (see Navigation below)
├── app_const.dart           # Typed accessors over .env (throws if required keys are missing)
├── Supabase/
│   └── supabase_service.dart      # Supabase client init/session helpers
├── services/
│   └── notification_service.dart  # Local notification channel setup
├── data/
│   └── app_data.dart               # In-memory app-wide cache/state, synced with Supabase
├── theme/                          # app_colors.dart, app_text.dart, app_theme.dart
├── widgets/                        # ff_nav.dart (bottom nav shell), ff_widgets.dart (shared UI)
├── utils/                          # nutrition_calc.dart, progressive_overload.dart, streak_utils.dart, units.dart
└── features/
    ├── auth/                       # splash, login, signup, onboarding flow
    │   ├── data/                   # auth_repository.dart, auth_mock_data.dart (static UI copy, not fake data)
    │   └── models/, presentation/
    ├── dashboard/                  # home dashboard + profile/settings screen
    │   ├── data/dashboard_repository.dart
    │   └── models/, presentation/
    ├── workout/                    # hub, active session, plan creation, library, detail,
    │   │                           # progress, weekly schedule, template customize, session edit, summary
    │   ├── data/workout_repository.dart
    │   └── models/, presentation/
    ├── nutrition/                  # meal/water logging, AI photo & text estimation
    │   ├── data/nutrition_repository.dart, nutrition_ai_service.dart
    │   └── models/, presentation/
    ├── reports/                    # weekly report scoring, AI narrative, screen
    │   └── data/, models/, presentation/
    ├── AI_Coach/                   # AI coach chat screen + post-workout feedback service
    │   ├── ai_coach_screen.dart
    │   └── data/workout_feedback_service.dart
    ├── achievements/                # models/, presentation/
    └── tools/
        └── plate_calculator_screen.dart

Platform folders (android/, ios/, macos/, windows/, linux/, web/) contain the standard Flutter-generated native runners plus the app's icons and platform config. Supabase SQL lives in supabase/, and test/widget_test.dart holds the starter widget test.

Navigation

Routing is defined in lib/app_router.dart using GoRouter:

  • Entry routes: /splash, /login, /signup, /onboarding.
  • Full-screen routes (pushed above the bottom nav, on the root navigator): /active-workout, /workout-summary, /create-workout (accepts an existing WorkoutPlan via extra to edit in place), /schedule, /template-customize, /exercise/:id, /profile, /plate-calculator, /achievements, /edit-session, /weekly-report.
  • Shell routes (nested under the bottom-nav FFShell): /home (Dashboard), /workouts (Workout Hub), /nutrition, /exercises (Exercise Library), /progress, /ai (AI Coach).

Data model

The Supabase schema (see DB_SCHEMA.md for the full reference, informational only — not meant to be executed as-is) covers:

Table Purpose
profiles User settings, goal/level, body data, macro targets, notification & unit preferences
exercises Global exercise catalog (name, muscle, equipment, difficulty, description)
workout_plans / plan_exercises User-created plans and their exercises; program_id/program_name group multi-day programs
plan_templates / template_exercises Built-in template library used to seed new plans
workout_sessions / session_exercises Logged workouts and their per-set data (includes RPE)
personal_records PR tracking per exercise
daily_activity Per-day activity used for streak/progress calculations
body_metrics Body-weight log entries (Progress → Body tab trend chart)
coach_messages AI Coach chat history
meal_logs / water_logs Nutrition tracking (event-based: one row per logged meal / per water addition)
weekly_reports One row per Mon–Sun week: deterministic scores plus an AI-generated narrative

All weights are stored in kg regardless of the user's display-unit preference (profiles.weight_unit is display-only).

Row Level Security is enabled on every user-data table (supabase/rls_policies.sql), scoping all access to auth.uid(). exercises, plan_templates, and template_exercises are shared catalog data and get public read-only access instead.

Getting started

  1. Install Flutter and make sure your environment is set up for your target platform(s) (flutter doctor).

  2. Clone and install packages:

    flutter pub get
  3. Create your local secrets file:

    cp .env.example .env      # macOS/Linux
    copy .env.example .env    # Windows
  4. Fill in .env:

    SUPABASE_URL=https://your-project-ref.supabase.co
    SUPABASE_ANON_KEY=your-supabase-anon-key
    
    GROQ_API_KEY=your-groq-api-key
    GROQ_MODEL=llama3-8b-8192
    GROQ_VISION_MODEL=meta-llama/llama-4-scout-17b-16e-instruct

    SUPABASE_URL and SUPABASE_ANON_KEY are required at startup — the app throws a clear error on launch if either is missing (see lib/app_const.dart). GROQ_API_KEY is only required when an AI feature (AI Coach, nutrition photo scan, post-workout feedback, weekly report narrative) is actually used.

  5. Set up your Supabase project — see Supabase setup below.

  6. Run the app:

    flutter run

AI / Groq configuration

The AI Coach screen, the nutrition photo-scan estimator, the post-workout feedback card, and the weekly report narrative all call the Groq API using the same key from .env:

  • GROQ_API_KEY — your Groq API key.
  • GROQ_MODEL — text model used for chat/coaching/report narrative (default: llama3-8b-8192).
  • GROQ_VISION_MODEL — multimodal model used only by nutrition's "Scan Photo" feature (default: meta-llama/llama-4-scout-17b-16e-instruct). Groq's vision lineup changes more often than its text models — if this stops working, check console.groq.com/docs/vision for a current model and update .env; no code changes needed.

This key ships inside the compiled app bundle, so it is not a production-safe secret — anyone can extract it from a release build. For a real production deployment, proxy these requests through a backend (e.g. a Supabase Edge Function) that holds the real key server-side, and call that function from the app instead of calling Groq directly.

Notifications

lib/services/notification_service.dart configures local notification channels for:

  • Workout reminders
  • Rest-timer completion
  • Weekly training summaries

Channels are initialized at startup, but the OS permission prompt is only requested when the user enables the corresponding toggle in Profile settings — not on first launch.

Platform notes

  • The app launches in portrait orientation only.
  • The app uses an always-dark theme (status bar icons are set to light to stay visible against it).
  • The app runs in immersive/fullscreen mode (system status/navigation bars hidden) and re-hides them if the user swipes them back into view.
  • The nutrition photo-scan feature requests camera and photo-library access on first use of "Scan Photo" — see NSCameraUsageDescription/NSPhotoLibraryUsageDescription in ios/Runner/Info.plist and the CAMERA permission in android/app/src/main/AndroidManifest.xml.
  • Android applicationId/namespace: com.aurix.fitness (see android/app/build.gradle.kts).

Android release signing

Release builds are unsigned (fall back to debug signing) until you configure your own keystore:

  1. Generate a keystore once:

    keytool -genkey -v -keystore ~/aurix-release.jks \
      -keyalg RSA -keysize 2048 -validity 10000 \
      -alias aurix

    Keep the resulting .jks file and its passwords safe and backed up — whoever holds it can publish updates to the app, and losing it means you can never update the app under the same listing again.

  2. Copy android/key.properties.example to android/key.properties (already gitignored) and fill in:

    storePassword=<your keystore password>
    keyPassword=<your key password>
    keyAlias=aurix
    storeFile=/absolute/path/to/aurix-release.jks
  3. flutter build appbundle --release will then sign with your real key automatically. Until key.properties exists, flutter run --release still works locally with debug signing, but a debug-signed build will be rejected by the Play Store.

Known behaviors worth knowing about

A few intentional design choices and open items, so they aren't mistaken for bugs:

  • Adaptive training streaks (lib/utils/streak_utils.dart, computeTrainingStreak) infer your typical training frequency from the last 4 weeks and tolerate that many rest days between sessions without resetting the streak — a genuine multi-day lapse still resets it. Dashboard, Progress, and Profile all share this one implementation.
  • Resumable active workouts: in-progress session state (checked sets, weights, elapsed time) lives in AppData, not screen-local state, so minimizing an active workout (▾ button or Android back) and returning later restores exactly where you left off. Elapsed time is computed from a wall-clock startedAt, so it keeps counting even while the screen isn't mounted.
  • Optimistic plan creation: AppData.addPlan() falls back to a temporary client-side id if the Supabase insert fails, so the UI doesn't appear broken on a flaky connection — but this means a failed write can silently diverge from the database until the next full reload.
  • Exercise Library reads from a static in-app list, not the exercises table, even though WorkoutRepository.fetchExerciseCatalog() exists — functionally fine since it's read-only reference data, but editing the catalog currently requires a code change rather than a database update.
  • "Clear All Workout Data" (Profile → Danger Zone) deletes plans, session history, PRs, streak/daily-activity data, and the body-weight log, but keeps the account and profile — so the user lands on a clean dashboard rather than back in onboarding.

Useful references

About

AI-powered fitness tracker built with Flutter & Supabase — workout planning, session logging, nutrition tracking, and an AI coach.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages