fluframe

pub package

Generate production-ready Flutter apps from the fluFrame boilerplate — Riverpod 3, go_router, localization, theming, dio, and tests wired out of the box.

Try a generated app in your browser — the real thing, nothing installed.

Home Sample REST feature Theming & 3 locales
Home tab of a generated app Post list loaded over REST Settings tab in dark mode

Straight out of fluframe create — no edits.

Install

Requires Flutter 3.44 or newer (Dart 3.12+) — generated apps declare sdk: ^3.12.1.

dart pub global activate fluframe

If fluframe is then not found, the pub cache's bin is not on your PATH. Add $HOME/.pub-cache/bin (macOS/Linux) or %LOCALAPPDATA%\Pub\Cache\bin (Windows) and reopen the terminal.

Usage

Runnable top to bottom, in this order:

fluframe doctor                      # check your environment first
fluframe create my_app --org com.mycompany --description "My shiny app"
cd my_app
flutter run --dart-define-from-file=env/dev.json

fluframe add feature billing --tab   # later: scaffold your next feature
fluframe upgrade                     # later: pull template updates in (dry-run)

Adding a feature

create runs once; add feature runs every time the app grows one:

fluframe add feature billing          # a full-screen route at /billing
fluframe add feature billing --tab    # ...or a bottom-navigation tab
fluframe add feature billing --dry-run

It writes the repository, controller, screen and two tests, registers the route in lib/app/router/app_router.dart, and adds the strings to all three ARBs — telling you which ones still carry the English text. Then run flutter gen-l10n.

Unlike upgrade, it is not dry-run by default: it only creates new files and makes bounded insertions at anchors the template ships. Apps generated before those anchors existed need fluframe upgrade first; the command says so rather than guessing.

Why fluframe

Every starter is a snapshot: you generate, and from that moment your app and the template diverge forever. fluframe is the only Flutter starter we know of that keeps the connection — fluframe upgrade reconstructs the template as it was at your generation version, three-way merges everything that changed since into your working tree, and reports genuine conflicts as conflicts instead of guessing. Your edits survive.

That is the reason to pick it, and it is not a reason to pick it over everything. If your team writes Bloc, or you need a package rather than an app, Very Good CLI is the better tool. docs/comparison.md lays both out honestly, including where fluframe loses.

What you get

  • Riverpod 3 state management — manual Notifier/AsyncNotifier, no codegen for providers
  • go_router 17StatefulShellRoute bottom tabs, nested routes
  • freezed 3 + json_serializable models with a sample REST feature (dio)
  • Typed error handlingDioException mapped to a sealed ApiException
  • Localizationflutter gen-l10n with English, Japanese and Korean out of the box
  • Material 3 theming — light/dark with a persisted ThemeMode
  • Persisted settingsSharedPreferencesAsync behind a testable KeyValueStore
  • Flavors--dart-define-from-file with env/dev.json / env/prod.json
  • Strict lintsvery_good_analysis, zero warnings
  • Tests — unit + widget tests using mocktail and Riverpod overrides

Options

Option Default Description
--org com.example Bundle/application identifier organization
--description template default Description for the new pubspec.yaml
--output-directory, -o . Where to create the project folder. May not contain & | < > ^ " or % — on Windows, cmd.exe reads these as command syntax before Flutter ever sees the path, so the rule applies on every platform: one path must behave the same for a whole team (exit 64)
--platforms all six Passed through to flutter create
--backend none Wire a real auth backend (supabase | firebase) into the generated app
--error-reporting none Wire crash reporting (sentry) into the error hooks
--analytics none Wire product analytics (amplitude) into the analytics seam
--no-pub off Skip flutter pub get / gen-l10n

Exit codes

Every failure is a sentence on stderr and a sysexits code — so a script can branch on what went wrong:

Code Name Meaning
0 EX_OK Success. Dry runs that found work to do exit 0 too
64 EX_USAGE Bad arguments, or a refusal before anything was written (an invalid name, an app upgrade will not touch)
65 EX_DATAERR .fluframe.json is malformed, holds a value of the wrong type, or names a package upgrade will not build a merge base for — including a name it fell back to from pubspec.yaml or the directory
69 EX_UNAVAILABLE Something fluframe depends on is not usable: no Flutter on PATH, no git on PATH for upgrade --apply, a fatal doctor finding, or an older template bundle upgrade could not download or verify
70 EX_SOFTWARE A step did not complete: a failed flutter invocation, an upgrade that ended with conflict markers still to resolve, an installed template bundle that is missing or incomplete (reinstall with dart pub global activate fluframe), or an error fluframe did not expect. The "This is a bug" trace is always this code
74 EX_IOERR add feature failed while writing — a full disk, a read-only checkout, a locked file. The message says whether every file was put back, and names what to restore if not

How it works

fluframe create runs flutter create --empty first — so platform folders always match your installed Flutter version — then overlays the fluFrame application template — lib/, test/, env/, l10n.yaml, analysis_options.yaml, pubspec.yaml, plus a replacement README.md and .gitignore and a ready-made .github/workflows/ci.yml — and rewrites package-name tokens.

License

MIT

Libraries

fluframe
fluFrame CLI — generates production-ready Flutter apps from the fluFrame boilerplate.