Skip to content

Directory map

File counts are tracked files (git ls-files) at d1b602a. Generated and ignored folders are listed separately at the end.

Path Files What it is
lib/ 110 The app. Everything that ships as Dart. Detail below.
test/ 91 Unit and widget tests, mirroring lib/, plus the shared harness, fixtures and the screenshot renderer. Detail below.
integration_test/ 1 full_race_test.dart: register, race the steady bot over 100 m with simulated GPS, check History and Profile. Runs on an emulator against a real backend via scripts/integration.sh.
widgetbook/ 38 A second Flutter app: the component catalog (Storybook for Flutter). Path dependency on this package; never shipped. Detail below.
android/ 48 The native Android shell that hosts the Flutter engine. Detail below.
ios/ 49 The native iOS shell. Detail below.
assets/ 9 brand/ (4: icon, adaptive icon, splash icon, logo.svg) and fonts/ (5: Plus Jakarta Sans regular and italic, Space Grotesk, two OFL licence files). Declared in app/pubspec.yaml:55-63.
docs/ 55 Project docs inside the repo. Detail below.
env/ 3 dev.json, staging.json, prod.json: the --dart-define values (API_BASE_URL, DEV_TOOLS, FAKE_GPS) for --dart-define-from-file.
scripts/ 1 integration.sh: boots the backend, resets and seeds the dev database, runs the integration test.
tool/ 1 check_coverage.dart: reads coverage/lcov.info, fails below the minimum. make coverage passes 70 (app/Makefile:23); the script’s own default is 60. Excludes lib/dev/.
.github/ 1 workflows/ci.yml: jobs check (format, analyze, test, coverage), build-android (debug APK), storybook (Widgetbook analyze + web build), and integration, which runs only on manual workflow_dispatch.

Root files:

File What it is
pubspec.yaml Package manifest: dependencies, fonts, icon and splash config. The package.json / mix.exs of the app.
pubspec.lock Resolved versions; committed because this is an app.
analysis_options.yaml Lint config: flutter_lints plus a few rules; excludes the platform folders.
Makefile check, format, analyze, test, coverage, integration, run-dev, release-android, release-ios, apk, icons, and the storybook* targets. See build and release.
.tool-versions flutter 3.47.2-stable for asdf.
.metadata Written by flutter create; tracks which platforms were generated. Do not edit.
CLAUDE.md, README.md Agent instructions and the human README (environments, release builds, the manual on-device GPS check).
.gitignore Note it ignores /linux/, /macos/, /web/, /windows/: only Android and iOS are built.
lib/
├── main.dart 1
├── app/ 4
├── core/ 5 (4 + config/1)
├── data/ 33 (api 2, models 13, repositories 10, socket 5, storage 3)
├── design/ 21 (2 + components 15 + components/race 4)
├── dev/ 4
├── features/ 31 (14 feature folders)
└── tracking/ 11 (8 + upload/3)

The architecture overview shows how these depend on each other.

Bootstrap only: Flutter binding, error handlers, the foreground-task communication port, then runApp(ProviderScope(child: FootraceApp())) (app/lib/main.dart:9-21).

File What
app.dart FootraceApp, the root ConsumerWidget: MaterialApp.router with the theme and router, and keeps the socket lifecycle alive (app/lib/app/app.dart:9-21).
router.dart routerProvider: every GoRoute, the four-tab StatefulShellRoute, and the auth redirect (app/lib/app/router.dart:27-147).
routes.dart AppRoutes, path constants and builders like AppRoutes.race(id) (app/lib/app/routes.dart:2-21).
theme.dart footraceTheme(): Material ThemeData built from the design tokens, with FrTheme attached (app/lib/app/theme.dart:12).

Page: app shell.

File What
config/app_config.dart AppConfig from --dart-define, the derived socket URL, appConfigProvider. The only reader of the defines.
clock.dart typedef Clock and clockProvider, so tests control “now”.
logging.dart The log logger, installErrorHandlers(), LoggingProviderObserver.
units.dart Units enum, unitsProvider, UnitsFormatter (every distance, pace and duration string).
relative_time.dart “5 min ago”-style formatting for the Activity feed.
Folder Files What
api/ 2 api_client.dart: buildDio (bearer header, 401 handling, error normalisation), guard, dioProvider. api_exception.dart: ApiException.
models/ 13 Hand-written immutable models with fromJson/toJson: user, auth_response, race_type, matched_race, race_snapshot, race_result, race_history_item, activity_item, leaderboard, lobby_entry, public_profile, user_settings, user_stats.
repositories/ 10 One per backend area: auth, user, profile, race_type, matchmaking, lobby, race, race_history, activity, leaderboard. Each is an abstract class, an Api... implementation and a provider. The only code that knows URLs.
socket/ 5 channel_transport.dart (the narrow SocketTransport/ChannelTransport interfaces), phoenix_transport.dart (implementation over phoenix_socket), race_channel.dart, waiting_channel.dart (typed channel clients), socket_service.dart (providers).
storage/ 3 token_store.dart (JWT in Keychain/Keystore), user_cache.dart (last user in SharedPreferences), active_race_store.dart (the race to resume after a kill). Each has an in-memory twin for tests.

Pages: data layer, realtime.

Path Files What
tokens.dart 1 FrColors, FrSpacing, FrRadii, FrShadows, FrFonts: every visual constant, named by role.
typography.dart 1 The TextTheme, the FrTheme theme extension, and context.fr (app/lib/design/typography.dart:309-313).
components/ 15 Fr* widgets: avatar, button, card, eyebrow, icon button, icon tile, list row, metric tile, navigation bar, section header, segmented control, stat, stat group, tag, plus the components.dart barrel export.
components/race/ 4 Race-screen pieces: head-to-head, live pill, slide-to-confirm, and the race.dart barrel.

design/ imports nothing else from lib/. Page: design system.

Debug-only tooling, reachable at /dev only when DEV_TOOLS is true (app/lib/app/router.dart:117-121), and excluded from the coverage gate.

File What
gps_diagnostics_screen.dart The GPS proof-of-concept screen: start/stop the service, see fixes from both isolates.
tracking_diagnostics.dart trackingDiagnosticsProvider: gap and fix statistics fed by the service’s batches.
sim_gps_controller.dart simGpsProvider: state of the simulated runner.
sim_gps_overlay.dart Draggable control panel for the simulated GPS, shown on the race screen when FAKE_GPS is on.

One folder per screen or flow, holding widgets and the notifier that owns their state. The features page has the full table of screens, notifiers and routes.

Folder Files Contents
auth/ 5 auth_notifier.dart (session owner, authProvider, authStatusProvider), auth_state.dart, auth_form.dart, login_screen.dart, register_screen.dart
home/ 1 home_shell.dart: the bottom-tab scaffold
race_tab/ 3 The Race tab (pick a distance): race_tab.dart, race_type_card.dart, race_types_notifier.dart
activity/ 2 Activity feed tab and its notifier
history/ 2 History tab and its notifier
profile/ 4 profile_tab.dart, profile_widgets.dart, settings_notifier.dart, opponent_profile_screen.dart (with its two providers)
leaderboard/ 2 Screen and notifier, plus the filter StateProvider
lobby/ 2 Open challenges: screen and notifier
queue/ 2 Matchmaking: queue_notifier.dart (sealed QueueState), queue_screen.dart
race/ 4 race_notifier.dart, race_screen.dart, result_screen.dart (with raceResultProvider), local_distance.dart
permissions/ 1 PermissionsSheet (the explainer shown before the first queue join) and PermissionBanner
shared/ 3 splash_screen.dart, message_state.dart (empty/error placeholder), coming_soon_screen.dart (also the 404 page)
File What
location_service.dart LocationService (UI side: permissions, start/stop the service) and LocationTaskHandler (runs inside the service isolate). The load-bearing file.
location_source.dart LocationSource interface and RealLocationSource over geolocator.
simulated_location_source.dart The fake runner used with FAKE_GPS.
gps_fix.dart GpsFix and TrackingState.
geo.dart Great-circle distance helpers.
location_provider.dart locationProvider for the diagnostics screen.
race_tracker.dart RaceTracker: what a race needs from the tracker; raceTrackerProvider.
permission_gate.dart PermissionGate notifier: what is still missing, asked one step at a time.
upload/fix_queue.dart Durable per-race queue of fixes on sembast.
upload/position_uploader.dart Drains the queue to POST /api/races/:id/positions in batches of 50 with backoff.
upload/race_upload_target.dart The keys the UI isolate saves for the service: race id, base URL, token, queue path.

Page: tracking.

test/ mirrors lib/. 91 tracked files:

Path Files What
app_test.dart 1 Boots the whole app on fakes.
core/ 2 app_config_test.dart, units_test.dart
data/ 13 One test per repository, lobby_entry_test.dart, fixture_contract_test.dart, and socket/ (3)
design/ 19 theme_test.dart and 18 component tests
features/ 20 Notifier and widget tests per feature
tracking/ 5 geo, gps_fix, simulated source, and upload/ (2: fix queue, uploader)
support/ 5 The harness: fakes.dart (testApp, testOverrides, every fake), fake_api_client.dart, fake_socket.dart, fixtures.dart, json_contract.dart
fixtures/ 23 22 real backend payloads as JSON plus a README.md on the backend’s inconsistencies
screenshots/ 3 Not a test suite: a renderer that writes 1080x2400 PNGs of every screen when FR_SCREENSHOTS is set

Page: testing.

Path Files What
lib/ 7 main.dart, foundations.dart (tokens), components.dart and the design_*.dart files (use cases with knobs)
android/ 19 Its own Android shell, for make storybook-phone
web/ 7 Web shell, for make storybook (served on port 8790)
root 5 Its own pubspec.yaml, pubspec.lock, analysis_options.yaml, .metadata, .gitignore

Both are standard flutter create shells. Almost everything in them is boilerplate; the parts that are Footrace-specific are permissions, the foreground service and the app id.

Path Files What matters
android/app/src/main/AndroidManifest.xml 1 Location, background location, foreground-service, notification and wake-lock permissions; the flutter_foreground_task service with foregroundServiceType="location" (app/android/app/src/main/AndroidManifest.xml:2-9, :36-40)
android/app/src/main/kotlin/.../MainActivity.kt 1 class MainActivity : FlutterActivity(), nothing else
android/app/src/main/res/ 35 Launcher icons, splash drawables, launch themes
android/app/src/debug/, src/profile/ 2 Debug and profile manifests (internet permission for the tool)
android/app/build.gradle.kts, proguard-rules.pro 2 App id, SDK levels, signing, release shrinking
android/ root 7 Gradle settings and wrapper properties, key.properties.example
ios/Runner/AppDelegate.swift, SceneDelegate.swift 2 FlutterAppDelegate and plugin registration
ios/Runner/Info.plist 1 Location usage strings, UIBackgroundModes location and fetch (app/ios/Runner/Info.plist:69-77)
ios/Runner/Base.lproj/ 2 Main.storyboard (a FlutterViewController), LaunchScreen.storyboard
ios/Runner/Assets.xcassets/ 29 App icon set and launch image
ios/Runner.xcodeproj, Runner.xcworkspace, Flutter/, RunnerTests/ 12 Xcode project, workspace, the Flutter xcconfigs, the template XCTest target
ios/ root 2 .gitignore, ExportOptions.plist.example (copy for make release-ios)

At d1b602a there is no tracked ios/Podfile; the local checkout has an untracked one and uncommitted changes to the Xcode project, which suggests CocoaPods was run locally after the commit. Page: build and release.

Path Files What
design/stitch/ 22 The Stitch mockups the UI is built from: README.md (settles tokens where exports disagree), screens/ (home, lobby, racing as HTML + PNG), components/ (15 PNG crops)
use-cases/ 13 One markdown file per manual flow (register, queue, lobby, bot race win/lose, abort, kill app, locked phone, lose network, permissions denied, history, units) plus a README
qa/ 2 device-checklist.md (real-device pass) and report-template.md
screenshots/ 18 Rendered screens committed per story (elb-1285/, elb-1683/, elb-1684/) and a README on how they are made

Present in a working checkout, never edited by hand:

Path What
build/ Build output for every target
.dart_tool/ Package resolution and tool caches (like _build/ or node_modules/.cache)
.flutter-plugins-dependencies Which plugins each platform needs; written by flutter pub get
linux/, macos/, web/, windows/ Exist locally from flutter create but are git-ignored and not built
coverage/ lcov.info from make coverage
.idea/, *.iml IDE files (footrace_flutter.iml and android/footrace_flutter_android.iml are tracked anyway)
ios/Pods/, android/.gradle/, GeneratedPluginRegistrant.java Native dependency and plugin-registration output