Flutter Zero: A go-zero-Inspired CLI That Generates Full MVI-BLoC Modules
Flutter projects accumulate repetitive boilerplate quickly, and most existing scaffolds stop at empty folders. Flutter Zero generates a complete, opinionated MVI-BLoC module with production concerns like request cancellation, error normalization, and side-effect isolation already wired in, cutting the setup time for a new feature to a single command.
A new open-source CLI, fluzer, scaffolds entire Flutter feature modules with a single command, generating BLoC, Repository, Effect handlers, and DI registration. The architecture centers on four independent Mixins that separate concerns within flutter_bloc: BlocAwaitMixin bridges async operations to the UI with Futures, BlocEffectMixin isolates side effects onto a dedicated Stream, BlocCancelTokenMixin ties network request lifecycles to page navigation, and BlocErrorHandlerMixin normalizes errors into a typed Result pattern.
The side-effect system uses an open abstract class and a chain of responsibility, allowing any feature to define custom UI effects without modifying framework code. A companion `gen-l10n` command parses standard .arb files to generate type-safe localization identifiers, decoupling translation logic from the BLoC layer entirely. The DI layer uses a template method pattern with AST-based code injection, ensuring the CLI can add new module registrations idempotently.
Built by an Android developer who missed go-zero's code generation in the Dart ecosystem, the toolchain prioritizes eliminating boilerplate and preventing silent failures—Completers time out after 30 seconds, BLoC disposal cancels all pending requests, and runtime checks throw immediately if a required Mixin is missing.
Using an abstract class instead of a sealed class for UIEffect is a deliberate trade-off: it sacrifices compile-time exhaustiveness checking to allow any feature to define custom side effects without modifying framework source files.
The `onAwait` method that wraps event handlers in try/finally is a direct response to a common failure mode—developers forgetting to call `completeAwait` after early returns or caught exceptions—and mirrors go-zero's philosophy of eliminating anything that can be forgotten.
Making the `cancel` parameter optional in `Result.when()` acknowledges that most business scenarios genuinely need no action on cancellation; forcing an empty callback would add noise across dozens of BLoCs.
Placing all freezed imports in a single main BLoC file and using `part of` for state and event definitions prevents code generation failures caused by missing dependencies in subsidiary files, a practical fix for a common freezed pain point.
The ToastEffect priority chain (message > l10nCode > code) cleanly separates three sources of user-facing text—server-translated, client-localized, and error-code fallback—without the BLoC ever needing to know the current locale.
Requiring `BlocEffectMixin` on the BLoC and throwing a StateError at build time if it's missing turns a silent failure (effects mysteriously not appearing) into an immediate, debuggable crash.