oh-my-customcode 0.36.1 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/cli/index.js +47 -2
  2. package/dist/index.js +44 -0
  3. package/package.json +1 -1
  4. package/templates/.claude/agents/arch-documenter.md +4 -1
  5. package/templates/.claude/agents/arch-speckit-agent.md +15 -0
  6. package/templates/.claude/agents/be-django-expert.md +1 -0
  7. package/templates/.claude/agents/be-express-expert.md +1 -0
  8. package/templates/.claude/agents/be-fastapi-expert.md +1 -0
  9. package/templates/.claude/agents/be-go-backend-expert.md +1 -0
  10. package/templates/.claude/agents/be-nestjs-expert.md +1 -0
  11. package/templates/.claude/agents/be-springboot-expert.md +1 -0
  12. package/templates/.claude/agents/db-postgres-expert.md +1 -0
  13. package/templates/.claude/agents/db-redis-expert.md +1 -0
  14. package/templates/.claude/agents/db-supabase-expert.md +1 -0
  15. package/templates/.claude/agents/de-airflow-expert.md +1 -0
  16. package/templates/.claude/agents/de-dbt-expert.md +1 -0
  17. package/templates/.claude/agents/de-kafka-expert.md +1 -0
  18. package/templates/.claude/agents/de-pipeline-expert.md +1 -0
  19. package/templates/.claude/agents/de-snowflake-expert.md +1 -0
  20. package/templates/.claude/agents/de-spark-expert.md +1 -0
  21. package/templates/.claude/agents/fe-flutter-agent.md +1 -0
  22. package/templates/.claude/agents/fe-svelte-agent.md +1 -0
  23. package/templates/.claude/agents/fe-vercel-agent.md +1 -0
  24. package/templates/.claude/agents/fe-vuejs-agent.md +1 -0
  25. package/templates/.claude/agents/infra-aws-expert.md +1 -0
  26. package/templates/.claude/agents/infra-docker-expert.md +1 -0
  27. package/templates/.claude/agents/lang-golang-expert.md +1 -0
  28. package/templates/.claude/agents/lang-java21-expert.md +3 -0
  29. package/templates/.claude/agents/lang-kotlin-expert.md +1 -0
  30. package/templates/.claude/agents/lang-python-expert.md +1 -0
  31. package/templates/.claude/agents/lang-rust-expert.md +1 -0
  32. package/templates/.claude/agents/lang-typescript-expert.md +1 -0
  33. package/templates/.claude/agents/mgr-claude-code-bible.md +1 -2
  34. package/templates/.claude/agents/mgr-creator.md +1 -0
  35. package/templates/.claude/agents/mgr-gitnerd.md +1 -0
  36. package/templates/.claude/agents/mgr-sauron.md +5 -2
  37. package/templates/.claude/agents/mgr-supplier.md +1 -3
  38. package/templates/.claude/agents/mgr-updater.md +1 -0
  39. package/templates/.claude/agents/qa-engineer.md +1 -0
  40. package/templates/.claude/agents/qa-planner.md +4 -1
  41. package/templates/.claude/agents/qa-writer.md +1 -1
  42. package/templates/.claude/agents/sec-codeql-expert.md +4 -2
  43. package/templates/.claude/agents/sys-memory-keeper.md +30 -0
  44. package/templates/.claude/agents/sys-naggy.md +36 -2
  45. package/templates/.claude/agents/tool-bun-expert.md +1 -1
  46. package/templates/.claude/agents/tool-npm-expert.md +1 -1
  47. package/templates/.claude/agents/tool-optimizer.md +1 -2
  48. package/templates/.claude/hooks/hooks.json +37 -7
  49. package/templates/.claude/hooks/scripts/agent-teams-advisor.sh +10 -0
  50. package/templates/.claude/hooks/scripts/audit-log.sh +55 -0
  51. package/templates/.claude/hooks/scripts/content-hash-validator.sh +2 -3
  52. package/templates/.claude/hooks/scripts/schema-validator.sh +103 -0
  53. package/templates/.claude/hooks/scripts/secret-filter.sh +97 -0
  54. package/templates/.claude/hooks/scripts/session-compliance-report.sh +65 -0
  55. package/templates/.claude/rules/MUST-agent-teams.md +0 -23
  56. package/templates/.claude/rules/MUST-orchestrator-coordination.md +1 -13
  57. package/templates/.claude/skills/django-best-practices/SKILL.md +27 -134
  58. package/templates/.claude/skills/flutter-best-practices/SKILL.md +39 -146
  59. package/templates/.claude/skills/go-backend-best-practices/SKILL.md +29 -233
  60. package/templates/.claude/skills/java21-best-practices/SKILL.md +48 -163
  61. package/templates/CLAUDE.md.en +7 -65
  62. package/templates/CLAUDE.md.ko +7 -65
  63. package/templates/manifest.json +1 -1
@@ -16,26 +16,7 @@ Apply Django patterns for building production-ready, secure, and maintainable Py
16
16
  ```yaml
17
17
  structure:
18
18
  settings_split: true
19
- layout: |
20
- project/
21
- ├── config/
22
- │ ├── settings/
23
- │ │ ├── base.py
24
- │ │ ├── development.py
25
- │ │ └── production.py
26
- │ ├── urls.py
27
- │ └── wsgi.py
28
- ├── apps/
29
- │ ├── core/ # Shared utilities, base models
30
- │ ├── users/ # Custom User model (ALWAYS create)
31
- │ └── {feature}/ # Feature-specific apps
32
- ├── templates/
33
- ├── static/
34
- ├── requirements/
35
- │ ├── base.txt
36
- │ ├── development.txt
37
- │ └── production.txt
38
- └── manage.py
19
+ layout: "config/{settings/{base,development,production}.py,urls.py,wsgi.py} + apps/{core/,users/,<feature>/} + templates/ + static/ + requirements/{base,development,production}.txt"
39
20
 
40
21
  app_module_contents:
41
22
  models.py: Database models
@@ -50,6 +31,8 @@ app_module_contents:
50
31
  tests/: Test suite (mirror app structure)
51
32
  ```
52
33
 
34
+ Reference: guides/django-best-practices/README.md
35
+
53
36
  ### 2. Models Best Practices
54
37
 
55
38
  ```yaml
@@ -57,15 +40,7 @@ custom_user_model:
57
40
  rule: ALWAYS create a custom User model, even if identical to default
58
41
  location: apps/users/models.py
59
42
  reason: Impossible to swap default User model mid-project
60
- example: |
61
- # apps/users/models.py
62
- from django.contrib.auth.models import AbstractUser
63
-
64
- class User(AbstractUser):
65
- pass # Can extend later without migrations
66
-
67
- # config/settings/base.py
68
- AUTH_USER_MODEL = 'users.User'
43
+ pattern: "Extend AbstractUser, set AUTH_USER_MODEL in settings"
69
44
 
70
45
  primary_key:
71
46
  default: BigAutoField
@@ -77,18 +52,6 @@ model_meta:
77
52
  - Meta.ordering: consistent default ordering
78
53
  - Meta.verbose_name: singular display name
79
54
  - Meta.verbose_name_plural: plural display name
80
- example: |
81
- class Article(models.Model):
82
- title = models.CharField(max_length=200)
83
- created_at = models.DateTimeField(auto_now_add=True)
84
-
85
- class Meta:
86
- ordering = ['-created_at']
87
- verbose_name = 'article'
88
- verbose_name_plural = 'articles'
89
-
90
- def __str__(self):
91
- return self.title
92
55
 
93
56
  query_optimization:
94
57
  foreign_key: select_related() # Single SQL JOIN
@@ -107,18 +70,7 @@ indexing:
107
70
 
108
71
  constraints:
109
72
  use: Meta.constraints for database-level enforcement
110
- example: |
111
- class Meta:
112
- constraints = [
113
- models.UniqueConstraint(
114
- fields=['user', 'article'],
115
- name='unique_user_article'
116
- ),
117
- models.CheckConstraint(
118
- check=models.Q(price__gte=0),
119
- name='price_non_negative'
120
- )
121
- ]
73
+ types: "UniqueConstraint, CheckConstraint"
122
74
 
123
75
  soft_delete:
124
76
  pattern: is_active = models.BooleanField(default=True)
@@ -126,16 +78,10 @@ soft_delete:
126
78
 
127
79
  custom_managers:
128
80
  rule: Use managers for reusable querysets
129
- example: |
130
- class PublishedManager(models.Manager):
131
- def get_queryset(self):
132
- return super().get_queryset().filter(status='published')
133
-
134
- class Article(models.Model):
135
- objects = models.Manager() # Keep default
136
- published = PublishedManager() # Add custom
137
81
  ```
138
82
 
83
+ Reference: guides/django-best-practices/README.md
84
+
139
85
  ### 3. Views Best Practices
140
86
 
141
87
  ```yaml
@@ -145,15 +91,6 @@ cbv_vs_fbv:
145
91
 
146
92
  thin_views:
147
93
  rule: Keep views thin — delegate business logic to services/models
148
- wrong: |
149
- def create_order(request):
150
- # 50 lines of business logic in view
151
- correct: |
152
- def create_order(request):
153
- form = OrderForm(request.POST)
154
- if form.is_valid():
155
- order = order_service.create(request.user, form.cleaned_data)
156
- return redirect('order-detail', pk=order.pk)
157
94
 
158
95
  shortcuts:
159
96
  - get_object_or_404(Model, pk=pk): Returns 404 instead of 500
@@ -179,7 +116,7 @@ status_codes:
179
116
  ```yaml
180
117
  namespacing:
181
118
  app_name: Required in every app's urls.py
182
- usage: reverse('app_name:url_name') or {% url 'app_name:url_name' %}
119
+ usage: "reverse('app_name:url_name') or {% url 'app_name:url_name' %}"
183
120
 
184
121
  syntax:
185
122
  prefer: path() over re_path() for clarity
@@ -187,56 +124,29 @@ syntax:
187
124
 
188
125
  naming:
189
126
  rule: Name ALL URL patterns
190
- convention: "{resource}-{action}" (e.g., article-list, article-detail)
127
+ convention: "{resource}-{action} (e.g., article-list, article-detail)"
191
128
 
192
129
  inclusion:
193
130
  root_urls: Use include() for app-level URLs
194
- example: |
195
- # config/urls.py
196
- urlpatterns = [
197
- path('admin/', admin.site.urls),
198
- path('api/', include('apps.api.urls', namespace='api')),
199
- path('articles/', include('apps.articles.urls', namespace='articles')),
200
- ]
201
-
202
- # apps/articles/urls.py
203
- app_name = 'articles'
204
- urlpatterns = [
205
- path('', ArticleListView.as_view(), name='list'),
206
- path('<int:pk>/', ArticleDetailView.as_view(), name='detail'),
207
- ]
208
131
  ```
209
132
 
133
+ Reference: guides/django-best-practices/README.md
134
+
210
135
  ### 5. Forms & Validation
211
136
 
212
137
  ```yaml
213
138
  model_forms:
214
139
  rule: Use ModelForm when form maps to a model
215
- fields: Explicitly list fields (never use fields = '__all__')
140
+ fields: "Explicitly list fields (never use fields = '__all__')"
216
141
 
217
142
  validation:
218
143
  field_level: clean_<field>() method
219
144
  cross_field: clean() method
220
145
  built_in: Use Django validators (MaxValueValidator, RegexValidator, etc.)
221
-
222
- example: |
223
- class ArticleForm(forms.ModelForm):
224
- class Meta:
225
- model = Article
226
- fields = ['title', 'body', 'status']
227
-
228
- def clean_title(self):
229
- title = self.cleaned_data['title']
230
- if len(title) < 5:
231
- raise forms.ValidationError('Title too short.')
232
- return title
233
-
234
- def clean(self):
235
- cleaned = super().clean()
236
- # Cross-field validation here
237
- return cleaned
238
146
  ```
239
147
 
148
+ Reference: guides/django-best-practices/README.md
149
+
240
150
  ### 6. Security
241
151
 
242
152
  ```yaml
@@ -287,22 +197,13 @@ test_classes:
287
197
  test_data:
288
198
  preferred: factory_boy or model_bakery
289
199
  avoid: fixtures (hard to maintain, slow)
290
- example: |
291
- import factory
292
- from apps.users.models import User
293
-
294
- class UserFactory(factory.django.DjangoModelFactory):
295
- class Meta:
296
- model = User
297
- username = factory.Sequence(lambda n: f'user{n}')
298
- email = factory.LazyAttribute(lambda o: f'{o.username}@example.com')
299
200
 
300
201
  request_testing:
301
202
  Client: Full request/response cycle (preferred for views)
302
203
  RequestFactory: Faster, no middleware (for unit testing views)
303
204
 
304
205
  settings_override:
305
- decorator: '@override_settings(EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend")'
206
+ decorator: '@override_settings(...)'
306
207
 
307
208
  coverage:
308
209
  target: 80%+
@@ -312,6 +213,8 @@ structure:
312
213
  mirror_app: tests/test_models.py, tests/test_views.py, tests/test_forms.py
313
214
  ```
314
215
 
216
+ Reference: guides/django-best-practices/README.md
217
+
315
218
  ### 8. Performance
316
219
 
317
220
  ```yaml
@@ -322,15 +225,15 @@ n_plus_1_prevention:
322
225
  complex: Prefetch object with custom queryset
323
226
 
324
227
  partial_loading:
325
- only: only('id', 'title', 'created_at') # Load only these fields
326
- defer: defer('body', 'metadata') # Load all except these
327
- values: values('id', 'title') # Returns dicts (no ORM overhead)
328
- values_list: values_list('id', flat=True) # Returns flat list
228
+ only: "only('id', 'title', 'created_at') Load only these fields"
229
+ defer: "defer('body', 'metadata') Load all except these"
230
+ values: "values('id', 'title') Returns dicts (no ORM overhead)"
231
+ values_list: "values_list('id', flat=True) Returns flat list"
329
232
 
330
233
  caching:
331
234
  backend: Redis (preferred), Memcached
332
- view_cache: '@cache_page(60 * 15)' decorator
333
- template_cache: '{% cache 500 sidebar %}' template tag
235
+ view_cache: "'@cache_page(60 * 15)' decorator"
236
+ template_cache: "'{% cache 500 sidebar %}' template tag"
334
237
  low_level: cache.get/set/delete for fine-grained control
335
238
 
336
239
  pagination:
@@ -339,8 +242,8 @@ pagination:
339
242
  drf: PageNumberPagination or CursorPagination
340
243
 
341
244
  bulk_operations:
342
- create: Article.objects.bulk_create(articles, batch_size=1000)
343
- update: Article.objects.bulk_update(articles, ['status'], batch_size=1000)
245
+ create: "bulk_create(articles, batch_size=1000)"
246
+ update: "bulk_update(articles, ['status'], batch_size=1000)"
344
247
  avoid: Loops calling .save() on many objects
345
248
  ```
346
249
 
@@ -351,17 +254,6 @@ serializers:
351
254
  standard_crud: ModelSerializer
352
255
  read_only: Use SerializerMethodField for computed values
353
256
  write_validation: validate_<field>() and validate() methods
354
- example: |
355
- class ArticleSerializer(serializers.ModelSerializer):
356
- author_name = serializers.SerializerMethodField()
357
-
358
- class Meta:
359
- model = Article
360
- fields = ['id', 'title', 'body', 'author_name', 'created_at']
361
- read_only_fields = ['id', 'created_at']
362
-
363
- def get_author_name(self, obj):
364
- return obj.author.get_full_name()
365
257
 
366
258
  viewsets:
367
259
  standard: ModelViewSet for full CRUD
@@ -380,7 +272,6 @@ permissions:
380
272
 
381
273
  versioning:
382
274
  method: NamespaceVersioning or URLPathVersioning
383
- example: "/api/v1/articles/" vs "/api/v2/articles/"
384
275
 
385
276
  throttling:
386
277
  anonymous: AnonRateThrottle
@@ -392,6 +283,8 @@ pagination:
392
283
  types: PageNumberPagination (simple), CursorPagination (large datasets)
393
284
  ```
394
285
 
286
+ Reference: guides/django-best-practices/README.md
287
+
395
288
  ### 10. Deployment
396
289
 
397
290
  ```yaml
@@ -46,15 +46,7 @@ state_choice:
46
46
 
47
47
  build_context:
48
48
  rule: "Never store BuildContext across async gaps"
49
- pattern: |
50
- // BAD
51
- final ctx = context;
52
- await Future.delayed(Duration(seconds: 1));
53
- Navigator.of(ctx).push(...); // context may be invalid
54
-
55
- // GOOD
56
- if (!mounted) return;
57
- Navigator.of(context).push(...);
49
+ pattern: "Check mounted before using context after await"
58
50
 
59
51
  keys:
60
52
  ValueKey: "When items have unique business identity"
@@ -83,6 +75,8 @@ slivers:
83
75
  avoid: "Nested ListView in ListView"
84
76
  ```
85
77
 
78
+ Reference: guides/flutter/fundamentals.md
79
+
86
80
  ### 2. State Management
87
81
 
88
82
  ```yaml
@@ -99,51 +93,26 @@ riverpod_patterns:
99
93
  async_state: "AsyncNotifier + AsyncValue (loading/data/error)"
100
94
  family: "family modifier for parameterized providers"
101
95
  keep_alive: "Only when justified (expensive computations)"
102
- invalidate_vs_refresh: |
103
- ref.invalidate(provider) // reset to loading, lazy re-fetch
104
- ref.refresh(provider) // immediate re-fetch, return new value
96
+ invalidate_vs_refresh: "ref.invalidate() resets to loading (lazy); ref.refresh() immediate re-fetch"
105
97
 
106
98
  bloc_patterns:
107
99
  one_event_per_action: "One UI action = one event class"
108
- cubit_vs_bloc: |
109
- Cubit: direct emit(state) — for simple state changes
110
- Bloc: event → state mapping — when audit trail needed
100
+ cubit_vs_bloc: "Cubit for simple state changes; Bloc when audit trail needed"
111
101
  never: "Emit state in constructor body"
112
- listener_vs_consumer: |
113
- BlocListener: side effects (navigation, snackbar)
114
- BlocConsumer: rebuild UI + side effects
115
- BlocBuilder: rebuild UI only (most common)
102
+ listener_vs_consumer: "BlocListener for side effects; BlocConsumer for UI + effects; BlocBuilder for UI only"
116
103
  stream_management: "Cancel subscriptions in close()"
117
104
 
118
105
  state_immutability:
119
106
  rule: "All state objects must be immutable"
120
107
  tool: "freezed package for copyWith/==/hashCode generation"
121
- pattern: |
122
- @freezed
123
- class UserState with _$UserState {
124
- const factory UserState({
125
- required String name,
126
- required int age,
127
- @Default(false) bool isLoading,
128
- }) = _UserState;
129
- }
130
108
 
131
109
  result_type:
132
110
  rule: "Return Result<T> from repositories, never throw"
133
- pattern: |
134
- sealed class Result<T> {
135
- const Result();
136
- }
137
- final class Ok<T> extends Result<T> {
138
- const Ok(this.value);
139
- final T value;
140
- }
141
- final class Error<T> extends Result<T> {
142
- const Error(this.error);
143
- final Exception error;
144
- }
111
+ pattern: "sealed class Result<T> with Ok<T> and Error<T> subclasses"
145
112
  ```
146
113
 
114
+ Reference: guides/flutter/state-management.md
115
+
147
116
  ### 3. Performance
148
117
 
149
118
  ```yaml
@@ -151,16 +120,7 @@ build_optimization:
151
120
  const_widgets: "Mark immutable widgets const — zero rebuild"
152
121
  localize_setState: "Call setState on smallest possible subtree"
153
122
  extract_widgets: "StatelessWidget class > helper method"
154
- child_parameter: |
155
- // GOOD: static child passed through
156
- AnimatedBuilder(
157
- animation: controller,
158
- builder: (context, child) => Transform.rotate(
159
- angle: controller.value,
160
- child: child, // not rebuilt
161
- ),
162
- child: const ExpensiveWidget(), // built once
163
- )
123
+ child_parameter: "Pass static child through AnimatedBuilder to avoid rebuild"
164
124
 
165
125
  rebuild_avoidance:
166
126
  consumer_placement: "Place Consumer/ListenableBuilder as deep as possible"
@@ -183,6 +143,8 @@ frame_budget:
183
143
  tool: "DevTools Performance view for jank detection"
184
144
  ```
185
145
 
146
+ Reference: guides/flutter/performance.md
147
+
186
148
  ### 4. Testing
187
149
 
188
150
  ```yaml
@@ -192,36 +154,16 @@ test_pyramid:
192
154
  integration: "Full app on device — slow, high confidence"
193
155
  golden: "Visual regression via matchesGoldenFile()"
194
156
 
195
- widget_test_pattern: |
196
- testWidgets('shows loading then content', (tester) async {
197
- await tester.pumpWidget(
198
- ProviderScope(
199
- overrides: [productsProvider.overrideWith((_) => fakeProducts)],
200
- child: const MaterialApp(home: ProductListScreen()),
201
- ),
202
- );
203
- expect(find.byType(CircularProgressIndicator), findsOneWidget);
204
- await tester.pumpAndSettle();
205
- expect(find.byType(ProductCard), findsNWidgets(3));
206
- });
157
+ widget_test_pattern:
158
+ rule: "Use pumpWidget with ProviderScope overrides, then pump/pumpAndSettle for async"
207
159
 
208
160
  mocking:
209
161
  prefer: "mocktail (null-safe, no codegen)"
210
162
  avoid: "Legacy mockito with build_runner"
211
163
  fakes: "Use Fake implementations for deterministic tests"
212
- pattern: |
213
- class FakeProductRepository extends Fake implements ProductRepository {
214
- @override
215
- Future<Result<List<Product>>> getAll() async => Ok(testProducts);
216
- }
217
-
218
- bloc_testing: |
219
- blocTest<AuthBloc, AuthState>(
220
- 'emits [loading, success] when login succeeds',
221
- build: () => AuthBloc(FakeAuthRepository()),
222
- act: (bloc) => bloc.add(LoginRequested('user', 'pass')),
223
- expect: () => [AuthLoading(), isA<AuthSuccess>()],
224
- );
164
+
165
+ bloc_testing:
166
+ rule: "Use blocTest<Bloc, State> with build/act/expect pattern"
225
167
 
226
168
  coverage_target:
227
169
  widget_tests: "80%+ for UI logic"
@@ -229,6 +171,8 @@ coverage_target:
229
171
  integration: "Critical user flows only"
230
172
  ```
231
173
 
174
+ Reference: guides/flutter/testing.md
175
+
232
176
  ### 5. Security
233
177
 
234
178
  ```yaml
@@ -236,14 +180,14 @@ secrets:
236
180
  never: "Hardcode API keys, tokens, or credentials in source"
237
181
  best: "Backend proxy for all sensitive API calls"
238
182
  use: "--dart-define-from-file=.env for NON-SECRET build config only (feature flags, environment URLs)"
239
- warning: "dart-define values are embedded in compiled binary and extractable via static analysis. Use only for non-secret build configuration (feature flags, environment URLs)."
183
+ warning: "dart-define values are embedded in compiled binary and extractable via static analysis"
240
184
 
241
185
  storage:
242
186
  sensitive_data: "flutter_secure_storage v10+ (Keychain/Keystore)"
243
187
  never: "SharedPreferences for tokens, PII, or credentials"
244
188
  ios: "AppleOptions(useSecureEnclave: true) for high-value"
245
189
  android: "AndroidOptions(encryptedSharedPreferences: true)"
246
- web_warning: "flutter_secure_storage on Web uses localStorage by default, which is accessible to any JavaScript on the page (XSS vulnerable). For Web targets, use HttpOnly cookies managed by backend or in-memory-only storage for sensitive data."
190
+ web_warning: "flutter_secure_storage on Web uses localStorage by default (XSS vulnerable). Use HttpOnly cookies or in-memory-only for sensitive data."
247
191
 
248
192
  network:
249
193
  tls: "Certificate pinning (SPKI) for financial/health apps"
@@ -267,54 +211,35 @@ logging:
267
211
  never: "Log PII, tokens, or credentials"
268
212
  ```
269
213
 
214
+ Reference: guides/flutter/security.md
215
+
270
216
  ### 6. Dart Language Patterns
271
217
 
272
218
  ```yaml
273
219
  naming:
274
- types: "UpperCamelCase for classes, enums, typedefs, extensions, mixins (e.g., HttpClient, JsonParser)"
275
- variables: "lowerCamelCase for variables, parameters, named constants (e.g., itemCount, defaultTimeout)"
276
- libraries: "lowercase_with_underscores for libraries, packages, directories, source files (e.g., my_package, slider_menu.dart)"
277
- constants: "lowerCamelCase for const (e.g., const defaultTimeout = 30), NOT SCREAMING_CAPS"
278
- private: "Prefix with underscore for library-private (e.g., _internalCache, _helper())"
279
- boolean: "Prefix with is/has/can/should for booleans (e.g., isEnabled, hasData, canScroll)"
280
- avoid: "Hungarian notation, type prefixes (strName, lstItems), abbreviations unless universally known (e.g., ok: http, url, id; avoid: mgr, ctx, btn)"
220
+ types: "UpperCamelCase for classes, enums, typedefs, extensions, mixins"
221
+ variables: "lowerCamelCase for variables, parameters, named constants"
222
+ libraries: "lowercase_with_underscores for libraries, packages, directories, source files"
223
+ constants: "lowerCamelCase for const (NOT SCREAMING_CAPS)"
224
+ private: "Prefix with underscore for library-private"
225
+ boolean: "Prefix with is/has/can/should"
226
+ avoid: "Hungarian notation, type prefixes, abbreviations unless universally known"
281
227
 
282
228
  null_safety:
283
229
  default: "Non-nullable types — use ? only when null is meaningful"
284
230
  avoid_bang: "Minimize ! operator — use only when null is logically impossible"
285
231
  late: "Only when initialization is guaranteed before use"
286
- pattern: |
287
- // GOOD
288
- final name = user?.name ?? 'Anonymous';
289
-
290
- // AVOID
291
- final name = user!.name; // crashes if null
292
232
 
293
233
  sealed_classes:
294
234
  use_for: "Exhaustive pattern matching on state/result types"
295
- pattern: |
296
- sealed class AuthState {}
297
- class AuthInitial extends AuthState {}
298
- class AuthLoading extends AuthState {}
299
- class AuthSuccess extends AuthState { final User user; AuthSuccess(this.user); }
300
- class AuthError extends AuthState { final String message; AuthError(this.message); }
301
-
302
- // Exhaustive switch — compiler enforces all cases
303
- return switch (state) {
304
- AuthInitial() => LoginScreen(),
305
- AuthLoading() => CircularProgressIndicator(),
306
- AuthSuccess(:final user) => HomeScreen(user: user),
307
- AuthError(:final message) => ErrorWidget(message),
308
- };
235
+ pattern: "sealed class with subclass per state, exhaustive switch expression"
309
236
 
310
237
  records:
311
238
  use_for: "Lightweight multi-value returns without class boilerplate"
312
- pattern: "(String name, int age) getUserInfo() => ('Alice', 30);"
313
239
  avoid: "Records for complex data — use freezed classes instead"
314
240
 
315
241
  extension_types:
316
242
  use_for: "Zero-cost type wrappers for primitive IDs"
317
- pattern: "extension type UserId(int id) implements int {}"
318
243
 
319
244
  immutability:
320
245
  prefer: "final variables, const constructors"
@@ -331,48 +256,19 @@ dynamic:
331
256
  reason: "No compile-time type checking, reduces IDE support"
332
257
  ```
333
258
 
259
+ Reference: guides/flutter/fundamentals.md
260
+
334
261
  ### 7. Architecture & Project Structure
335
262
 
336
263
  ```yaml
337
264
  default_structure:
338
- small_app: |
339
- lib/
340
- models/
341
- services/
342
- screens/
343
- widgets/
344
- medium_app: |
345
- lib/
346
- ui/
347
- core/themes/, core/widgets/
348
- <feature>/<feature>_screen.dart
349
- <feature>/<feature>_viewmodel.dart
350
- data/
351
- repositories/<entity>_repository.dart
352
- services/<source>_service.dart
353
- domain/ (optional)
354
- use_cases/
355
- large_app: |
356
- lib/
357
- core/ (shared)
358
- features/<feature>/
359
- data/datasources/, data/repositories/
360
- domain/entities/, domain/usecases/
361
- presentation/bloc/, presentation/pages/
265
+ small_app: "lib/{models,services,screens,widgets}/"
266
+ medium_app: "lib/{ui/{core/,<feature>/},data/{repositories/,services/},domain/}"
267
+ large_app: "lib/{core/,features/<feature>/{data/,domain/,presentation/}}"
362
268
 
363
269
  navigation:
364
270
  default: "go_router (official recommendation)"
365
- pattern: |
366
- GoRoute(
367
- path: '/product/:id',
368
- builder: (context, state) {
369
- final id = state.pathParameters['id']!;
370
- return ProductDetailScreen(id: id);
371
- },
372
- )
373
- go_vs_push: |
374
- context.go('/path') // replaces stack (navigation reset)
375
- context.push('/path') // adds to stack (back button works)
271
+ go_vs_push: "context.go() replaces stack; context.push() adds to stack"
376
272
 
377
273
  dependency_injection:
378
274
  riverpod: "Built-in — providers as DI (default)"
@@ -381,13 +277,12 @@ dependency_injection:
381
277
 
382
278
  environments:
383
279
  pattern: "Flavors + --dart-define for multi-environment builds"
384
- command: "flutter run --flavor development --target lib/main/main_development.dart"
385
280
  rule: "Separate bundle IDs, API URLs, and Firebase config per flavor"
386
281
  ```
387
282
 
388
- ## Default Stack
283
+ Reference: guides/flutter/architecture.md
389
284
 
390
- When starting a new Flutter project, recommend this stack:
285
+ ## Default Stack
391
286
 
392
287
  ```yaml
393
288
  state_management: Riverpod 3.0
@@ -402,8 +297,6 @@ structure: Official MVVM (lib/{ui,data}/)
402
297
 
403
298
  ## Enterprise Stack
404
299
 
405
- For regulated or large-team projects:
406
-
407
300
  ```yaml
408
301
  state_management: BLoC 9.0 + Cubit
409
302
  navigation: go_router or auto_route