Create a domain-based Flutter project and Feature-First architectureIt is automatically configured with. You can select a Todo, Habit, Note, Expense, or Custom domain to instantly generate an offline-first CRUD app.
Tech Stack
| Area | Technology | Notes |
|---|---|---|
| State | Riverpod 3 | Code Gen required (@riverpod) |
| Data | Freezed 3 | Immutable Models |
| DB | Drift | SQLite, Offline-first |
| Network | Dio | HTTP Client |
| Routing | GoRouter | Typed Routes required |
Quick Start
When the skill runs, the following information is entered:
- Folder name (e.g., my_habit_app)
- Project name/package name (e.g., habit_app)
- Domain selection (Todo/Habit/Note/Expense/Custom)
- Stack preset (Minimal/Essential/Full Stack/Custom)
After that, the following steps run automatically:
# 1. 프로젝트 생성 (Android/Kotlin, iOS/Swift)
flutter create --platforms android,ios --android-language kotlin --org com.example [폴더명]
# 2. 패키지 설치
flutter pub get
# 3. Feature-First 구조로 코드 자동 생성
# - lib/src/features/{domain}/presentation/ (UI + Notifier)
# - lib/src/features/{domain}/domain/ (Freezed 모델)
# - lib/src/features/{domain}/data/ (Repository, DAO)
# - lib/src/database/ (Drift DB 정의)
# - lib/src/routing/ (GoRouter Typed Routes)
# 4. 코드 생성 (Riverpod, Freezed, Drift)
dart run build_runner build --delete-conflicting-outputs
# 5. 코드 검증 및 오류 자동 수정 (필수)
flutter analyze
# 6. 앱 실행
flutter run
Task Instructions
IMPORTANT: This skill proceeds interactively.
Step 1: Domain and project setup questions
First, ask the user this:
"Create a Flutter app. Please provide the following information:
1. Select domain (entity)
What domain app would you like to create?
A) Todo (task management)
- Fields: title, description, isCompleted, createdAt, completedAt
- Features: CRUD, filtering (all/in progress/completed), checkbox toggle
B) Habit (habit tracker)
- Fields: name, description, frequency(daily/weekly/monthly), streak, lastCompletedAt, goal, isActive
- Features: CRUD, streak tracking, goal achievement rate, completion check
C) Note (memo)
- Fields: title, content, tags, isPinned, createdAt, updatedAt
- Features: CRUD, tag filtering, pinned notes, search
D) Expense (expense management)
- Fields: amount, category, description, date, paymentMethod
- Features: CRUD, aggregation by category, monthly statistics, filtering
E) Custom (define your own)
- Enter the entity name and fields yourself
2. Project information
- Folder name: The folder name where the project will be created (default: [domain]_app, e.g., habit_app)
- The Flutter project will be created in this folder
- Project name (package name): Flutter package name (default: same as folder name)
- Used for the name field in pubspec.yaml
- Used in import statements (e.g., package:habit_app/...)
- Organization name: (default: com.example)
- Used for Android/iOS package identifiers (e.g., com.example.habit_app)
3. Select stack preset
Please choose one of the following:
A) Essential (recommended)
- ✅ GoRouter (type-safe routing)
- ✅ SharedPreferences (local settings storage)
- ✅ FPDart (functional error handling)
- ✅ Google Fonts
- ✅ FluentUI Icons
- ❌ Auth system excluded
- ❌ Responsive Utils excluded
B) Minimal (simplest)
- ❌ GoRouter (use default Navigator)
- ✅ SharedPreferences
- ❌ FPDart excluded
- ❌ Exclude Google Fonts
- ✅ Default FluentUI Icons
- ❌ Exclude Auth system
- ❌ Exclude Responsive Utils
C) Full Stack (all features)
- ✅ GoRouter
- ✅ SharedPreferences
- ✅ FPDart (functional error handling)
- ✅ Google Fonts
- ✅ Responsive Utils
- ✅ FluentUI Icons
- ✅ Auth system (Login/Register) - depending on the selected domain
D) Custom (select manually)
- Select each feature individually
Which domain and preset would you like to select? (Domain: A/B/C/D/E, Preset: A/B/C/D)"
Step 2: Additional questions when Custom is selected
2-1. When Custom domain (E) is selected:
- Entity name: Enter the entity name (e.g., Task, Event, Book)
- Field definition: Enter each field (format: fieldName:type, e.g., title:String, amount:double, isActive:bool)
- Supported types: String, int, double, bool, DateTime
- createdAt, updatedAt are added automatically
- Main features: Select the fields to be used as filtering/sorting criteria
2-2. When Custom stack preset (D) is selected:
Ask the following questions sequentially:
- Navigation: Would you like to use GoRouter? (yes/no)
- Error handling: Would you like to use FPDart? (yes/no)
- UI: Would you like to use Google Fonts? (yes/no)
- Responsive: Would you like to include Responsive Utils? (yes/no)
- Authentication system: Would you like to include the Auth system? (yes/no)
Step 3: Create the project according to the selected domain and stack
-
Create Flutter project:
- Create the project with the folder namespecified by the user
- Command:
flutter create --platforms android,ios --android-language kotlin --org [조직명] [폴더명] - 예:
flutter create --platforms android,ios --android-language kotlin --org com.example my_habit_app - If the folder name and project name (package name) differ, after creation, modify the
namefield in pubspec.yaml
-
Check Kotlin DSL (the latest Flutter automatically uses Kotlin DSL)
-
Install selected packages:
pubspec.yamlAfter updatingflutter pub get -
Create Feature-First folder structure:
lib/ └── src/ ├── features/ │ └── {domain}/ │ ├── presentation/ # UI 위젯 + Notifier (@riverpod) │ ├── domain/ # Freezed 모델/엔티티 │ └── data/ # Repository 구현, DAO ├── database/ # Drift DB 정의 (전역) ├── routing/ # GoRouter Typed Routes └── shared/ # 공통 위젯, 유틸리티 -
Generate boilerplate per domain (Feature-First + Riverpod Code Gen):
A) Todo: title, description, isCompleted, createdAt, completedAt
features/todo/domain/todo.dart- Freezed entityfeatures/todo/data/todo_repository.dart- Repository + DAOfeatures/todo/presentation/todo_notifier.dart-@riverpodNotifierfeatures/todo/presentation/todo_list_screen.dart- UI
B) Habit: name, description, frequency, streak, lastCompletedAt, goal, isActive
features/habit/domain/habit.dart- Freezed entityfeatures/habit/data/habit_repository.dart- Repository + DAOfeatures/habit/presentation/habit_notifier.dart-@riverpodNotifierfeatures/habit/presentation/habit_list_screen.dart- UI
C) Note: title, content, tags, isPinned, createdAt, updatedAt
features/note/domain/note.dart- Freezed entityfeatures/note/data/note_repository.dart- Repository + DAOfeatures/note/presentation/note_notifier.dart-@riverpodNotifierfeatures/note/presentation/note_list_screen.dart- UI
D) Expense: amount, category, description, date, paymentMethod
features/expense/domain/expense.dart- Freezed entityfeatures/expense/data/expense_repository.dart- Repository + DAOfeatures/expense/presentation/expense_notifier.dart-@riverpodNotifierfeatures/expense/presentation/expense_list_screen.dart- UI
E) Custom: custom fields
- Generate with the same Feature-First structure
-
Create configuration files:
lib/src/database/app_database.dart- Drift DB (global)lib/src/routing/app_router.dart- GoRouter Typed Routesassets/translations/- Easy Localization
-
Code generation:
dart run build_runner build --delete-conflicting-outputs -
Code verification and error fixing:
a.
flutter analyzeRunb. Fix discovered errors:
- import path:
package:Use the format - Riverpod 3 Code Gen: All Providers use the
@riverpodannotation - Freezed 3:
@freezedannotation +partCheck the file - AsyncValue: Loading/error states use the
.when()pattern
c. Re-validation: Repeat until there are no errors at the error level
d. Goal:
flutter analyzethe result is "0 issues found"✅ CRITICAL: This step is mandatory. All errors must be removed before you can proceed to the next step.
- import path:
Step 4: Final verification and guidance
✅ CRITICAL: This step is a mandatory condition for project completion.
-
Run final analysis:
flutter analyze -
Success criteria:
-
✅ Success example:
Analyzing todo_app... No issues found!or
Analyzing todo_app... 1 issue found. (ran in 2.3s) info • Prefer using lowerCamelCase for constant names • lib/core/constants.dart:5:7 • constant_identifier_names -
❌ Failure example (must be fixed if there are any errors):
error • Target of URI doesn't exist: 'package:...' • lib/main.dart:5:8 • uri_does_not_exist error • The getter 'xyz' isn't defined for the type 'ABC' • lib/presentation/screens/home.dart:42:15
-
-
Verification result summary (on success):
✅ Flutter 프로젝트 생성 완료! ✅ 코드 생성 완료 (Freezed, Drift, JSON Serializable) ✅ Flutter analyze 통과 (0-1 issues found, info 레벨만) ✅ 모든 패키지 설치 완료 -
Provide project information:
- Folder name: [user input value] (e.g., my_habit_app)
- Project name (package name): [user input value] (e.g., habit_app)
- Organization name: [user input value] (e.g., com.example)
- Domain: [selected domain] (Todo/Habit/Note/Expense/Custom)
- Selected stack: [preset name] (GoRouter, Drift, FPDart, etc.)
- Key features: [domain] CRUD, multilingual support, local storage, etc.
- Generated files: XX Dart files (core, data, domain, presentation)
-
How to run:
cd [폴더명] flutter run -
Suggested next steps (optional, by domain):
- Todo: Add/edit/delete items, filtering (all/in progress/completed), toggle completion
- Habit: Habit logging, streak tracking, goal achievement rate, statistics
- Note: Create/edit notes, add tags, pin notes, search
- Expense: Expense logging, statistics by category, monthly totals, filtering
- Common: Language switching (English ↔ Korean), dark/light theme switching
Core Principles
- Feature-First: Independent structure per feature (
lib/src/features/{feature}/) - Riverpod 3 Code Gen: All Providers must use the
@riverpodannotation - Freezed 3: Immutable models + JSON serialization
- Offline-First: Local-first storage with Drift SQLite
- Typed Routes: Type-safe navigation with GoRouter
- AsyncValue: Loading/error states use the
.when()pattern
Coding Conventions
1. Riverpod 3 (State Management)
// ✅ Code Gen 사용 (필수)
@riverpod
class TodoNotifier extends _$TodoNotifier {
@override
Future<List<Todo>> build() async {
return ref.watch(todoRepositoryProvider).getTodos();
}
}
// UI에서 사용
ref.watch(todoNotifierProvider).when(
data: (todos) => ListView(...),
error: (e, st) => ErrorWidget(e),
loading: () => CircularProgressIndicator(),
);
2. Freezed 3 (Models)
@freezed
class Todo with _$Todo {
const factory Todo({
required int id,
required String title,
@Default(false) bool isCompleted,
}) = _Todo;
factory Todo.fromJson(Map<String, dynamic> json) => _$TodoFromJson(json);
}
3. Error handling
- Repository:
try-catchthen return a custom error or wrap withAsyncValuewrapped in - UI:
.when(data, error, loading)pattern to display errors
4. Drift (Local DB)
- Table definition:
lib/src/database/(global) - DAO:
features/{feature}/data/located within
Reference Files
references/setup-guide.md - Complete guide
- Feature-First Structure Details
- Riverpod 3 Code Gen Pattern
- Drift DAO Pattern
- GoRouter Typed Routes
Notes
- Feature-First Structure: Independent folder per feature (
lib/src/features/) - Code Gen required: Riverpod, Freezed, and Drift all use code generation
- Domain support: Todo, Habit, Note, Expense, Custom
- Preset provided: Full Stack, Essential, Minimal, Custom
- Platform: Android/Kotlin, iOS/Swift
- Main Commands:
- Build:
dart run build_runner build --delete-conflicting-outputs - Watch:
dart run build_runner watch - Lint:
flutter analyze - Test:
flutter test
- Build: