AI-Powered Fitness App - A Flutter application that helps users create, manage, and execute personalized workouts with AI assistance.
Workouch is a comprehensive fitness application that combines AI-powered workout generation with manual workout management. The app offers two distinct modes: "The Shuffle" (AI-powered quick workouts) and "The Neat" (manual workout builder), providing flexibility for users of all fitness levels.
-
"The Shuffle" Mode: Generate workouts from natural language preferences
- Users describe their workout needs (e.g., "I have 30 minutes and a pair of dumbbells")
- AI analyzes preferences and generates personalized workouts
- Animated dialog shows AI thinking process with dynamic messages
-
"The Neat" Mode: Structured workout generation with detailed specifications
- Specify workout name, duration, intensity, goals, body parts, equipment, location
- Account for injuries/limitations
- AI generates workouts based on structured parameters
- Create & Edit Workouts: Build custom workouts with exercises, sets, and rest times
- Exercise Library: Browse and filter exercises by muscle groups, equipment, and body parts
- Multiple Set Types: Support for weight-based, time-based, distance-based, and reps-only sets
- Workout Persistence: Save workouts to cloud (Supabase) with automatic sync
- Interactive Workout Sessions: Step-by-step workout execution with timers
- Rest Timers: Automatic rest timers between sets and exercises
- Exercise Details: View GIFs, instructions, and muscle targets during workouts
- Progress Tracking: Track workout completion and duration
- Health Metrics: Track weight, height, BMI, activity level
- Social Authentication: Sign in with Google, Apple, or Email
- Profile Management: Update user information and preferences
- Modern UI: Clean, intuitive interface with smooth animations
- Responsive Design: Adaptive layouts using Flutter ScreenUtil
- Lottie Animations: Engaging loading animations and visual feedback
- Error Handling: Comprehensive error handling with user-friendly messages
The app follows Clean Architecture principles with clear separation of concerns:
lib/
βββ core/ # Core functionality
β βββ constants/ # App constants and configuration
β βββ di/ # Dependency injection (GetIt + Injectable)
β βββ router/ # Navigation (GoRouter)
β βββ services/ # Core services (Firebase, etc.)
β βββ theme/ # App theming and styling
β βββ utils/ # Utilities (error handling, logging)
β βββ widgets/ # Reusable UI components
β
βββ features/ # Feature modules
βββ auth/ # Authentication
β βββ data/ # Data layer (DTOs, services)
β βββ domain/ # Domain layer (entities, repositories)
β βββ presentation/ # Presentation layer (UI, Cubits)
βββ workout/ # Workout management
βββ workout_session/ # Workout execution
βββ home/ # Home screen
βββ profile/ # User profile
UI (Cubit/State)
β
Repository Interface (Domain)
β
Repository Implementation (Data)
β
Data Source (Supabase/API)
β
Database/External API
- Flutter 3.8.1+ - Cross-platform UI framework
- Dart - Programming language
- flutter_bloc ^9.1.1 - BLoC pattern for state management
- Cubit - Lightweight state management
- Supabase - Backend-as-a-Service (PostgreSQL, Auth, Storage)
- Row Level Security (RLS) - Data isolation and security
- Supabase Edge Functions - Authenticated proxy for exercise data and AI generation
- OpenAI API - AI workout generation via the server-side Exercise API
- get_it ^8.0.3 - Service locator
- injectable ^2.5.0 - Code generation for DI
- freezed ^2.5.8 - Immutable data classes
- json_serializable ^6.9.5 - JSON serialization
- supabase_flutter ^2.9.1 - Supabase authentication
- google_sign_in ^6.3.0 - Google Sign-In
- sign_in_with_apple ^7.0.1 - Apple Sign-In
- flutter_screenutil ^5.9.3 - Responsive design
- flutter_svg ^2.2.0 - SVG support
- google_fonts ^6.2.1 - Custom fonts
- lottie ^3.3.2 - Lottie animations
- cached_network_image ^3.4.1 - Image caching
- flutter_dotenv ^5.2.1 - Environment variables
- shared_preferences ^2.5.3 - Local storage
- go_router ^16.3.0 - Declarative routing
- oktoast ^3.4.0 - Toast notifications
- logger ^2.6.0 - Logging
- intl ^0.20.2 - Internationalization
- firebase_core ^3.15.1 - Firebase initialization
- firebase_crashlytics ^4.3.9 - Crash reporting
- firebase_analytics ^11.5.2 - Analytics
- purchases_flutter ^8.10.6 - RevenueCat for in-app purchases
- in_app_review ^2.0.10 - In-app review prompts
The app uses Supabase (PostgreSQL) with the following schema:
id(UUID, Primary Key)user_id(UUID, Foreign Key β auth.users)name(TEXT)rest_time_between_exercises(INTEGER, seconds)created_at(TIMESTAMPTZ)updated_at(TIMESTAMPTZ)
id(UUID, Primary Key)workout_id(UUID, Foreign Key β workouts)exercise_order(INTEGER)exercise_id(TEXT) - Reference to external exercise API- Exercise snapshot fields:
name,gif_url,description,target_muscles,body_parts,equipments,secondary_muscles,instructions rest_time_between_sets(INTEGER, seconds)set_type(TEXT) - 'weightBased', 'timeBased', 'distanceBased', 'repsOnly'sets(JSONB) - Array of set objectscreated_at(TIMESTAMPTZ)updated_at(TIMESTAMPTZ)
- Row Level Security (RLS) enabled on all tables
- Users can only access their own workouts
- Policies use
auth.uid() = user_idfor data isolation
- Automatic timestamps: Triggers update
updated_aton changes - Cascading deletes: Deleting a workout deletes associated exercises
- Indexes: Optimized queries on
user_idandexercise_order - JSONB sets: Flexible set storage with type-specific fields
See docs/workout_database_schema.md for detailed schema documentation.
- The mobile app invokes the authenticated
exercise-apiSupabase Edge Function. - The function proxies an allowlist of endpoints and supplies the private upstream key from Supabase secrets.
- Endpoints:
GET /exercises/filter- Filter and search exercisesGET /bodyparts- Get available body partsGET /equipments- Get available equipment typesPOST /workouts/generate- Generate AI workouts
- AI workout generation is handled through the Exercise DB API
- Uses OpenAI's Chat Completions API with vector store for exercise selection
- Two generation modes:
- Shuffle Mode: Natural language preferences β structured workout
- Neat Mode: Structured parameters β personalized workout
- Flutter SDK 3.8.1 or higher
- Dart SDK
- Android Studio / Xcode (for mobile development)
- Supabase account
- Exercise DB API access
-
Clone the repository
git clone <repository-url> cd workouch
-
Install dependencies
flutter pub get
-
Set up client configuration
cp .env.example .env
Fill in only public client identifiers. The
.envfile is bundled into the application; it is not a secret store. -
Configure Firebase
- Add
google-services.json(Android) toandroid/app/ - Add
GoogleService-Info.plist(iOS) toios/Runner/ - Configure Firebase project settings
- Add
-
Set up Supabase
- Create a Supabase project and configure Google/Apple authentication.
- Apply the SQL files in
docs/in this order:users_table.sql,user_subscription_table.sql,workout_database_schema.sql, andworkout_history_database_schema.sql. - Apply
supabase/migrations/20260830150510_public_release_hardening.sql. - Configure and deploy the server boundary:
supabase secrets set EXERCISE_DB_API_KEY=... REVENUECAT_SECRET_API_KEY=... supabase functions deploy exercise-api supabase functions deploy sync-subscription
-
Generate code
flutter pub run build_runner build --delete-conflicting-outputs
-
Run the app
flutter run
lib/
βββ core/
β βββ constants/ # App-wide constants
β βββ di/ # Dependency injection setup
β βββ router/ # Navigation configuration
β βββ services/ # Core services (Firebase)
β βββ theme/ # Colors, text styles, themes
β βββ utils/ # Utilities (errors, logging, extensions)
β βββ widgets/ # Reusable UI components
β
βββ features/
βββ auth/ # Authentication feature
β βββ data/
β β βββ models/dtos/ # Data Transfer Objects
β β βββ services/ # Auth services (Supabase)
β βββ domain/
β β βββ entities/ # Domain entities
β β βββ repositories/ # Repository interfaces
β βββ presentation/
β βββ cubit/ # State management
β βββ pages/ # UI pages
β
βββ workout/ # Workout management feature
β βββ data/
β β βββ models/
β β β βββ dtos/ # DTOs for API responses
β β β βββ requests/ # Request models
β β βββ repositories/ # Repository implementations
β β βββ services/ # Supabase and Edge Function services
β βββ domain/
β β βββ entities/ # Domain entities
β β βββ enums/ # Domain enums
β β βββ repositories/ # Repository interfaces
β βββ presentation/
β βββ cubit/ # State management
β βββ dialogs/ # Feature-specific dialogs
β βββ pages/ # UI pages
β βββ widgets/ # Feature-specific widgets
β
βββ workout_session/ # Workout execution feature
βββ home/ # Home screen feature
βββ profile/ # User profile feature
- Uses OpenAI API via Exercise DB backend
- Prompts are engineered to select exercises from a vector store
- Response format matches domain entities (camelCase JSON)
- Dynamic message updates during generation (every 5 seconds)
- Validates generated workouts have exercises before returning
- BLoC/Cubit pattern for predictable state management
- Separate Cubits for each feature (AuthCubit, WorkoutCubit, WorkoutSessionCubit)
- Immutable states using
freezed - Error handling via
Either<Error, T>pattern
- Centralized error handling in
core/utils/error.dart - Categorizes errors: network, server, validation, other
- User-friendly error messages
- Comprehensive exception handling with
handleExceptionutility
- Uses
get_itwithinjectablefor code generation - Lazy singletons for services and repositories
- Auto-generated
injection.config.dart
- UI triggers action via Cubit
- Cubit calls Repository interface
- Repository implementation calls Data Source
- Data Source interacts with Supabase/API
- Response converted to DTO β Entity
- Entity returned via
Either<Error, T> - Cubit updates state
- UI rebuilds with new state
The app supports four set types:
- Weight-Based: Sets Γ Reps Γ Weight (kg)
- Time-Based: Duration (seconds)
- Distance-Based: Distance (meters)
- Reps-Only: Sets Γ Reps (no weight)
Sets are stored as JSONB in PostgreSQL and converted to union types using freezed.
Run code generation after making changes to:
freezedclassesjson_serializableclassesinjectabledependencies
flutter pub run build_runner build --delete-conflicting-outputsThe project uses flutter_lints for code quality:
flutter analyzeAndroid:
flutter build apk --release
# or
flutter build appbundle --releaseiOS:
flutter build ios --releaseClient-visible values (.env file; see .env.example):
SUPABASE_URLSUPABASE_PUBLISHABLE_KEY(legacySUPABASE_ANON_KEYis also accepted)- Google OAuth client IDs
- PostHog's public project key and host
Server-only values are set with supabase secrets set and must never appear in
the Flutter .env file:
EXERCISE_DB_API_KEYREVENUECAT_SECRET_API_KEY
Firebase platform configuration files are also required. Firebase Analytics and Crashlytics are disabled by default until a user opts in.
- Row Level Security (RLS) on all database tables
- Paid entitlements are verified server-side with RevenueCat
- AI quotas are reserved atomically in PostgreSQL
- Private API keys are held in Supabase Edge Function secrets, never in the app
- Analytics and crash reporting are opt-in and disabled by default
- Secure authentication via Supabase Auth
- OAuth providers (Google, Apple) configured securely
- Input validation on all user inputs
No reuse license is currently granted. Public visibility does not make this project open source; all rights are reserved by the copyright holder. Choose and add an explicit license before accepting outside contributions or encouraging reuse. Third-party assets and dependencies remain subject to their own licenses.
See CONTRIBUTING.md.
For support, visit https://workouch.nosiahstudios.com/support or email vigor.workouch@gmail.com. Report security issues using SECURITY.md.
Built with β€οΈ using Flutter