A Flutter template with real boundaries between its parts.
Every capability is two packages โ an _api contract and an
_impl implementation โ enforced by the analyzer, not by
discipline. This site walks through why, shows the moving parts, and
runs the modular CLI in front of you.
Try it
Clone it, rename it, run it.
modular rename rewrites the bundle id, the app name and
every reference to modular_app_template in one pass โ
there's no search-and-replace by hand.
modular rename at your bundle id and app name.dev flavor โ you get a counter screen and a live posts list, wired end to end.terminal
# clone and resolve the workspace git clone https://github.com/thisisyusub/modular_app_template my_app cd my_app && flutter pub get # install the CLI, then rename the template to your app dart pub global activate --source git https://github.com/Yusubov-Engineering/modular_cli.git --git-ref v1.0.0 modular rename --bundle-id com.acme.myapp --name "My App" # run it cd app && flutter run --flavor dev \ --dart-define-from-file=../config/dev.json
Why not just use folders
Folders don't stop anyone. Package boundaries do.
A lib/features/counter/ directory is a suggestion. A separate
counter_impl package with implementation_imports set to
error is a wall the analyzer enforces on every save.
| Folders | This template | |
|---|---|---|
| Import a feature's internals | nothing stops you | analyzer error |
| Feature A reaching into feature B | one import away | impossible; must go through _api |
| Forgot to register a module | crashes at runtime | modular doctor catches it before you ship |
| Navigating by hardcoded path | everywhere, eventually | route addresses are private to _impl |
| Adding a feature | copy, paste, rename, wire by hand | modular new feature <name> |
The cost is real โ two packages per capability, and a composition root you have to keep current. It tends to pay for itself above roughly ten features or two teams working the same codebase; probably not below that.
The shape
Four layers, dependencies flow one way.
app โ features โ base / core. Nothing
downstream ever imports upstream, and an _impl package is invisible
outside the one that owns it.
_implWhat's in the box
Nine core capabilities, two worked examples.
Every core capability ships as its own _api/_impl pair
so it can be swapped without touching a feature.
state_manager
From-scratch State/Event/Effect controllers. No riverpod, no bloc, no dependency at all.
router
go_router underneath, but no feature ever imports it โ routes are typed requests.
dependency_injection
get_it underneath, exposed through a container-agnostic locator.
network
dio-backed REST client that knows nothing about your backend's envelope.
design_system
Tokens, theming, six example components. Build yours on the tokens.
storage
Standard + secure key/value storage behind one contract.
app_localization
ARB translations in 7 languages, locale persisted and RTL-aware.
app_network_contract
This app's own success/error envelope โ the one file you edit for a new backend.
counter
The minimal shape modular new feature generates.
posts
The same shape plus a full data layer over JSONPlaceholder โ DTOs, repository, sealed failures.
logger
talker-backed, with an in-app log screen.
biometric_auth
Face ID / Touch ID behind a two-method contract.