Mobile client for the moveUP fitness platform.
- 🚀 Highlights
- 📦 Tech Stack
- 🏗️ Architecture
- 📂 Project Structure
- 🛠️ Getting Started
- 🧪 Testing
- 📖 Documentation
- 🐋 Docker Build
- 📝 Changelog
- 🏃 Fitness Start Onboarding: guest quiz, onboarding test catalog, guest test attempts, and completed-progress resume support before sign-up
- 🔐 End-to-end Auth Flow: sign in, sign up, email verification, password recovery, OTP verification, password reset, and logout
- 📶 Offline Flow: app-level connectivity tracking, blocking offline route, and automatic return to the auth flow after reconnect
- ✨ Startup Splash Flow: branded startup entry route with router-driven splash timing before auth or offline redirects
- 🏛️ Clean Architecture in feature modules (Data → Domain → Presentation)
- 🌐 Network Layer built on Dio + Retrofit
- 🧭 Navigation with GoRouter, session-aware redirects, and startup/offline gating
- 🎨 UIKit + Theming with shared buttons, dialogs, images, colors, gradients, and text styles
⚠️ Error Handling viaResultand typedFailurehierarchies- 💉 Dependency Injection with GetIt + Provider
| Category | Technology |
|---|---|
| Framework | Flutter 3.41.0+ |
| State Management | flutter_bloc |
| Dependency Injection | get_it, provider |
| Navigation | go_router |
| Connectivity Tracking | connectivity_plus |
| HTTP Client | dio + retrofit |
| Code Generation | freezed, json_serializable, build_runner |
| Logging | logger |
| Testing | mockito, bloc_test, flutter_test |
| UI Components | flutter_svg, cached_network_image |
This app follows Clean Architecture principles:
┌─────────────────────────────────────────┐
│ Presentation Layer │
│ (Pages, Widgets, BLoC/Cubit) │
└───────────────────┬─────────────────────┘
│
│ uses
┌───────────────────▼─────────────────────┐
│ Domain Layer │
│ (Entities, UseCases, Repositories*) │ * interfaces only
└───────────────────▲─────────────────────┘
│
│ implements
┌───────────────────┴─────────────────────┐
│ Data Layer │
│ (DTOs, DataSources, Repositories Impl) │
└─────────────────────────────────────────┘
lib/
├── core/
│ ├── constants/ # Shared app strings and asset references
│ ├── di/ # Dependency injection
│ ├── env/ # Envied-based environment config
│ ├── failures/ # Feature and network failure types
│ ├── network/ # Dio setup, interceptors, mappers, error DTOs
│ ├── result/ # Result pattern
│ ├── router/ # GoRouter config and route paths
│ ├── services/ # Cross-feature services (network, token storage)
│ └── utils/ # Logger and analytics utilities
├── features/
│ ├── app/ # App composition and root widget
│ ├── auth/
│ │ ├── data/ # DTOs, API client, repository implementation
│ │ ├── domain/ # Entities and repository contracts
│ │ └── presentation/ # Pages, widgets, cubits, validators
│ ├── fitness_start/ # Guest onboarding quiz, tests shell, and onboarding flow UI
│ ├── offline/ # Connectivity state and blocking offline flow
│ ├── splash/ # Branded startup splash screen
│ ├── tests/ # Shared tests catalog and guest test attempt flow
│ └── debug/ # Internal debug screen
├── uikit/
│ ├── buttons/ # Shared buttons
│ ├── dialogs/ # Shared dialogs
│ ├── images/ # Shared image widgets
│ └── themes/ # Color, gradient, and typography system
├── main.dart # Main entry point
└── runner.dart # Bootstrap entrypoint
- Flutter SDK:
>=3.41.0 - Dart SDK:
>=3.11.0
-
Create a local
.envfile in the project root.touch .env
-
Fill in
API_URLin.env. -
Install dependencies:
flutter pub get
-
Run code generation:
flutter pub run build_runner build --delete-conflicting-outputs
-
Run the app:
flutter run
Run tests:
# Unit tests
flutter test
# Widget tests
flutter test test/features/*/presentation/
# Coverage (requires lcov)
flutter test --coverage
genhtml coverage/lcov.info -o coverage/htmlEnd-to-end auth and Fitness Start validation still requires a local .env with a reachable API_URL.
Generate API docs from Dart doc-comments:
dart doc --output doc/apiServe docs locally:
dart pub global activate dhttpd
dart pub global run dhttpd --path doc/apiThen open:
http://localhost:8080
Build Android APK using Docker:
docker build \
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
--build-arg VCS_REF=$(git rev-parse --short HEAD) \
--progress=plain \
--no-cache \
-t moveUP-app-android:latest .Extract APK files:
docker create --name temp-flutter moveUP-app-android:latest
docker cp temp-flutter:/artifacts/. ./apk-output/
docker rm temp-flutterAll notable changes to this project are documented in CHANGELOG.md.