Transito is a Flutter bus timing application for Singapore. Use this file as the repository map and source of project-specific constraints; inspect nearby code and configuration for ordinary Dart and Flutter conventions.
- Never run Shorebird commands (
shorebird release,shorebird patch). The user always runs them. - Do not start the background development stack directly or run the
devscript. The user starts those servers and processes with the fish aliastransito-dev. - You may run
flutter runfor app development and hot reload after confirming that no other Flutter build is already running on the same target device. - Before asking the user to run
transito-dev, check that both port 8080 (Transito server) and port 4000 (Firebase emulator UI) are listening:lsof -nP -iTCP:8080 -sTCP:LISTENandlsof -nP -iTCP:4000 -sTCP:LISTEN. - After editing any non-generated Dart file, run
dart format <file>. - Do not manually edit or format checked-in
.g.dartfiles. Regenerate them withflutter pub run build_runner build.
flutter --version # Flutter 3.41.0 managed by FVM
flutter pub run build_runner build # Regenerate JSON serialization code
flutter analyze # Static analysis
flutter test # Logic-heavy test suite
flutter test test/specific_test.dart # Relevant logic-heavy test
flutter build apk # Android build when requested/needed
flutter build ios # iOS build when requested/needed- The formatter contract is defined in
analysis_options.yaml(page_width: 100,trailing_commas: preserve)..vscode/settings.jsonmirrors it for VS Code. - Run formatting and static analysis after normal Dart changes. Run code generation when annotated models change.
- Do not add unit or widget tests by default for routine UI, model, persistence, or serialization changes. Add or update tests for substantial data processing, complex algorithms, or a regression best protected by a focused test.
- For normal UI work, prefer widget previews, hot reload, formatting, and static analysis.
lib/global/providers/: sharedChangeNotifierstate.lib/global/services/: API clients and shared business services.lib/global/utils/: shared utilities.lib/models/: API, app, favourites, user, and enum models.lib/screens/: application screens grouped by feature.lib/widgets/: reusable widgets grouped by feature; shared widgets live inwidgets/common/.docs/adr/: architecture decision records.tool/: local development utilities.
State management uses Provider with ChangeNotifier. API services extend BaseApiService and use
the repository's singleton pattern. JSON API models use json_serializable with
@JsonSerializable(explicitToJson: true) where nested objects must be serialized explicitly.
Use a screen ChangeNotifier controller when a parent needs imperative control of the screen. Do
not introduce a controller or abstraction that merely delegates to an already available dependency;
an abstraction should add behavior, enforce a boundary, or meaningfully improve reuse.
- Use
AppSymbolinstead of a directIconfor Material Symbols. - Preserve both Material and iOS-style Liquid Glass navigation behavior.
- Use DM Sans as the primary font and Itim as the secondary font.
- Use
CommonProvider.scaffoldMessengerKeywhen a service needs to show a snackbar without aBuildContext. - Catch async errors where the code adds recovery, translation, logging, or user feedback. Otherwise allow errors to propagate.
- Use
debugPrint()for debug logging and guard debug-only behavior withkDebugMode. - Existing API/wire enum values in
lib/models/enums/use uppercase names. Internal Dart-only enums may follow the local surrounding convention. - Use
Theme.of(context).colorSchemerather than introducing hard-coded theme colors.
- API exceptions are defined in
lib/global/services/api_exceptions.dart(ApiException,NetworkException, andApiParsingException). - When an LTA API call fails in a flow that needs maintenance feedback, preserve the established
showLtaMaintenanceWarningSnackbar()behavior. - Use
ErrorTextfor consistent error presentation inFutureBuilderand equivalent async states.
- API singleton and LTA failure handling:
lib/global/services/lta_api_service.dart - Backend API service:
lib/global/services/transito_api_service.dart - Screen controller:
lib/screens/main/nearby_screen.dart - Global snackbar access:
lib/widgets/common/lta_maintenance_warning_snackbar.dart - Shared async error UI:
lib/widgets/common/error_text.dart - Shared app state and device layout information:
lib/global/providers/common_provider.dart
- Firebase emulators use ports 9099 (Auth), 8088 (Firestore), and 4000 (Emulator UI).
- The Node.js/Koa backend uses localhost port 8080.
- Assets live in
assets/. - The application supports phone and tablet layouts; shared device state is exposed by
CommonProvider.