WebTrit Phone — Flutter VoIP app, Melos monorepo. Flutter 3.44.0 (stable), Android SDK 35.0.1.
- Flutter version is pinned only in
.fvmrc— single source of truth, read byfvmlocally and by thewebtrit_phone_builderCI. When you bump it, update the version mentioned above in the same commit. (Older release branches may still carry the legacy.github/flutter_version.yaml; the builder falls back to it there.) - Use
fvm flutter .../fvm dart ...so the pinned SDK is used; a bareflutterfromPATHmay be a different version. The.fvm/SDK cache is gitignored — runfvm installonce per machine.
melos bootstrap # install all deps
melos run analyze # lint all packages
melos run test # test all packages
flutter test # unit/widget (app root)
dart run build_runner build --delete-conflicting-outputs # codegen
dart run bin/create_new_schema_dump_and_test_migration.dart # after Drift table changes- No Cyrillic in source, comments, logs, strings, or keys, except translation values in localization ARB files (
lib/l10n/arb/*.arb). - Comments: no redundant what comments that restate the code; comments explain non-obvious why (rationale, gotchas, workarounds, links to issues). DartDoc for public APIs.
- No DI frameworks (
get_it,injectable, Service Locator — forbidden). - Single quotes; 120-char line width.
- Never edit
*.g.dart/*.freezed.dart/*.gr.dart— regenerate viabuild_runner. - Required named params before optional named params.
- Callbacks: single-expression only; extract multi-statement logic to a private method.
- Imports: 6 groups, one blank line between, alphabetical within:
- Dart SDK
- Flutter SDK
- External
- Internal packages
package:webtrit_phone/...- Relative
lib/ → app (features/, theme/, repositories/, models/, blocs/, l10n/)
packages/ → shared libs (must NOT import from lib/)
webtrit_appearance_theme/ pure Dart theme DTOs
data/app_database/ Drift DB + DAOs
webtrit_api/ REST client
webtrit_signaling/ WebSocket signaling
webtrit_callkeep/ native call UI (external repo)
- State:
@freezedfor state;sealed class + Equatablefor events (neverfreezedon events). - BLoC deps via
Provider/RepositoryProvider; never passBuildContextinto BLoC/Service. - DB: DAOs only — never
AppDatabasedirectly; Drift-generated classes stay in repo layer. - Theme: never raw
Colors.xxxorTextStylein widgets;Theme.of(context).extension<T>(). - Widgets:
StatelessWidgetalways (not helper methods); dumb widgets infeatures/*/view/widgets/. - Tests:
MockClient/mocktail— no real network calls; DB migrations viaSchemaVerifier. - Routing (
auto_route): theAppRouter.routestree must ALWAYS be complete — never gate route declarations on async/runtime values (server capability, login state, feature flags).routeCollectionislate final, built once at router construction (before serversystem-infoloads), so anyif (capability) AutoRoute(...)is frozen with whatever the value was at startup; later navigation to a route omitted then throwsFailed to navigate to <Route>. Register every variant unconditionally and decide which one to show at navigation/build time (e.g.AutoTabsRouter.routes, guards, initial-tab resolver). Sibling routes may share apath(recents) —RouteCollectiononly requires unique route names, and tab matching is name-based.