Reusable Flutter starter template for Cuboid applications, built on Cuboid's own MVVM, dependency injection, and routing.
This repository is infrastructure for starting a new app. It is not a production domain application and does not contain application-specific business workflows, database schema, or repository/data layers.
- Flutter and Dart
- Cuboid's own in-house MVVM, routing, service locator (get_it-based),
dialogs, and bottom sheets -- no third-party MVVM framework. The MVVM
runtime (
CuboidView/CuboidViewModel) lives inpackages/cuboid_flutter, a framework package depended on viapath:, not insidelib/ - Technology-neutral base: no backend or storage technology is pre-installed;
add one explicitly via the Cuboid CLI (e.g.
cuboid create database supabase,cuboid create storage) when a project actually needs one - Focused unit and widget tests
- Bootstrap tooling for renaming a generated app from the template
lib/
|-- app/ Locator, router, app root (CLI-patched, hand-editable)
|-- core/ Constants, errors, formatters, forms, models,
| services, storage, theme, and validators
|-- features/
| |-- startup/ Startup view and view model
| `-- home/ Home feature
`-- shared/
`-- widgets/ Reusable UI widgets
packages/cuboid_flutter/ CuboidView/CuboidViewModel runtime (path dependency)
test/ Unit, widget, and bootstrap tests
tool/ Template bootstrap tooling
doc/design/ Generic design guidance
lib/core/config/ and lib/core/network/ are not part of the base
template -- they're added once a generated app needs backend configuration or
network guards. See ARCHITECTURE.md §10.
lib/app/app.locator.dart and lib/app/app.router.dart are plain,
hand-maintained Dart -- not code-generated output. Edit them directly, or let
cuboid create <artifact> patch them idempotently.
Use the bootstrap tool before product-specific development:
dart run tool/bootstrap.dart --helpThe bootstrap updates the template identity for a new application. Review the resulting diff before adding product code.
packages/cuboid is a Dart CLI (cuboid) that stamps out new projects from
this template and scaffolds artifacts inside a generated project. It is
published on pub.dev; most users should install it with:
dart pub global activate cuboidIf you are developing cuboid itself from a checkout of this repository,
install your local build instead:
dart run packages/cuboid/tool/install.dartThis compiles cuboid to a native executable and places it on the same
~/.pub-cache/bin PATH entry dart pub global activate would have used.
Do not install a checkout with dart pub global activate --source path packages/cuboid: the shell shim it generates embeds the checkout's absolute
path into an unquoted [ -f ... ] test, so it fails with [: too many arguments for every cuboid command whenever the checkout path contains a
space -- a defect in dart pub global activate's shim template, not
something a package can work around from its own source. Re-run the install
command above after pulling changes to packages/cuboid.
Create a new project (an alternative to tool/bootstrap.dart for starting a
brand-new project directory, rather than renaming this checkout in place):
cuboid create app "My App" com.example.myappPackage identifiers (com.example.myapp) may use letters and numbers, each
dot-separated segment must start with a letter.
Inside a generated project, scaffold artifacts with cuboid create <artifact>:
cuboid create feature <name> # also creates its repository and route
cuboid create service <name>
cuboid create bottomsheet <name> # patches app.bottomsheets.dart itself
cuboid create dialog <name> # patches app.dialogs.dart itself
cuboid create storage
cuboid create database supabase
cuboid create view <name> <feature> # also registers the view's route
cuboid create model <name>
cuboid create widget <name> # shared, under lib/shared/widgets/<name>/
cuboid create widget <name> <feature> # feature-scoped
There is no separate route or repository command: creating a feature
generates and registers its repository, and creating a feature or view
registers its route, automatically.
Every command supports --dry-run to preview the plan without writing
anything. No command needs a code-generation step afterward: lib/app/ app.locator.dart, app.router.dart, app.bottomsheets.dart, and
app.dialogs.dart are plain Dart files each command patches directly. Full
per-command contracts (generated files, registration behavior, safety
guarantees) live in
ARCHITECTURE.md §9.
Reverse most of the above with cuboid delete <artifact>:
cuboid delete service <name>
cuboid delete feature <name> # also removes its route(s) and repository
cuboid delete bottomsheet <name> # removes app.bottomsheets.dart too if it was the last bottom sheet
cuboid delete dialog <name> # removes app.dialogs.dart too if it was the last dialog
cuboid delete storage
cuboid delete database supabase
cuboid delete view <name> <feature> # also removes the view's route
cuboid delete widget <name> # shared
cuboid delete widget <name> <feature> # feature-scoped
cuboid delete route <name> # router entry only; does not touch View files
cuboid delete never removes lib/app/app.locator.dart or lib/app/ app.router.dart themselves -- only the entries a matching create command
added. Deleting the last dialog or bottom sheet also tears down its owning
service (DialogService / BottomSheetService); deleting any earlier one
leaves that shared infrastructure in place. There is no cuboid delete model
or cuboid delete app. Deleting something that was never created is an
error, not a silent no-op -- matching how every create command treats
unexpected state.
Install dependencies:
flutter pub getRun the app:
flutter runThe base template has no backend or storage technology installed. Add one explicitly when a project actually needs it:
cuboid create database supabase # Supabase example model, repository, migration
cuboid create storage # A local key-value/secure storage wrappercuboid create database supabase provisions its own Supabase foundation: it
adds the supabase_flutter dependency to pubspec.yaml and creates
lib/core/network/supabase_guard.dart when either is missing, so it does not
require a developer to add them first. See
ARCHITECTURE.md §12-13
for the full contract.
Once a project has persistent feature data:
- repositories own backend access and row/model mapping;
- ViewModels consume repositories instead of calling a backend SDK directly;
- PostgreSQL schemas, RLS policies, privileged functions, and server authority are application-specific and must be documented with that app's product rules;
- service-role keys and secrets must never be embedded in the Flutter app.
For documentation-only changes, review paths, links, and diffs. For code changes, run the relevant checks:
dart format <changed Dart files>
flutter analyze
flutter test
git diff --check- Run the bootstrap tool to rename package and app identity.
- Keep the template infrastructure generic until the product boundary is clear.
- Add feature folders under
lib/features/<feature>/. - Add repositories only when a feature introduces persistent data.
- Define application-specific backend schema, RLS, and server-side rules in the generated application, not in the starter template.
Architecture and engineering rules: