Thanks for taking a look. This is a template, so the bar for changes is a bit different from a normal app: anything added here is inherited by every project generated from it.
flutter pub get
dart format .
flutter analyze
dart run melos test
modular doctorAll five must pass. modular is the CLI from tool/cli, activated with
dart pub global activate --source path tool/cli (see
The CLI); CI installs it the same way. If you changed the
CLI itself, also run cd tool/cli && dart analyze && dart test.
The template teaches module boundaries and composition — the _api/_impl
split, the composition root, the launcher pattern. It deliberately does not
prescribe what happens inside a module: your data layer, your error types and
your networking conventions live in _impl/lib/src/ and are invisible across
every boundary this template cares about.
So:
- Yes — anything that makes the boundaries clearer or harder to violate.
- Yes — a new
doctorrule for an invariant we rely on but cannot compile-check. - Careful — new design-system components. The token system is the valuable part; the handful of components exist to show how tokens are consumed. A component library is a different project.
- Careful — new core capabilities. Each one is two packages every adopter carries forever.
- No — domain features.
counteris the only feature, on purpose.
features/counter/ and the CLI's templates in tool/cli/lib/src/templates/
describe the same thing twice. Change one and you must change the other, in the
same commit.
CI generates a feature with the in-repo CLI and analyzes it against the current core packages, which is what actually catches drift — but it only runs after you push, so run it yourself:
modular new feature scratch
flutter pub get && flutter analyze
git checkout pubspec.yaml app/lib/bootstrap/ && rm -rf features/scratchDo not hardcode import order in a template: whether {{name}}_api sorts before
or after router_api depends on the name, so the renderer sorts the package:
block after substitution.
- Primary-constructor syntax throughout, e.g.
final class NetworkModule({final bool enableLogging = false}) implements ... abstract interface classfor protocols in_apipackages.- Lint rules change only in the separate
app_linterrepo, never per package. - Design-system tokens, never raw values —
context.spacing.spacingXl, not16.0.