{"id":50695771,"url":"https://github.com/hngprojects/personal-trainer-mobile","last_synced_at":"2026-06-09T06:08:42.112Z","repository":{"id":355586313,"uuid":"1227991538","full_name":"hngprojects/personal-trainer-mobile","owner":"hngprojects","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-04T09:59:31.000Z","size":633,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"dev","last_synced_at":"2026-05-04T11:38:10.946Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hngprojects.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-03T12:55:10.000Z","updated_at":"2026-05-04T09:22:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/hngprojects/personal-trainer-mobile","commit_stats":null,"previous_names":["hngprojects/personal-trainer-mobile"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/hngprojects/personal-trainer-mobile","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hngprojects%2Fpersonal-trainer-mobile","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hngprojects%2Fpersonal-trainer-mobile/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hngprojects%2Fpersonal-trainer-mobile/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hngprojects%2Fpersonal-trainer-mobile/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hngprojects","download_url":"https://codeload.github.com/hngprojects/personal-trainer-mobile/tar.gz/refs/heads/dev","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hngprojects%2Fpersonal-trainer-mobile/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34093841,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-09T06:08:41.268Z","updated_at":"2026-06-09T06:08:42.099Z","avatar_url":"https://github.com/hngprojects.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# personal_trainer_mobile\n\nA Flutter starter template for building apps with clean arch.\n\n## Stack\n\n- Flutter 3.x\n- Material 3\n- Riverpod\n- GetIt\n- Dio\n- GoRouter\n- flutter_dotenv\n- Mocktail\n- Flutter lints\n\n## Project Layout\n\n```txt\n.\n├── .env\n├── .env.example\n├── lib/\n│   ├── main.dart\n│   ├── app/\n│   │   ├── app.dart\n│   │   └── theme/\n│   │       ├── app_palette.dart\n│   │       └── app_theme.dart\n│   ├── core/\n│   │   ├── core.dart\n│   │   ├── api_utils/\n│   │   │   ├── api_utils.dart\n│   │   │   ├── api_client.dart\n│   │   │   ├── api_failure.dart\n│   │   │   └── api_response_model.dart\n│   │   ├── config/\n│   │   │   ├── config.dart\n│   │   │   ├── app_config.dart\n│   │   │   └── env_loader.dart\n│   │   ├── locator/\n│   │   │   ├── locator.dart\n│   │   │   └── locator_service.dart\n│   │   └── navigator/\n│   │       ├── navigator.dart\n│   │       └── app_router.dart\n│   ├── features/\n│   │   ├── features.dart\n│   │   └── example_tasks/\n│   │       ├── example_tasks.dart\n│   │       ├── data/\n│   │       │   ├── data.dart\n│   │       │   └── tasks_datasource.dart\n│   │       ├── domain/\n│   │       │   ├── domain.dart\n│   │       │   ├── models/\n│   │       │   │   ├── models.dart\n│   │       │   │   └── task_model.dart\n│   │       │   └── repo/\n│   │       │       ├── repo.dart\n│   │       │       └── tasks_repo.dart\n│   │       └── presentation/\n│   │           ├── presentation.dart\n│   │           ├── components/\n│   │           │   ├── components.dart\n│   │           │   └── tasks_header.dart\n│   │           ├── providers/\n│   │           │   ├── providers.dart\n│   │           │   └── tasks_provider.dart\n│   │           ├── views/\n│   │           │   ├── views.dart\n│   │           │   └── tasks_view.dart\n│   │           └── widgets/\n│   │               ├── widgets.dart\n│   │               └── task_tile.dart\n├── test/\n│   ├── app_test.dart\n│   ├── helpers/\n│   │   └── test_material_app.dart\n│   ├── unit/\n│   │   └── features/\n│   └── widget/\n│       └── features/\n├── analysis_options.yaml\n├── pubspec.yaml\n└── README.md\n```\n\n## Architecture\n\nEach feature owns its UI, business rules, repository contract, and data implementation.\n\n```txt\npresentation -\u003e domain \u003c- data\n```\n\n- `app`: app setup and theme.\n- `core`: shared infrastructure.\n- `features`: vertical feature modules.\n- `domain`: models and repo contracts.\n- `data`: datasources and API access.\n- `presentation`: views, components, widgets, providers, and UI state.\n\nThe `example_tasks` feature shows the full flow:\n\n```txt\nTasksView\n  -\u003e tasksProvider\n  -\u003e TasksRepo\n  -\u003e TasksDatasource\n  -\u003e ApiBaseService\n```\n\n## Core Rules\n\nKeep `core` small. Add shared code only when more than one feature needs it.\n\nGood `core` candidates:\n\n- App config\n- Dependency injection\n- API base service\n- API failure handling\n- Navigation\n- Storage, connectivity, logging, providers, enums, or app services when used\n\n## Adding A Feature\n\n1. Create `features/\u003cfeature_name\u003e`.\n2. Put datasources and API access in `data`.\n3. Put models and repo contracts in `domain`.\n4. Put screens, components, widgets, providers, and UI state in `presentation`.\n5. Keep feature models in `domain/models`.\n6. Register long-lived implementations in `core/locator/locator_service.dart`.\n\nAvoid global `utils`, `constants`, or `services` folders for one-off code. Keep code inside the feature until it is truly shared.\n\n## Barrel Exports\n\nEvery folder that exposes reusable Dart files should have a barrel file.\n\nUse **exactly these two root-barrel imports** everywhere you need shared core plus feature exports (same order and URIs as `lib/features/example_tasks/data/tasks_datasource.dart`):\n\n```dart\nimport 'package:personal_trainer_mobile/core/core.dart';\nimport 'package:personal_trainer_mobile/features/features.dart';\n```\n\nIf you rename the app in `pubspec.yaml`, update the `package:` name in both lines to match. Narrower barrels are only for real import cycles or boundary clarity—this pair stays the default.\n\nExport chain:\n\n```txt\nleaf files -\u003e layer barrel -\u003e feature barrel -\u003e features.dart\nshared core files -\u003e core.dart\n```\n\nRules:\n\n- Add new exports whenever you add a reusable file.\n- Prefer `core/core.dart` for shared app infrastructure.\n- Prefer `features/features.dart` when code needs feature-level exports.\n- Inside a feature, use the narrowest useful barrel when `features.dart` (or the feature barrel) would create an import cycle or blur boundaries—often a **layer** barrel (`data/data.dart`, `domain/domain.dart`, `presentation/presentation.dart`) or a **subfolder** barrel (`domain/repo/repo.dart`, `presentation/views/views.dart`, etc.).\n- Avoid importing leaf `.dart` files directly unless every barrel option causes a real problem.\n\n**Narrower than `features.dart`:** import that feature’s barrel file first, e.g. `lib/features/example_tasks/example_tasks.dart` (same pattern for any feature: `lib/features/\u003cname\u003e/\u003cname\u003e.dart`). That file already re-exports `data`, `domain`, and `presentation`. Reach for layer or subfolder barrels only when you need a smaller slice to break a cycle or keep dependencies obvious.\n\n## Configuration\n\nEnv files live at the **project root** (`.env`, `.env.example`) and are listed under `flutter.assets` so [`flutter_dotenv`](https://pub.dev/packages/flutter_dotenv) can load them before dependency injection runs.\n\nThe repo ships a **safe default** `.env` so `flutter analyze` and first runs work without extra setup. Treat `.env.example` as a template you can copy if you ever delete `.env`.\n\n1. Edit `.env` for your machine.\n2. Do not commit real secrets; prefer CI variables or `--dart-define` for production values.\n\n```txt\nAPI_BASE_URL=https://api.example.com\nUSE_MOCK_DATA=false\n```\n\n`USE_MOCK_DATA` accepts `true` / `false` (also `1` / `0`, `yes` / `no`).\n\n### Overrides for CI or release builds\n\n`--dart-define` still works and **wins over `.env`** when you need non-file config:\n\n```sh\nflutter run --dart-define=API_BASE_URL=https://api.example.com --dart-define=USE_MOCK_DATA=false\n```\n\nDefaults when neither `.env` nor defines set a value:\n\n```txt\nAPI_BASE_URL=https://example.com/api\nUSE_MOCK_DATA=true\n```\n\n## Clone\n\nThe GitHub repo root **is** this Flutter project: `pubspec.yaml` and `lib/` sit at the top level. After cloning, `cd` into the repo folder only—there is no extra nested `personal_trainer_mobile/` directory inside the clone.\n\n```sh\ngit clone https://github.com/hngprojects/flutter-starter.git\ncd flutter-starter\n```\n\n## Quick Start\n\n```sh\nflutter pub get\nflutter run\n```\n\nOptional: reset env from the template.\n\n```sh\ncp .env.example .env\n```\n\nWindows (PowerShell):\n\n```powershell\nCopy-Item .env.example .env\n```\n\n## Common Commands\n\n```sh\ndart format lib test\ndart analyze\nflutter test\n```\n\n## Testing\n\nTests should mirror the app structure:\n\n- `test/helpers`: reusable test setup\n- `test/unit`: datasources, repo contracts, and services\n- `test/widget`: views and reusable widgets\n\nMock dependencies at the layer boundary being tested.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhngprojects%2Fpersonal-trainer-mobile","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhngprojects%2Fpersonal-trainer-mobile","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhngprojects%2Fpersonal-trainer-mobile/lists"}