Work with Obsidian vaults (plain Markdown notes) and automate via obsidian-cli.
npx skills add bear2u/my-skills --skill "flutter-init"
Install specific skill from multi-skill repository
# Description
Use when user wants to create a new Flutter project (Todo/Habit/Note/Expense/Custom domain) with Clean Architecture, Riverpod 3.0, Drift, and modern Flutter stack
# SKILL.md
name: flutter-init
description: Use when user wants to create a new Flutter project (Todo/Habit/Note/Expense/Custom domain) with Clean Architecture, Riverpod 3.0, Drift, and modern Flutter stack
Flutter Init Skill
λλ©μΈ κΈ°λ° Flutter νλ‘μ νΈλ₯Ό μμ±νκ³ νλμ μΈ μν€ν
μ²λ‘ μλ μ€μ ν©λλ€.
Todo, Habit, Note, Expense λλ Custom λλ©μΈμ μ ννμ¬ Clean Architecture κΈ°λ°μ μμ ν CRUD μ±μ μ¦μ μμ±ν μ μμ΅λλ€.
Quick Start
μ€ν¬ μ€ν μ λ€μ μ 보λ₯Ό μ
λ ₯λ°μ΅λλ€:
- ν΄λλͺ
(μ: my_habit_app)
- νλ‘μ νΈλͺ
/ν¨ν€μ§λͺ
(μ: habit_app)
- λλ©μΈ μ ν (Todo/Habit/Note/Expense/Custom)
- μ€ν ν리μ
(Minimal/Essential/Full Stack/Custom)
κ·Έ ν μλμΌλ‘ λ€μ λ¨κ³κ° μ€νλ©λλ€:
# 1. νλ‘μ νΈ μμ± (Android/Kotlin, iOS/Swift)
flutter create --platforms android,ios --android-language kotlin --org com.example [ν΄λλͺ
]
# 2. ν¨ν€μ§ μ€μΉ
flutter pub get
# 3. λλ©μΈλ³ Clean Architecture μ½λ μλ μμ±
# - domain/entities/[domain].dart (Freezed μν°ν°)
# - data/datasources/local/app_database.dart (Drift ν
μ΄λΈ)
# - data/repositories/[domain]_repository_impl.dart (Repository ꡬν)
# - presentation/providers/[domain]_providers.dart (Riverpod 3.0)
# - presentation/screens/* (List/Detail/Form νλ©΄)
# 4. μ½λ μμ± (Freezed, Drift, JSON Serializable)
dart run build_runner build --delete-conflicting-outputs
# 5. μ½λ κ²μ¦ λ° μ€λ₯ μλ μμ (νμ)
flutter analyze
# 6. μ± μ€ν
flutter run
Task Instructions
IMPORTANT: μ΄ μ€ν¬μ λννμΌλ‘ μ§νλ©λλ€.
Step 1: λλ©μΈ λ° νλ‘μ νΈ μ€μ μ§λ¬Έ
λ¨Όμ μ¬μ©μμκ² μ΄λ κ² λ¬Όμ΄λ³΄μΈμ:
"Flutter μ±μ μμ±ν©λλ€. λ€μ μ 보λ₯Ό μλ €μ£ΌμΈμ:
1. λλ©μΈ(μν°ν°) μ ν
μ΄λ€ λλ©μΈμ μ±μ λ§λμκ² μ΅λκΉ?
A) Todo (ν μΌ κ΄λ¦¬)
- νλ: title, description, isCompleted, createdAt, completedAt
- κΈ°λ₯: CRUD, νν°λ§(μ 체/μ§νμ€/μλ£), 체ν¬λ°μ€ ν κΈ
B) Habit (μ΅κ΄ νΈλ컀)
- νλ: name, description, frequency(daily/weekly/monthly), streak, lastCompletedAt, goal, isActive
- κΈ°λ₯: CRUD, μ°μ κΈ°λ‘ μΆμ , λͺ©ν λ¬μ±λ₯ , μλ£ μ²΄ν¬
C) Note (λ©λͺ¨)
- νλ: title, content, tags, isPinned, createdAt, updatedAt
- κΈ°λ₯: CRUD, νκ·Έ νν°λ§, κ³ μ λ©λͺ¨, κ²μ
D) Expense (μ§μΆ κ΄λ¦¬)
- νλ: amount, category, description, date, paymentMethod
- κΈ°λ₯: CRUD, μΉ΄ν
κ³ λ¦¬λ³ μ§κ³, μλ³ ν΅κ³, νν°λ§
E) Custom (μ§μ μ μ)
- μν°ν°λͺ
κ³Ό νλλ₯Ό μ§μ μ
λ ₯
2. νλ‘μ νΈ μ 보
- ν΄λλͺ
: νλ‘μ νΈλ₯Ό μμ±ν ν΄λ μ΄λ¦ (κΈ°λ³Έκ°: [λλ©μΈ]_app, μ: habit_app)
- μ΄ ν΄λμ Flutter νλ‘μ νΈκ° μμ±λ©λλ€
- νλ‘μ νΈλͺ
(ν¨ν€μ§λͺ
): Flutter ν¨ν€μ§ μ΄λ¦ (κΈ°λ³Έκ°: ν΄λλͺ
κ³Ό λμΌ)
- pubspec.yamlμ name νλμ μ¬μ©λ©λλ€
- import λ¬Έμ μ¬μ©λ©λλ€ (μ: package:habit_app/...)
- μ‘°μ§λͺ
: (κΈ°λ³Έκ°: com.example)
- Android/iOS ν¨ν€μ§ μλ³μμ μ¬μ©λ©λλ€ (μ: com.example.habit_app)
3. μ€ν ν리μ μ ν
λ€μ μ€ νλλ₯Ό μ νν΄μ£ΌμΈμ:
A) Essential (κΆμ₯)
- β
GoRouter (νμ
μμ ν λΌμ°ν
)
- β
SharedPreferences (λ‘컬 μ€μ μ μ₯)
- β
FPDart (ν¨μν μλ¬ νΈλ€λ§)
- β
Google Fonts
- β
FluentUI Icons
- β Auth μμ€ν
μ μΈ
- β Responsive Utils μ μΈ
B) Minimal (κ°μ₯ λ¨μ)
- β GoRouter (κΈ°λ³Έ Navigator μ¬μ©)
- β
SharedPreferences
- β FPDart μ μΈ
- β Google Fonts μ μΈ
- β
κΈ°λ³Έ FluentUI Icons
- β Auth μμ€ν
μ μΈ
- β Responsive Utils μ μΈ
C) Full Stack (λͺ¨λ κΈ°λ₯)
- β
GoRouter
- β
SharedPreferences
- β
FPDart (ν¨μν μλ¬ νΈλ€λ§)
- β
Google Fonts
- β
Responsive Utils
- β
FluentUI Icons
- β
Auth μμ€ν
(Login/Register) - μ ν λλ©μΈμ λ°λΌ
D) Custom (μ§μ μ ν)
- κ° κΈ°λ₯μ κ°λ³μ μΌλ‘ μ ν
μ΄λ€ λλ©μΈκ³Ό ν리μ μ μ ννμκ² μ΅λκΉ? (λλ©μΈ: A/B/C/D/E, ν리μ : A/B/C/D)"
Step 2: Custom μ ν μ μΆκ° μ§λ¬Έ
2-1. Custom λλ©μΈ (E) μ ν μ:
- μν°ν°λͺ : μν°ν° μ΄λ¦μ μ λ ₯νμΈμ (μ: Task, Event, Book)
- νλ μ μ: κ° νλλ₯Ό μ λ ₯νμΈμ (νμ: νλλͺ :νμ , μ: title:String, amount:double, isActive:bool)
- μ§μ νμ : String, int, double, bool, DateTime
- createdAt, updatedAtμ μλ μΆκ°λ¨
- μ£Όμ κΈ°λ₯: νν°λ§/μ λ ¬ κΈ°μ€μ΄ λ νλλ₯Ό μ ννμΈμ
2-2. Custom μ€ν ν리μ (D) μ ν μ:
λ€μ μ§λ¬Έλ€μ μμ°¨μ μΌλ‘ νμΈμ:
- λ€λΉκ²μ΄μ : GoRouterλ₯Ό μ¬μ©νμκ² μ΅λκΉ? (μ/μλμ€)
- μλ¬ νΈλ€λ§: FPDartλ₯Ό μ¬μ©νμκ² μ΅λκΉ? (μ/μλμ€)
- UI: Google Fontsλ₯Ό μ¬μ©νμκ² μ΅λκΉ? (μ/μλμ€)
- λ°μν: Responsive Utilsλ₯Ό ν¬ν¨νμκ² μ΅λκΉ? (μ/μλμ€)
- μΈμ¦ μμ€ν : Auth μμ€ν μ ν¬ν¨νμκ² μ΅λκΉ? (μ/μλμ€)
Step 3: μ νλ λλ©μΈκ³Ό μ€νμ λ°λΌ νλ‘μ νΈ μμ±
- Flutter νλ‘μ νΈ μμ±:
- μ¬μ©μκ° μ§μ ν ν΄λλͺ μΌλ‘ νλ‘μ νΈ μμ±
- λͺ
λ Ήμ΄:
flutter create --platforms android,ios --android-language kotlin --org [μ‘°μ§λͺ ] [ν΄λλͺ ] - μ:
flutter create --platforms android,ios --android-language kotlin --org com.example my_habit_app - ν΄λλͺ
κ³Ό νλ‘μ νΈλͺ
(ν¨ν€μ§λͺ
)μ΄ λ€λ₯Έ κ²½μ°, μμ± ν pubspec.yamlμ
nameνλλ₯Ό μμ - Kotlin DSL νμΈ (μ΅μ Flutterλ μλμΌλ‘ Kotlin DSL μ¬μ©)
- μ νλ ν¨ν€μ§ μ€μΉ:
pubspec.yamlμ λ°μ΄νΈ νflutter pub get - ν΄λ ꡬ쑰 μμ±: Clean Architecture (core, data, domain, presentation)
- λλ©μΈλ³ 보μΌλ¬νλ μ΄νΈ μμ±:
A) Todo: title, description, isCompleted, createdAt, completedAt
- Repository: getTodos, createTodo, updateTodo, toggleCompletion, deleteTodo
- Providers: filteredTodosProvider (all/pending/completed)
- UI: TodoListScreen (νν°λ§), TodoDetailScreen, TodoFormDialog
B) Habit: name, description, frequency, streak, lastCompletedAt, goal, isActive
- Repository: getHabits, createHabit, updateHabit, completeHabit, deleteHabit
- Providers: filteredHabitsProvider (active/inactive), habitStatsProvider
- UI: HabitListScreen (ν΅κ³), HabitDetailScreen, HabitFormDialog
C) Note: title, content, tags, isPinned, createdAt, updatedAt
- Repository: getNotes, createNote, updateNote, togglePin, deleteNote
- Providers: filteredNotesProvider (pinned/all/byTag), searchProvider
- UI: NoteListScreen (κ²μ/νκ·Έ), NoteDetailScreen, NoteFormDialog
D) Expense: amount, category, description, date, paymentMethod
- Repository: getExpenses, createExpense, updateExpense, deleteExpense
- Providers: expensesByCategory, monthlyStats, filteredExpenses
- UI: ExpenseListScreen (ν΅κ³), ExpenseDetailScreen, ExpenseFormDialog
E) Custom: μ¬μ©μ μ μ νλ
- Repository: κΈ°λ³Έ CRUD λ©μλ
- Providers: κΈ°λ³Έ list provider
- UI: κΈ°λ³Έ List/Detail/Form νλ©΄
- μ€μ νμΌ μμ± (λΌμ°ν , μ€ν 리μ§, λ€κ΅μ΄ λ±)
- Android μ€μ μ λ°μ΄νΈ (CRITICAL for flutter_local_notifications):
android/app/build.gradle.ktsμ core library desugaring νμ±ν:
kotlin android { compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 isCoreLibraryDesugaringEnabled = true // μΆκ° } } dependencies { coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4") // μΆκ° }- μ½λ μμ±:
dart run build_runner build --delete-conflicting-outputs - μ½λ κ²μ¦ λ° μ€λ₯ μμ :
a. flutter analyze μ€ν
b. λ°κ²¬λ μ€λ₯ μμ :
- Freezed 3.0 νΈνμ± (CRITICAL): λͺ¨λ Freezed μν°ν°λ sealed class μ¬μ©
- β class User with _$User
- β
sealed class User with _$User
- ν
λ§ μ€μ : CardTheme β CardThemeData μ¬μ© (deprecated)
- API Client Map νμ
: Map<String, dynamic> λ°ν μ μμ± μ½λ κ²μ¦
- retrofit_generatorκ° μμ±ν dynamic.fromJson μλ¬ λ°μ μ μμ νμ
- import κ²½λ‘ μμ : λͺ¨λ μλ κ²½λ‘λ₯Ό package: νμμΌλ‘ λ³κ²½
- μ: import '../../domain/entities/todo.dart'; β import 'package:todo_app/domain/entities/todo.dart';
- ν¨ν€μ§ μμ‘΄μ± νμΈ: λλ½λ ν¨ν€μ§ μΆκ° (μ: shared_preferences)
- Riverpod 3.0 νΈνμ±: StateNotifier β Notifier, StateProvider β NotifierProvider
- FluentUI μμ΄μ½ μ΄λ¦ νμΈ: μ‘΄μ¬νμ§ μλ μμ΄μ½μ λ체
- νμ
μμ μ±: switch expression μ¬μ©, null safety μ€μ
c. μ¬κ²μ¦: λͺ¨λ error λ 벨 μ€λ₯κ° μμ λκΉμ§ λ°λ³΅
d. λͺ©ν: flutter analyze κ²°κ³Όκ° "0-1 issues found" (info λ λ²¨λ§ νμ©)
β CRITICAL: μ΄ λ¨κ³λ νμμ λλ€. λͺ¨λ errorλ₯Ό μ κ±°ν΄μΌ λ€μ λ¨κ³λ‘ μ§νν μ μμ΅λλ€.
Step 4: μ΅μ’ κ²μ¦ λ° μλ΄
β CRITICAL: μ΄ λ¨κ³λ νλ‘μ νΈ μλ£μ νμ 쑰건μ λλ€.
-
μ΅μ’ λΆμ μ€ν:
bash flutter analyze -
μ±κ³΅ κΈ°μ€:
-
β μ±κ³΅ μμ:
Analyzing todo_app... No issues found!
λλ
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 -
β μ€ν¨ μμ (errorκ° μμΌλ©΄ λ°λμ μμ ):
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 -
κ²μ¦ κ²°κ³Ό μμ½ (μ±κ³΅ μ):
β Flutter νλ‘μ νΈ μμ± μλ£! β μ½λ μμ± μλ£ (Freezed, Drift, JSON Serializable) β Flutter analyze ν΅κ³Ό (0-1 issues found, info λ 벨λ§) β λͺ¨λ ν¨ν€μ§ μ€μΉ μλ£ -
νλ‘μ νΈ μ 보 μ 곡:
- ν΄λλͺ : [μ¬μ©μ μ λ ₯κ°] (μ: my_habit_app)
- νλ‘μ νΈλͺ (ν¨ν€μ§λͺ ): [μ¬μ©μ μ λ ₯κ°] (μ: habit_app)
- μ‘°μ§λͺ : [μ¬μ©μ μ λ ₯κ°] (μ: com.example)
- λλ©μΈ: [μ νλ λλ©μΈ] (Todo/Habit/Note/Expense/Custom)
- μ νλ μ€ν: [ν리μ λͺ ] (GoRouter, Drift, FPDart λ±)
- μ£Όμ κΈ°λ₯: [λλ©μΈ] CRUD, λ€κ΅μ΄ μ§μ, λ‘컬 μ μ₯μ λ±
-
μμ±λ νμΌ: XXκ° Dart νμΌ (core, data, domain, presentation)
-
μ€ν λ°©λ² μλ΄:
bash cd [ν΄λλͺ ] flutter run -
λ€μ λ¨κ³ μ μ (μ νμ¬ν, λλ©μΈλ³):
- Todo: νλͺ© μΆκ°/μμ /μμ , νν°λ§(μ 체/μ§νμ€/μλ£), μλ£ ν κΈ
- Habit: μ΅κ΄ κΈ°λ‘, μ°μ κΈ°λ‘ νμΈ, λͺ©ν λ¬μ±λ₯ , ν΅κ³ νμΈ
- Note: λ©λͺ¨ μμ±/νΈμ§, νκ·Έ μΆκ°, κ³ μ λ©λͺ¨, κ²μ
- Expense: μ§μΆ κΈ°λ‘, μΉ΄ν κ³ λ¦¬λ³ ν΅κ³, μλ³ μ§κ³, νν°λ§
- 곡ν΅: μΈμ΄ μ ν (μμ΄ β νκ΅μ΄), λ€ν¬/λΌμ΄νΈ ν λ§ μ ν
Core Principles
- Repository ν¨ν΄: λ°μ΄ν° λ μ΄μ΄μ λλ©μΈ λ μ΄μ΄ λΆλ¦¬
- μμ‘΄μ± μ£Όμ : Riverpod 3.xλ₯Ό ν΅ν μμ‘΄μ± κ΄λ¦¬
- λΆλ³μ±: Freezedλ‘ λΆλ³ λͺ¨λΈ μμ±
- λ€κ΅μ΄ μ§μ: Easy LocalizationμΌλ‘ i18n
- λͺ¨λ UI: FluentUI Icons μ¬μ©
Reference Files
references/setup-guide.md - μμ ν κ°μ΄λ
- κΈ°λ³Έ μ
μ
(λλ©μΈλ³ CRUD, λ€κ΅μ΄, FluentUI Icons)
- μ ν μ΅μ
: GoRouter, Auth, FPDart, Google Fonts, Responsive Utils, ν¨ν€μ§ μ
λ°μ΄νΈ
Notes
- λνν μ€ν¬: μ¬μ©μμκ² λλ©μΈκ³Ό ν리μ μ νμ ν΅ν΄ λ§μΆ€ν μ± κ΅¬μ±
- λλ©μΈ μ§μ: Todo, Habit, Note, Expense, Custom (μ¬μ©μ μ μ)
- ν리μ μ 곡: Full Stack, Essential, Minimal, Custom
- μ ν κ°λ₯ κΈ°λ₯: GoRouter, Auth, FPDart, Google Fonts, Responsive Utils
- κΈ°λ³Έ ν¬ν¨: Riverpod 3.x, Easy Localization, FluentUI Icons, Drift, Dio, SharedPreferences
- λ€κ΅μ΄: μμ΄/νκ΅μ΄ (νμ₯ κ°λ₯)
- νλ«νΌ: Android/Kotlin, iOS/Swift (μΉ/μλμ°/리λ μ€ μ μΈ)
- νμ§ λ³΄μ¦:
- λͺ¨λ νλ‘μ νΈλ
flutter analyzeν΅κ³Ό νμ - package: imports μ€νμΌ μ€μ
- νμ μμ μ± λ³΄μ₯
- μ½λ μμ± μλν
- λλ©μΈλ³ μ΅μ νλ UI/UX
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.