This document describes the internal system design of FlutterInit, explaining how a user's selection on the dashboard travels through the generator to produce a production-ready Flutter project.
FlutterInit follows a layered pipeline where configuration data is transformed into a functional filesystem.
+-----------------------+ (Next.js Dashboard)
| Web UI (Wizard) |
+-----------+-----------+
|
v
+-----------+-----------+ (app/lib/config/schema.ts)
| Config Schema |
+-----------+-----------+
|
v
+-----------+-----------+ (app/lib/generator/index.ts)
| Generator Logic |
+-----------+-----------+
|
v
+-----------+-----------+ (templates/flutter/)
| Handlebars Templates |
+-----------+-----------+
|
v
+-----------+-----------+ (ZIP / dev_out/)
| Generated Dart Output |
+-----------------------+
The front-end wizard built with Next.js allows users to visually configure their project. It collects user inputs and validates them against the shared Zod schema.
The single source of truth for all project options. It defines the ScaffoldConfig interface using Zod, ensuring that only valid combinations of flags (like usesRiverpod or navigation: 'go_router') reach the generator.
The engine of the system.
index.ts: Orchestrates the generation by resolving which "Architecture Overlays" should be applied based on the config.handlebars.ts: Configures the Handlebars environment with custom helpers likeres(for ScreenUtil scaling) and case conversion utilities.- It performs a Layered Merge: it starts with the
base/directory and overlays specific architecture, state management, and plugin folders on top.
The raw material of the generated app.
base/: The fundamental Flutter project structure shared by everyone.overlays/: Conditional logic blocks (State Management, Auth providers, etc.) that replace or add files to the base structure.partials/: Reusable code snippets (e.g., standard login form UI) included via{{> partial_name }}.
The final product. During production, the generator produces a JSZip buffer for the user to download. During development, the scripts/template-dev.ts script extracts this into dev_out/ for real-time debugging.
To understand the end-to-end flow, consider toggling the Riverpod state management flag:
- Dashboard: User selects "Riverpod" in the State Management step.
- Schema: The
stateManagementfield inScaffoldConfigis set to'riverpod'. - Generator:
buildTemplateContext()sees this and setsflags.isRiverpod = true. - Overlays:
resolveOverlayDirs()addstemplates/flutter/overlays/state/riverpodto the merge list. - Templates:
pubspec.yaml.hbsaddsflutter_riverpodto dependencies.main.dart.hbswraps theAppin aProviderScope.- Architectural blocks use
ConsumerWidgetinstead ofStatelessWidget.
- Output: The generated project contains a fully reactive Riverpod setup.
| File | Role |
|---|---|
app/lib/config/schema.ts |
Defines every available option and its default value. |
app/lib/generator/index.ts |
The main generateFlutterScaffold function. |
app/lib/generator/handlebars.ts |
Custom logic for templates (e.g. isRiverpod checks). |
templates/flutter/base/ |
The "skeleton" of the generated app. |
scripts/template-dev.ts |
The bridge between template changes and a running dev_out project. |
When adding a new architectural pattern or plugin support:
- Define the Flag: Add the new boolean flag to
miscSchemainschema.ts. - Update Context: Wire the flag in
buildTemplateContext()insidegenerator/index.ts. - Create Overlay: Add a new folder in
templates/flutter/overlays/to house the specific files. - Register Overlay: Add the new folder path to
candidatesinresolveOverlayDirs(). - Update Barrels: Ensure any new services/widgets are exported in
core_imports.dart.hbsorservices.dart.hbs.
Next Step: See Template Development Guide to start building.