ginskill-init 1.0.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 (92) hide show
  1. package/README.md +77 -0
  2. package/agents/developer.md +56 -0
  3. package/agents/frontend-design.md +69 -0
  4. package/agents/mobile-reviewer.md +36 -0
  5. package/agents/review-code.md +49 -0
  6. package/agents/security-scanner.md +50 -0
  7. package/agents/tester.md +72 -0
  8. package/bin/cli.js +226 -0
  9. package/package.json +20 -0
  10. package/skills/ai-asset-generator/SKILL.md +255 -0
  11. package/skills/ai-asset-generator/docs/gen-image.md +274 -0
  12. package/skills/ai-asset-generator/docs/genvideo.md +341 -0
  13. package/skills/ai-asset-generator/docs/remove-background.md +19 -0
  14. package/skills/ai-asset-generator/generate-credit-assets.mjs +180 -0
  15. package/skills/ai-asset-generator/generate-ginbrowser-assets.mjs +242 -0
  16. package/skills/ai-asset-generator/generate-sty-icon.mjs +149 -0
  17. package/skills/ai-asset-generator/lib/bg-remove.mjs +34 -0
  18. package/skills/ai-asset-generator/lib/env.mjs +38 -0
  19. package/skills/ai-asset-generator/lib/kie-client.mjs +88 -0
  20. package/skills/ai-asset-generator/scripts/scaffold-generator.mjs +203 -0
  21. package/skills/ai-build-ai/SKILL.md +124 -0
  22. package/skills/ai-build-ai/docs/agent-teams.md +293 -0
  23. package/skills/ai-build-ai/docs/checkpointing.md +161 -0
  24. package/skills/ai-build-ai/docs/create-agent.md +399 -0
  25. package/skills/ai-build-ai/docs/create-mcp.md +395 -0
  26. package/skills/ai-build-ai/docs/create-skill.md +299 -0
  27. package/skills/ai-build-ai/docs/headless-mode.md +614 -0
  28. package/skills/ai-build-ai/docs/hooks.md +578 -0
  29. package/skills/ai-build-ai/docs/memory-claude-md.md +375 -0
  30. package/skills/ai-build-ai/docs/output-styles.md +208 -0
  31. package/skills/ai-build-ai/docs/overview.md +162 -0
  32. package/skills/ai-build-ai/docs/permissions.md +391 -0
  33. package/skills/ai-build-ai/docs/plugins.md +396 -0
  34. package/skills/ai-build-ai/docs/sandbox.md +262 -0
  35. package/skills/ai-build-ai/scripts/load-tutorial.sh +54 -0
  36. package/skills/icon-generator/SKILL.md +270 -0
  37. package/skills/mobile-app-review/SKILL.md +321 -0
  38. package/skills/mobile-app-review/references/apple-review.md +132 -0
  39. package/skills/mobile-app-review/references/google-play-review.md +203 -0
  40. package/skills/mongodb/SKILL.md +667 -0
  41. package/skills/mongodb/references/mongoose-patterns.md +368 -0
  42. package/skills/nestjs-architecture/SKILL.md +1086 -0
  43. package/skills/nestjs-architecture/references/advanced-patterns.md +590 -0
  44. package/skills/performance/SKILL.md +509 -0
  45. package/skills/react-fsd-architecture/SKILL.md +693 -0
  46. package/skills/react-fsd-architecture/references/fsd-patterns.md +747 -0
  47. package/skills/react-query/SKILL.md +685 -0
  48. package/skills/react-query/references/query-patterns.md +365 -0
  49. package/skills/review-code/SKILL.md +321 -0
  50. package/skills/review-code/references/clean-code-principles.md +395 -0
  51. package/skills/review-code/references/frontend-patterns.md +136 -0
  52. package/skills/review-code/references/nestjs-patterns.md +184 -0
  53. package/skills/review-code/scripts/check-module.sh +201 -0
  54. package/skills/review-code/scripts/deep-scan.sh +604 -0
  55. package/skills/review-code/scripts/dep-check.sh +522 -0
  56. package/skills/review-code/scripts/detect-duplicates.sh +466 -0
  57. package/skills/review-code/scripts/format-check.sh +577 -0
  58. package/skills/review-code/scripts/run-review.sh +167 -0
  59. package/skills/review-code/scripts/scan-codebase.sh +152 -0
  60. package/skills/security-scanner/SKILL.md +327 -0
  61. package/skills/security-scanner/references/nestjs-security.md +260 -0
  62. package/skills/security-scanner/references/nextjs-security.md +201 -0
  63. package/skills/security-scanner/references/react-native-security.md +199 -0
  64. package/skills/security-scanner/scripts/security-scan.sh +478 -0
  65. package/skills/ui-ux-pro-max/SKILL.md +377 -0
  66. package/skills/ui-ux-pro-max/data/charts.csv +26 -0
  67. package/skills/ui-ux-pro-max/data/colors.csv +97 -0
  68. package/skills/ui-ux-pro-max/data/icons.csv +101 -0
  69. package/skills/ui-ux-pro-max/data/landing.csv +31 -0
  70. package/skills/ui-ux-pro-max/data/products.csv +97 -0
  71. package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  72. package/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  73. package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  74. package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  75. package/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  76. package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  77. package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  78. package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  79. package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  80. package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  81. package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  82. package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  83. package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  84. package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  85. package/skills/ui-ux-pro-max/data/styles.csv +68 -0
  86. package/skills/ui-ux-pro-max/data/typography.csv +58 -0
  87. package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  88. package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  89. package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  90. package/skills/ui-ux-pro-max/scripts/core.py +253 -0
  91. package/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  92. package/skills/ui-ux-pro-max/scripts/search.py +114 -0
@@ -0,0 +1,395 @@
1
+ # Clean Code Principles — Review Reference
2
+
3
+ Practical guide for reviewing code against clean code, SOLID, and design principles. All examples use TypeScript in a NestJS/Next.js context.
4
+
5
+ ## Table of Contents
6
+ 1. [SOLID Principles](#solid-principles)
7
+ 2. [DRY, KISS, YAGNI](#dry-kiss-yagni)
8
+ 3. [Code Smells Catalog](#code-smells-catalog)
9
+ 4. [Anti-Patterns](#anti-patterns)
10
+ 5. [Refactoring Recipes](#refactoring-recipes)
11
+
12
+ ---
13
+
14
+ ## SOLID Principles
15
+
16
+ ### S — Single Responsibility Principle (SRP)
17
+
18
+ **Rule:** A class should have only one reason to change.
19
+
20
+ Bad — service does too much:
21
+ ```typescript
22
+ @Injectable()
23
+ export class OrderService {
24
+ async createOrder(dto: CreateOrderDto, user: User) { /* ... */ }
25
+ async sendOrderEmail(order: Order) { /* ... */ } // ← email is not order logic
26
+ async generateInvoicePdf(order: Order) { /* ... */ } // ← PDF generation is not order logic
27
+ async syncToAnalytics(order: Order) { /* ... */ } // ← analytics is not order logic
28
+ }
29
+ ```
30
+
31
+ Good — each class has one job:
32
+ ```typescript
33
+ @Injectable()
34
+ export class OrderService {
35
+ constructor(
36
+ private readonly emailService: EmailService,
37
+ private readonly invoiceService: InvoiceService,
38
+ private readonly eventEmitter: EventEmitter2,
39
+ ) {}
40
+
41
+ async createOrder(dto: CreateOrderDto, user: User) {
42
+ const order = await this.orderModel.create({ ...dto, userId: user._id });
43
+ this.eventEmitter.emit('order.created', order); // Other services react to events
44
+ return order;
45
+ }
46
+ }
47
+ ```
48
+
49
+ **Review checklist:**
50
+ - Service has >10 public methods → likely violates SRP, split by domain concern
51
+ - Service injects >5 dependencies → may be doing too much
52
+ - Controller has business logic beyond validation + delegation → move to service
53
+ - A change in one feature requires editing this class → it has multiple responsibilities
54
+
55
+ ### O — Open/Closed Principle (OCP)
56
+
57
+ **Rule:** Open for extension, closed for modification.
58
+
59
+ Bad — modifying existing code for each new case:
60
+ ```typescript
61
+ @Injectable()
62
+ export class NotificationService {
63
+ async send(type: string, data: any) {
64
+ if (type === 'email') { /* send email */ }
65
+ else if (type === 'sms') { /* send SMS */ }
66
+ else if (type === 'push') { /* send push */ }
67
+ // Adding Slack? Must modify this class.
68
+ }
69
+ }
70
+ ```
71
+
72
+ Good — extend through new implementations:
73
+ ```typescript
74
+ interface NotificationChannel {
75
+ send(data: NotificationPayload): Promise<void>;
76
+ }
77
+
78
+ @Injectable()
79
+ export class EmailChannel implements NotificationChannel { /* ... */ }
80
+ @Injectable()
81
+ export class SmsChannel implements NotificationChannel { /* ... */ }
82
+ @Injectable()
83
+ export class SlackChannel implements NotificationChannel { /* ... */ }
84
+
85
+ @Injectable()
86
+ export class NotificationService {
87
+ constructor(
88
+ @Inject('NOTIFICATION_CHANNELS') private channels: NotificationChannel[],
89
+ ) {}
90
+
91
+ async send(channelType: string, data: NotificationPayload) {
92
+ const channel = this.channels.find(c => c.type === channelType);
93
+ await channel.send(data);
94
+ }
95
+ }
96
+ ```
97
+
98
+ **Review checklist:**
99
+ - Growing if/else or switch chains for variants → use strategy/registry pattern
100
+ - Adding a new feature type requires editing existing service → violates OCP
101
+ - Configuration-driven behavior is hardcoded → extract to config or plugins
102
+
103
+ ### L — Liskov Substitution Principle (LSP)
104
+
105
+ **Rule:** Subtypes must be substitutable for their base types without breaking behavior.
106
+
107
+ Bad — subclass changes expected behavior:
108
+ ```typescript
109
+ class ReadOnlyRepository<T> {
110
+ async findById(id: string): Promise<T> { /* ... */ }
111
+ async save(entity: T): Promise<T> { throw new Error('Read only!'); } // ← breaks contract
112
+ }
113
+ ```
114
+
115
+ Good — separate interfaces for different capabilities:
116
+ ```typescript
117
+ interface Readable<T> {
118
+ findById(id: string): Promise<T>;
119
+ }
120
+ interface Writable<T> {
121
+ save(entity: T): Promise<T>;
122
+ }
123
+ interface Repository<T> extends Readable<T>, Writable<T> {}
124
+ ```
125
+
126
+ **Review checklist:**
127
+ - Overridden methods that throw "not supported" → violates LSP
128
+ - Subclasses that ignore or nullify parent behavior → redesign the hierarchy
129
+ - Type assertions needed after using a base type → polymorphism is broken
130
+
131
+ ### I — Interface Segregation Principle (ISP)
132
+
133
+ **Rule:** Don't force implementations to depend on methods they don't use.
134
+
135
+ Bad — fat interface:
136
+ ```typescript
137
+ interface UserService {
138
+ findById(id: string): Promise<User>;
139
+ createUser(dto: CreateUserDto): Promise<User>;
140
+ deleteUser(id: string): Promise<void>;
141
+ sendWelcomeEmail(user: User): Promise<void>; // ← not every consumer needs this
142
+ generateReport(userId: string): Promise<Buffer>; // ← not every consumer needs this
143
+ }
144
+ ```
145
+
146
+ Good — focused interfaces:
147
+ ```typescript
148
+ interface UserReader {
149
+ findById(id: string): Promise<User>;
150
+ }
151
+ interface UserWriter {
152
+ createUser(dto: CreateUserDto): Promise<User>;
153
+ deleteUser(id: string): Promise<void>;
154
+ }
155
+ ```
156
+
157
+ **Review checklist:**
158
+ - Interface has methods that some implementations leave empty → split it
159
+ - Classes implement interfaces where half the methods are no-ops → ISP violation
160
+ - Consumers import a service but only use 1-2 of its 10+ methods → interface is too broad
161
+
162
+ ### D — Dependency Inversion Principle (DIP)
163
+
164
+ **Rule:** Depend on abstractions, not concretions.
165
+
166
+ Bad — direct dependency on implementation:
167
+ ```typescript
168
+ @Injectable()
169
+ export class OrderService {
170
+ private stripe = new Stripe(process.env.STRIPE_KEY); // ← concrete dependency
171
+
172
+ async charge(amount: number) {
173
+ return this.stripe.charges.create({ amount });
174
+ }
175
+ }
176
+ ```
177
+
178
+ Good — depend on abstraction via NestJS DI:
179
+ ```typescript
180
+ interface PaymentProvider {
181
+ charge(amount: number, currency: string): Promise<PaymentResult>;
182
+ }
183
+
184
+ @Injectable()
185
+ export class StripeProvider implements PaymentProvider { /* ... */ }
186
+
187
+ @Injectable()
188
+ export class OrderService {
189
+ constructor(
190
+ @Inject('PAYMENT_PROVIDER') private paymentProvider: PaymentProvider,
191
+ ) {}
192
+
193
+ async charge(amount: number) {
194
+ return this.paymentProvider.charge(amount, 'usd');
195
+ }
196
+ }
197
+ ```
198
+
199
+ **Review checklist:**
200
+ - `new ExternalService()` inside business logic → inject it instead
201
+ - Direct SDK imports in services (aws-sdk, stripe, etc.) → wrap in abstraction
202
+ - High-level modules importing from low-level modules → invert the dependency
203
+
204
+ ---
205
+
206
+ ## DRY, KISS, YAGNI
207
+
208
+ ### DRY — Don't Repeat Yourself
209
+
210
+ **Rule:** Every piece of knowledge has a single, unambiguous representation.
211
+
212
+ Common DRY violations in our stack:
213
+
214
+ | Violation | Fix |
215
+ |---|---|
216
+ | Same validation logic in DTO and frontend Zod schema | Share validation via a common schema package or derive one from the other |
217
+ | Identical error handling in every controller method | Use NestJS exception filters |
218
+ | Copy-pasted Mongoose query patterns across services | Extract to a base repository or shared query builder |
219
+ | Same API response shape defined in multiple DTOs | Create a base DTO and extend |
220
+ | Repeated auth check logic | Use guards and decorators |
221
+
222
+ **But beware of wrong DRY:** Don't merge things that happen to look similar but serve different purposes. Two functions with identical code TODAY might evolve differently. Ask: "If one changes, must the other change too?" If no, they aren't true duplicates.
223
+
224
+ ### KISS — Keep It Simple, Stupid
225
+
226
+ **Rule:** The simplest solution that works correctly is the best solution.
227
+
228
+ Red flags for over-engineering:
229
+ - Abstract factory pattern for 2 variants → just use a simple if/else
230
+ - Generic base class with 5 type parameters used by 1 subclass → remove the generics
231
+ - Custom event bus when NestJS EventEmitter2 works fine
232
+ - Hand-rolled caching layer when `@nestjs/cache-manager` exists
233
+ - Complex class hierarchy when composition would be simpler
234
+
235
+ **Review question:** "Could a mid-level developer understand this code in 5 minutes?" If not, it might be too complex.
236
+
237
+ ### YAGNI — You Ain't Gonna Need It
238
+
239
+ **Rule:** Don't build it until you actually need it.
240
+
241
+ Red flags:
242
+ - Unused exported functions, types, or interfaces
243
+ - Configuration options that are never set to anything other than the default
244
+ - Abstract base classes with only one concrete implementation
245
+ - Plugin/extension architecture with zero plugins
246
+ - Feature flags for features that shipped months ago
247
+ - "Flexible" data structures that only store one type of data
248
+
249
+ ---
250
+
251
+ ## Code Smells Catalog
252
+
253
+ Quick-reference for the most common code smells in our stack:
254
+
255
+ ### Bloaters (too big)
256
+ | Smell | Threshold | Action |
257
+ |---|---|---|
258
+ | Long method | >30 lines | Extract methods by responsibility |
259
+ | Large class | >200 lines or >10 public methods | Split into focused classes |
260
+ | Long parameter list | >3 params | Use options object / DTO |
261
+ | Primitive obsession | Strings/numbers for domain concepts | Create value objects or enums |
262
+ | Data clumps | Same group of params passed together | Extract to a class/interface |
263
+
264
+ ### Object-Orientation Abusers
265
+ | Smell | Sign | Action |
266
+ |---|---|---|
267
+ | Switch/if chains on type | `if (type === 'A') ... else if (type === 'B')` | Use polymorphism or strategy pattern |
268
+ | Refused bequest | Subclass doesn't use inherited methods | Rethink hierarchy, prefer composition |
269
+ | Temporary field | Fields only set in some scenarios | Extract to separate class or use Optional |
270
+
271
+ ### Change Preventers
272
+ | Smell | Sign | Action |
273
+ |---|---|---|
274
+ | Divergent change | One class changed for many different reasons | Split by SRP |
275
+ | Shotgun surgery | One change touches many files | Consolidate related logic |
276
+ | Parallel inheritance | Adding a subclass requires adding sibling subclass | Merge hierarchies or use composition |
277
+
278
+ ### Dispensables (remove them)
279
+ | Smell | Sign | Action |
280
+ |---|---|---|
281
+ | Dead code | Unreachable or uncalled code | Delete it (git has history) |
282
+ | Speculative generality | Unused abstractions "for the future" | Delete until needed (YAGNI) |
283
+ | Duplicate code | Same logic in multiple places | Extract to shared utility |
284
+ | Lazy class | Class that does too little | Inline it into its caller |
285
+ | Comments explaining bad code | `// This increments i by 1` | Rewrite the code to be clear |
286
+
287
+ ### Couplers (too connected)
288
+ | Smell | Sign | Action |
289
+ |---|---|---|
290
+ | Feature envy | Method uses another class's data more than its own | Move method to that class |
291
+ | Inappropriate intimacy | Classes access each other's private details | Establish proper public interfaces |
292
+ | Message chains | `a.getB().getC().getD()` | Provide a direct method |
293
+ | Middle man | Class delegates everything without adding value | Remove and call directly |
294
+
295
+ ---
296
+
297
+ ## Anti-Patterns
298
+
299
+ ### Backend Anti-Patterns (NestJS)
300
+
301
+ **Fat Controller:**
302
+ ```typescript
303
+ // BAD: Controller with business logic
304
+ @Post()
305
+ async create(@Body() dto: CreateItemDto) {
306
+ const exists = await this.itemModel.findOne({ name: dto.name }); // ← DB access in controller
307
+ if (exists) throw new ConflictException();
308
+ const item = await this.itemModel.create(dto);
309
+ await this.emailService.send(item.userId, 'Item created'); // ← side effects in controller
310
+ return item;
311
+ }
312
+ ```
313
+
314
+ **Service Locator (anti-DI):**
315
+ ```typescript
316
+ // BAD: Fetching services manually instead of injecting
317
+ @Injectable()
318
+ export class OrderService {
319
+ async process(orderId: string) {
320
+ const emailService = this.moduleRef.get(EmailService); // ← defeats DI, untestable
321
+ await emailService.send(...);
322
+ }
323
+ }
324
+ ```
325
+
326
+ **Catch and Ignore:**
327
+ ```typescript
328
+ // BAD: Swallowing errors
329
+ try {
330
+ await this.paymentService.charge(order);
331
+ } catch (e) {
332
+ console.log(e); // ← error logged but not handled, order proceeds as if payment succeeded
333
+ }
334
+ ```
335
+
336
+ **Stringly Typed:**
337
+ ```typescript
338
+ // BAD: Using strings where enums/types belong
339
+ async updateStatus(id: string, status: string) { /* ... */ }
340
+ // GOOD:
341
+ async updateStatus(id: string, status: OrderStatus) { /* ... */ }
342
+ ```
343
+
344
+ ### Frontend Anti-Patterns (Next.js / React)
345
+
346
+ **Prop Drilling:**
347
+ ```typescript
348
+ // BAD: Passing props through 4+ levels of components
349
+ <App user={user}>
350
+ <Layout user={user}>
351
+ <Sidebar user={user}>
352
+ <UserAvatar user={user} /> // ← just use context or Zustand
353
+ ```
354
+
355
+ **useEffect for Everything:**
356
+ ```typescript
357
+ // BAD: Derived state in useEffect
358
+ const [fullName, setFullName] = useState('');
359
+ useEffect(() => {
360
+ setFullName(`${firstName} ${lastName}`); // ← just compute it
361
+ }, [firstName, lastName]);
362
+
363
+ // GOOD: Compute directly
364
+ const fullName = `${firstName} ${lastName}`;
365
+ ```
366
+
367
+ **God Component:**
368
+ ```typescript
369
+ // BAD: 500-line component with mixed concerns
370
+ export function Dashboard() {
371
+ // 20 state variables
372
+ // 10 useEffects
373
+ // 15 handler functions
374
+ // 300 lines of JSX
375
+ }
376
+ // GOOD: Split into focused components with custom hooks
377
+ ```
378
+
379
+ ---
380
+
381
+ ## Refactoring Recipes
382
+
383
+ Common refactoring patterns to suggest during reviews:
384
+
385
+ | Current Code | Refactoring | Result |
386
+ |---|---|---|
387
+ | Long method with comment sections | **Extract Method** | Small, named methods that self-document |
388
+ | Repeated if/else on type | **Replace Conditional with Polymorphism** | Strategy pattern or class hierarchy |
389
+ | Multiple params always passed together | **Introduce Parameter Object** | DTO or interface |
390
+ | Nested callbacks or promise chains | **Replace with async/await** | Flat, readable async code |
391
+ | Boolean method params | **Replace Parameter with Explicit Methods** | `publish()` and `saveDraft()` instead of `save(isPublished)` |
392
+ | Raw string/number domain values | **Replace Primitive with Value Object** | `OrderId`, `Money`, `Email` types |
393
+ | God service | **Extract Class** | Multiple focused services |
394
+ | Copy-paste with small variations | **Extract with Parameters** | Shared function with config |
395
+ | Manual resource cleanup | **Use try/finally or disposable** | Guaranteed cleanup |
@@ -0,0 +1,136 @@
1
+ # Frontend Patterns — Next.js Review Reference
2
+
3
+ Quick reference for reviewing Next.js frontend code.
4
+
5
+ ## Table of Contents
6
+ 1. [App Router Structure](#app-router-structure)
7
+ 2. [Component Patterns](#component-patterns)
8
+ 3. [State Management](#state-management)
9
+ 4. [Data Fetching](#data-fetching)
10
+ 5. [Form Handling](#form-handling)
11
+ 6. [Styling](#styling)
12
+
13
+ ---
14
+
15
+ ## App Router Structure
16
+
17
+ ```
18
+ src/app/
19
+ ├── api/ # Next.js API routes (server functions)
20
+ ├── (public)/ # Public pages (landing, marketing)
21
+ ├── (dashboard)/ # Authenticated pages
22
+ ├── layout.tsx # Root layout
23
+ └── page.tsx # Home page
24
+ ```
25
+
26
+ Review checklist:
27
+ - Route groups should have their own layouts
28
+ - Authenticated routes should check session in layout/middleware
29
+ - API routes should validate inputs and handle errors
30
+
31
+ ## Component Patterns
32
+
33
+ ```
34
+ src/
35
+ ├── shared/components/ # Reusable UI (buttons, modals, cards)
36
+ ├── features/ # Feature-specific components
37
+ ├── components/ # Global components (navbar, sidebar)
38
+ └── entities/ # Domain model components
39
+ ```
40
+
41
+ Review checklist:
42
+ - Use `"use client"` only where React hooks or browser APIs are needed
43
+ - Prefer server components for data fetching and static content
44
+ - Keep components focused — one component, one responsibility (SRP). If a component does too many things, split it
45
+ - Props should be typed with TypeScript interfaces, not `any`
46
+ - Components should be <150 lines of JSX. Split larger ones into sub-components
47
+ - Extract reusable logic into custom hooks (DRY) — if 2+ components share the same state/effect pattern, make a hook
48
+ - Prefer composition over prop drilling — use context, Zustand, or render props for deeply shared state
49
+ - Avoid `useEffect` for derived state — compute values directly or use `useMemo`
50
+ - Name components and hooks descriptively: `useItemFilters` not `useData`, `OrderSummaryCard` not `Card2`
51
+
52
+ ## State Management
53
+
54
+ **Zustand** for client-side state:
55
+ ```typescript
56
+ import { create } from 'zustand';
57
+
58
+ interface ItemStore {
59
+ items: Item[];
60
+ addItem: (item: Item) => void;
61
+ }
62
+
63
+ export const useItemStore = create<ItemStore>((set) => ({
64
+ items: [],
65
+ addItem: (item) => set((state) => ({ items: [...state.items, item] })),
66
+ }));
67
+ ```
68
+
69
+ Review checklist:
70
+ - Stores should be small and focused (one per domain) — SRP for state (ISP)
71
+ - Avoid god-stores that manage everything — split by feature/concern
72
+ - Use selectors to prevent unnecessary rerenders
73
+ - Don't duplicate server state in Zustand — that's what React Query is for (single source of truth / DRY)
74
+ - Keep store actions simple — complex business logic belongs in services, not stores
75
+ - Avoid derived state in stores — compute it in components or with selectors (KISS)
76
+
77
+ ## Data Fetching
78
+
79
+ **React Query** for server state:
80
+ ```typescript
81
+ import { useQuery } from '@tanstack/react-query';
82
+ import { itemService } from '@/shared/services';
83
+
84
+ function useItems() {
85
+ return useQuery({
86
+ queryKey: ['items'],
87
+ queryFn: () => itemService.getAll(),
88
+ });
89
+ }
90
+ ```
91
+
92
+ Review checklist:
93
+ - Query keys should follow a consistent namespace: `['items']`, `['items', id]`, `['items', { filter }]` — use query key factories (DRY)
94
+ - API calls should go through the service layer, not directly in components (separation of concerns)
95
+ - Handle loading, error, and empty states — never show a blank screen
96
+ - Use `useMutation` for writes, not manual state updates
97
+ - Invalidate relevant queries after mutations
98
+ - Extract query hooks into dedicated files (e.g., `useItems.ts`) — don't inline `useQuery` calls throughout components (DRY)
99
+ - Set appropriate `staleTime` / `gcTime` — don't refetch data that rarely changes on every mount (KISS)
100
+
101
+ ## Form Handling
102
+
103
+ **React Hook Form + Zod**:
104
+ ```typescript
105
+ const schema = z.object({
106
+ name: z.string().min(1, 'Required'),
107
+ category: z.enum(['tops', 'bottoms', 'shoes']),
108
+ });
109
+
110
+ type FormData = z.infer<typeof schema>;
111
+
112
+ function ItemForm() {
113
+ const { register, handleSubmit } = useForm<FormData>({
114
+ resolver: zodResolver(schema),
115
+ });
116
+ }
117
+ ```
118
+
119
+ Review checklist:
120
+ - Use Zod schemas for validation (matches backend DTOs)
121
+ - Derive TypeScript types from Zod schemas with `z.infer`
122
+ - Handle form submission errors and show to user
123
+ - Disable submit button during loading
124
+
125
+ ## Styling
126
+
127
+ **Tailwind CSS + shadcn/ui (Radix)**:
128
+
129
+ Review checklist:
130
+ - Use Tailwind utility classes, not custom CSS (unless truly necessary)
131
+ - shadcn/ui components should be used for standard UI elements — don't reinvent existing components (DRY)
132
+ - Responsive design: mobile-first (`sm:`, `md:`, `lg:` breakpoints)
133
+ - Dark mode: use `dark:` variants where appropriate
134
+ - Avoid inline styles
135
+ - Extract repeated class combinations into reusable components, not utility strings (KISS)
136
+ - Use design tokens / CSS variables for colors, spacing — don't hardcode hex values throughout (DRY, maintainability)