Creates a new Flutter project with Clean Architecture, domain pattern boilerplate, and production-ready setup
/plugin marketplace add vp-k/flutter-craft/plugin install vp-k-flutter-craft-plugins-flutter-craft@vp-k/flutter-craftThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/categorized-pattern.mdreferences/relational-pattern.mdreferences/simple-pattern.mdreferences/stateful-pattern.mdreferences/tracked-pattern.mdUse when: "new project", "create project", "start project", "init flutter"
Step 1: Project Info → name, org, description
Step 2: Domain Pattern → Simple/Stateful/Categorized/Tracked/Relational/Custom
Step 3: Tech Stack → State Management, Features
Step 4: Generate & Verify → create, build, analyze
Ask user for:
| Field | Example | Required |
|---|---|---|
| Project name | my_app (snake_case) | Yes |
| Organization | com.example | Yes |
| Description | "Task management app" | Yes |
| Entity name | Task, Note, Expense | Yes |
Ask user to choose:
| Pattern | Examples | Generated Structure |
|---|---|---|
| Simple | Note, Memo, Bookmark | 단일 엔티티 CRUD |
| Stateful | Todo, Task, Order | 상태 필드 포함 (완료/진행중 등) |
| Categorized | Expense, Product, Recipe | 카테고리 관계 포함 |
| Tracked | Habit, Workout, Study | 시간/날짜 기반 트래킹 |
| Relational | Blog (User-Post-Comment) | 다중 엔티티 관계 |
| Custom | - | 사용자 정의 필드 |
// Entity
@freezed
sealed class Note with _$Note {
const factory Note({
required String id,
required String title,
required String content,
required DateTime createdAt,
DateTime? updatedAt,
}) = _Note;
}
// Entity with status
@freezed
sealed class Task with _$Task {
const factory Task({
required String id,
required String title,
required String description,
@Default(TaskStatus.pending) TaskStatus status,
required DateTime createdAt,
DateTime? completedAt,
}) = _Task;
}
enum TaskStatus { pending, inProgress, completed, cancelled }
// Entity with category relation
@freezed
sealed class Expense with _$Expense {
const factory Expense({
required String id,
required String title,
required double amount,
required String categoryId,
required DateTime date,
String? note,
}) = _Expense;
}
@freezed
sealed class Category with _$Category {
const factory Category({
required String id,
required String name,
required String icon,
required String color,
}) = _Category;
}
// Entity with time tracking
@freezed
sealed class Habit with _$Habit {
const factory Habit({
required String id,
required String name,
required String description,
required HabitFrequency frequency,
required List<DateTime> completedDates,
required int currentStreak,
required int bestStreak,
required DateTime createdAt,
}) = _Habit;
}
enum HabitFrequency { daily, weekly, monthly }
// Multiple related entities
@freezed
sealed class User with _$User {
const factory User({
required String id,
required String name,
required String email,
required DateTime createdAt,
}) = _User;
}
@freezed
sealed class Post with _$Post {
const factory Post({
required String id,
required String authorId,
required String title,
required String content,
required DateTime createdAt,
@Default(0) int likeCount,
}) = _Post;
}
@freezed
sealed class Comment with _$Comment {
const factory Comment({
required String id,
required String postId,
required String authorId,
required String content,
required DateTime createdAt,
}) = _Comment;
}
| Option | Description |
|---|---|
| Riverpod (Recommended) | Modern, compile-safe, testable |
| BLoC | Event-driven, enterprise-grade |
| Preset | Includes |
|---|---|
| Minimal | Core only (Freezed, Drift, DI) |
| Essential | + GoRouter, Dio, Error handling |
| Full | + Auth, Localization, Responsive |
# Minimal preset (always included)
flutter pub add freezed_annotation
flutter pub add drift
flutter pub add get_it
flutter pub add injectable
flutter pub add dev:freezed
flutter pub add dev:build_runner
flutter pub add dev:injectable_generator
flutter pub add dev:drift_dev
# Essential preset adds
flutter pub add go_router
flutter pub add dio
flutter pub add dartz # Either type for error handling
# Full preset adds
flutter pub add easy_localization
flutter pub add responsive_framework
flutter pub add firebase_auth # Optional
flutter create --org <org> --project-name <name> <name>
cd <name>
lib/
├── core/
│ ├── constants/
│ │ └── app_constants.dart
│ ├── database/
│ │ └── app_database.dart
│ ├── di/
│ │ └── injection.dart
│ ├── errors/
│ │ ├── exceptions.dart
│ │ └── failures.dart
│ ├── router/
│ │ └── app_router.dart
│ ├── theme/
│ │ ├── app_colors.dart
│ │ └── app_theme.dart
│ └── utils/
│ └── extensions.dart
├── features/
│ └── <entity>/
│ ├── domain/
│ │ ├── entities/
│ │ │ └── <entity>.dart
│ │ ├── repositories/
│ │ │ └── <entity>_repository.dart
│ │ └── usecases/
│ │ ├── create_<entity>.dart
│ │ ├── delete_<entity>.dart
│ │ ├── get_<entity>s.dart
│ │ └── update_<entity>.dart
│ ├── data/
│ │ ├── datasources/
│ │ │ └── <entity>_local_datasource.dart
│ │ ├── models/
│ │ │ └── <entity>_model.dart
│ │ └── repositories/
│ │ └── <entity>_repository_impl.dart
│ └── presentation/
│ ├── bloc/ # or providers/
│ │ ├── <entity>_bloc.dart
│ │ ├── <entity>_event.dart
│ │ └── <entity>_state.dart
│ ├── pages/
│ │ ├── <entity>_list_page.dart
│ │ └── <entity>_detail_page.dart
│ └── widgets/
│ └── <entity>_card.dart
├── shared/
│ └── widgets/
│ └── loading_widget.dart
└── main.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'failures.freezed.dart';
@freezed
sealed class Failure with _$Failure {
const factory Failure.server({required String message, int? code}) = ServerFailure;
const factory Failure.cache({required String message}) = CacheFailure;
const factory Failure.network({@Default('No internet connection') String message}) = NetworkFailure;
const factory Failure.validation({required String message}) = ValidationFailure;
}
import 'dart:io';
import 'package:drift/drift.dart';
import 'package:drift/native.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p;
part 'app_database.g.dart';
// Tables will be added per domain pattern
@DriftDatabase(tables: [])
class AppDatabase extends _$AppDatabase {
AppDatabase() : super(_openConnection());
@override
int get schemaVersion => 1;
}
LazyDatabase _openConnection() {
return LazyDatabase(() async {
final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, 'app.db'));
return NativeDatabase.createInBackground(file);
});
}
import 'package:get_it/get_it.dart';
import 'package:injectable/injectable.dart';
import 'injection.config.dart';
final getIt = GetIt.instance;
@InjectableInit(preferRelativeImports: true)
Future<void> configureDependencies() async => getIt.init();
Based on selected preset, add all required dependencies.
flutter pub get
flutter pub run build_runner build --delete-conflicting-outputs
flutter analyze
Must pass with 0 errors. Info/warning level issues are acceptable.
If errors exist:
flutter pub run build_runner buildflutter analyzegit init
git add .
git commit -m "Initial commit: <project_name> with Clean Architecture
- Domain pattern: <selected_pattern>
- State management: <Riverpod/BLoC>
- Features: <selected_preset>
🤖 Generated with flutter-craft"
flutter pub get successfulflutter pub run build_runner build successfulflutter analyze returns 0 errorsAfter completion, inform:
✅ Project '<name>' created successfully!
📁 Structure: Clean Architecture
📦 Pattern: <selected_pattern>
🔄 State: <Riverpod/BLoC>
✨ Features: <preset>
Next steps:
1. cd <name>
2. flutter run
3. Use /brainstorm to plan your first feature
For detailed code templates per pattern, see:
references/simple-pattern.mdreferences/stateful-pattern.mdreferences/categorized-pattern.mdreferences/tracked-pattern.mdreferences/relational-pattern.mdNote: Custom 패턴은 사용자 정의 필드를 직접 설계하므로 별도 템플릿이 없습니다.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.