@codihaus/claude-skills 1.6.6 → 1.6.8
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.
- package/package.json +1 -1
- package/skills/debrief/SKILL.md +139 -421
- package/skills/dev-arch/SKILL.md +120 -403
- package/skills/dev-changelog/SKILL.md +67 -221
- package/skills/dev-coding/SKILL.md +170 -696
- package/skills/dev-coding/references/backend-principles.md +130 -0
- package/skills/dev-coding/references/frontend-principles.md +212 -0
- package/skills/dev-review/SKILL.md +63 -238
- package/skills/dev-scout/SKILL.md +140 -864
- package/skills/dev-scout/references/output-template.md +231 -0
- package/skills/dev-specs/SKILL.md +136 -586
- package/skills/dev-specs/references/spec-template.md +146 -0
- package/skills/dev-test/SKILL.md +79 -157
- package/src/utils/config.js +1 -1
- package/templates/scripts/safe-graph-update.sh +3 -1
- package/skills/dev-coding-backend/SKILL.md +0 -240
- package/skills/dev-coding-backend/references/fundamentals.md +0 -428
- package/skills/dev-coding-frontend/SKILL.md +0 -296
- package/skills/dev-coding-frontend/references/fundamentals.md +0 -577
- package/skills/dev-scout/references/feature-patterns.md +0 -210
- package/skills/dev-scout/references/file-patterns.md +0 -252
- package/skills/dev-scout/references/stack-patterns.md +0 -371
- package/skills/dev-scout/references/tech-detection.md +0 -211
- package/skills/dev-specs/references/checklist.md +0 -176
- package/skills/dev-specs/references/spec-templates.md +0 -460
|
@@ -1,428 +0,0 @@
|
|
|
1
|
-
# Backend Fundamentals
|
|
2
|
-
|
|
3
|
-
The principles and patterns that enable scalable, maintainable backend systems.
|
|
4
|
-
|
|
5
|
-
## Core Mindset
|
|
6
|
-
|
|
7
|
-
**"I am the guardian of truth. I trust nothing. I enforce rules. I must be reliable."**
|
|
8
|
-
|
|
9
|
-
The backend is the last line of defense. It:
|
|
10
|
-
- Protects data integrity
|
|
11
|
-
- Enforces business rules
|
|
12
|
-
- Handles failures gracefully
|
|
13
|
-
- Scales under load
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## The Principles
|
|
18
|
-
|
|
19
|
-
Principles are the fundamental laws. Patterns are solutions derived from them.
|
|
20
|
-
|
|
21
|
-
### 1. Separation of Concerns
|
|
22
|
-
|
|
23
|
-
**Law**: Each piece of code should have ONE responsibility.
|
|
24
|
-
|
|
25
|
-
**Why**: When things are mixed, changing one breaks another. Testing becomes impossible. New developers get lost.
|
|
26
|
-
|
|
27
|
-
**Patterns derived**:
|
|
28
|
-
|
|
29
|
-
| Pattern | What it Separates |
|
|
30
|
-
|---------|-------------------|
|
|
31
|
-
| Service Layer | Business logic FROM HTTP handling |
|
|
32
|
-
| Repository | Data access FROM business logic |
|
|
33
|
-
| Controller/Route | Request parsing FROM processing |
|
|
34
|
-
| Middleware | Cross-cutting concerns FROM main logic |
|
|
35
|
-
| Event-Driven | "What happened" FROM "What to do about it" |
|
|
36
|
-
|
|
37
|
-
**Recognition signals**:
|
|
38
|
-
- Function does more than one thing
|
|
39
|
-
- Can't test without real database/HTTP
|
|
40
|
-
- Changing one feature breaks another
|
|
41
|
-
- File is > 300 lines
|
|
42
|
-
|
|
43
|
-
**Structure example**:
|
|
44
|
-
```
|
|
45
|
-
# BAD: Mixed concerns
|
|
46
|
-
route('/orders', async (req) => {
|
|
47
|
-
validate(req.body) # validation
|
|
48
|
-
const user = await db.users.find(req.userId) # data access
|
|
49
|
-
if (user.balance < req.body.total) throw Error # business rule
|
|
50
|
-
await db.orders.create(...) # data access
|
|
51
|
-
await sendEmail(user.email) # side effect
|
|
52
|
-
return order
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
# GOOD: Separated concerns
|
|
56
|
-
route('/orders', OrderController.create)
|
|
57
|
-
|
|
58
|
-
OrderController.create(req) {
|
|
59
|
-
const dto = OrderValidator.validate(req.body) # validation layer
|
|
60
|
-
const order = await OrderService.create(dto, req.userId) # service layer
|
|
61
|
-
return OrderPresenter.format(order) # presentation layer
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
OrderService.create(dto, userId) {
|
|
65
|
-
const user = await UserRepository.findById(userId) # repository
|
|
66
|
-
OrderRules.validateCanOrder(user, dto) # business rules
|
|
67
|
-
const order = await OrderRepository.create(dto)
|
|
68
|
-
await EventBus.emit('order.created', order) # events for side effects
|
|
69
|
-
return order
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
---
|
|
74
|
-
|
|
75
|
-
### 2. Single Source of Truth
|
|
76
|
-
|
|
77
|
-
**Law**: Each piece of data or rule should exist in ONE place only.
|
|
78
|
-
|
|
79
|
-
**Why**: Duplicated data gets out of sync. Duplicated rules diverge over time.
|
|
80
|
-
|
|
81
|
-
**Patterns derived**:
|
|
82
|
-
|
|
83
|
-
| Pattern | What it Centralizes |
|
|
84
|
-
|---------|---------------------|
|
|
85
|
-
| Repository | All access to a data type |
|
|
86
|
-
| Domain Model | Business rules for an entity |
|
|
87
|
-
| Configuration | Environment-specific values |
|
|
88
|
-
| Constants/Enums | Magic values and statuses |
|
|
89
|
-
| Event Store | Historical record of changes |
|
|
90
|
-
|
|
91
|
-
**Recognition signals**:
|
|
92
|
-
- Same validation in multiple places
|
|
93
|
-
- Same query written twice
|
|
94
|
-
- Hardcoded values scattered around
|
|
95
|
-
- "Which one is correct?" questions
|
|
96
|
-
|
|
97
|
-
**Structure example**:
|
|
98
|
-
```
|
|
99
|
-
# BAD: Rules in multiple places
|
|
100
|
-
# In controller:
|
|
101
|
-
if (order.status !== 'pending') throw Error
|
|
102
|
-
|
|
103
|
-
# In service:
|
|
104
|
-
if (order.status !== 'pending') throw Error
|
|
105
|
-
|
|
106
|
-
# In another service:
|
|
107
|
-
if (order.status != 'pending' && order.status != 'draft') throw Error # diverged!
|
|
108
|
-
|
|
109
|
-
# GOOD: Single source
|
|
110
|
-
class Order {
|
|
111
|
-
canBeModified() {
|
|
112
|
-
return ['pending', 'draft'].includes(this.status)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
# Everywhere else:
|
|
117
|
-
if (!order.canBeModified()) throw Error
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
---
|
|
121
|
-
|
|
122
|
-
### 3. Don't Repeat Work
|
|
123
|
-
|
|
124
|
-
**Law**: If the same work is done repeatedly with the same result, do it once and remember.
|
|
125
|
-
|
|
126
|
-
**Why**: Wasted resources, slower response, higher costs, database overload.
|
|
127
|
-
|
|
128
|
-
**Patterns derived**:
|
|
129
|
-
|
|
130
|
-
| Pattern | What it Remembers |
|
|
131
|
-
|---------|-------------------|
|
|
132
|
-
| Caching (Redis/Memory) | Expensive query results |
|
|
133
|
-
| Memoization | Function computation |
|
|
134
|
-
| Database Indexes | Query paths |
|
|
135
|
-
| CDN | Static assets |
|
|
136
|
-
| Materialized Views | Pre-computed aggregations |
|
|
137
|
-
|
|
138
|
-
**Recognition signals**:
|
|
139
|
-
- Same query runs multiple times per request
|
|
140
|
-
- Same computation on same input
|
|
141
|
-
- Dashboard aggregations are slow
|
|
142
|
-
- Database CPU is high
|
|
143
|
-
|
|
144
|
-
**Decision guide**:
|
|
145
|
-
```
|
|
146
|
-
How often does data change?
|
|
147
|
-
├── Never (static) → CDN, aggressive cache
|
|
148
|
-
├── Rarely (config) → Long TTL cache (hours)
|
|
149
|
-
├── Sometimes (user profile) → Medium TTL (minutes)
|
|
150
|
-
├── Often (feed) → Short TTL (seconds) or real-time
|
|
151
|
-
└── Always (balance) → No cache, or cache with invalidation
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
---
|
|
155
|
-
|
|
156
|
-
### 4. Don't Make Users Wait
|
|
157
|
-
|
|
158
|
-
**Law**: If something takes long and user doesn't need immediate result, do it later.
|
|
159
|
-
|
|
160
|
-
**Why**: Users leave, connections timeout, server resources blocked.
|
|
161
|
-
|
|
162
|
-
**Patterns derived**:
|
|
163
|
-
|
|
164
|
-
| Pattern | Use When |
|
|
165
|
-
|---------|----------|
|
|
166
|
-
| Message Queue | Task takes > 1-2 seconds |
|
|
167
|
-
| Background Jobs | Scheduled or deferred work |
|
|
168
|
-
| Webhooks | Notify instead of poll |
|
|
169
|
-
| Streaming | Large data transfer |
|
|
170
|
-
| Pagination | Large result sets |
|
|
171
|
-
|
|
172
|
-
**Recognition signals**:
|
|
173
|
-
- API timeout errors
|
|
174
|
-
- User waits > 3 seconds
|
|
175
|
-
- Sending emails in request
|
|
176
|
-
- Processing files in request
|
|
177
|
-
- Generating reports in request
|
|
178
|
-
|
|
179
|
-
**Structure example**:
|
|
180
|
-
```
|
|
181
|
-
# BAD: User waits for everything
|
|
182
|
-
route('/orders', async (req) => {
|
|
183
|
-
const order = await createOrder(req.body)
|
|
184
|
-
await generateInvoicePDF(order) # 3 seconds
|
|
185
|
-
await sendEmail(order) # 2 seconds
|
|
186
|
-
await notifyWarehouse(order) # 1 second
|
|
187
|
-
await updateAnalytics(order) # 500ms
|
|
188
|
-
return order # User waited 6.5 seconds!
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
# GOOD: Return fast, process later
|
|
192
|
-
route('/orders', async (req) => {
|
|
193
|
-
const order = await createOrder(req.body)
|
|
194
|
-
await queue.add('order.process', { orderId: order.id })
|
|
195
|
-
return order # User waited 200ms
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
# Background worker handles the rest
|
|
199
|
-
worker.process('order.process', async (job) => {
|
|
200
|
-
const order = await OrderRepository.find(job.orderId)
|
|
201
|
-
await generateInvoicePDF(order)
|
|
202
|
-
await sendEmail(order)
|
|
203
|
-
await notifyWarehouse(order)
|
|
204
|
-
await updateAnalytics(order)
|
|
205
|
-
})
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
---
|
|
209
|
-
|
|
210
|
-
### 5. Don't Trust Anyone
|
|
211
|
-
|
|
212
|
-
**Law**: Every input is potentially malicious or malformed. Validate at boundaries.
|
|
213
|
-
|
|
214
|
-
**Why**: Security breaches, data corruption, system crashes.
|
|
215
|
-
|
|
216
|
-
**Patterns derived**:
|
|
217
|
-
|
|
218
|
-
| Pattern | What it Protects |
|
|
219
|
-
|---------|------------------|
|
|
220
|
-
| Input Validation | Data integrity |
|
|
221
|
-
| Authentication | Identity verification |
|
|
222
|
-
| Authorization | Access control |
|
|
223
|
-
| Rate Limiting | Resource protection |
|
|
224
|
-
| Sanitization | Injection prevention |
|
|
225
|
-
|
|
226
|
-
**Recognition signals**:
|
|
227
|
-
- User input used directly in queries
|
|
228
|
-
- No authentication on endpoints
|
|
229
|
-
- Missing role checks
|
|
230
|
-
- No request size limits
|
|
231
|
-
- Error messages expose internals
|
|
232
|
-
|
|
233
|
-
**Validation layers**:
|
|
234
|
-
```
|
|
235
|
-
Request arrives
|
|
236
|
-
↓
|
|
237
|
-
[1. Rate Limit] → Too many? Reject 429
|
|
238
|
-
↓
|
|
239
|
-
[2. Authentication] → Who is this? Reject 401 if unknown
|
|
240
|
-
↓
|
|
241
|
-
[3. Authorization] → Can they do this? Reject 403 if not
|
|
242
|
-
↓
|
|
243
|
-
[4. Input Validation] → Is data valid? Reject 400 if not
|
|
244
|
-
↓
|
|
245
|
-
[5. Business Rules] → Is action allowed? Reject 422 if not
|
|
246
|
-
↓
|
|
247
|
-
Process request
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
---
|
|
251
|
-
|
|
252
|
-
### 6. Plan for Failure
|
|
253
|
-
|
|
254
|
-
**Law**: Everything will fail eventually. Design for it.
|
|
255
|
-
|
|
256
|
-
**Why**: Network fails, services go down, databases crash, disks fill up.
|
|
257
|
-
|
|
258
|
-
**Patterns derived**:
|
|
259
|
-
|
|
260
|
-
| Pattern | Failure it Handles |
|
|
261
|
-
|---------|-------------------|
|
|
262
|
-
| Circuit Breaker | External service down |
|
|
263
|
-
| Retry with Backoff | Temporary failures |
|
|
264
|
-
| Timeout | Hung connections |
|
|
265
|
-
| Fallback | Degraded operation |
|
|
266
|
-
| Dead Letter Queue | Unprocessable messages |
|
|
267
|
-
| Idempotency | Duplicate requests |
|
|
268
|
-
|
|
269
|
-
**Recognition signals**:
|
|
270
|
-
- No try/catch around external calls
|
|
271
|
-
- No timeout on HTTP requests
|
|
272
|
-
- Retrying without backoff (hammering)
|
|
273
|
-
- No fallback when service unavailable
|
|
274
|
-
- Duplicate orders when user clicks twice
|
|
275
|
-
|
|
276
|
-
**Structure example**:
|
|
277
|
-
```
|
|
278
|
-
# BAD: Assumes success
|
|
279
|
-
const payment = await paymentService.charge(order)
|
|
280
|
-
|
|
281
|
-
# GOOD: Plans for failure
|
|
282
|
-
const payment = await circuitBreaker.call(
|
|
283
|
-
() => paymentService.charge(order),
|
|
284
|
-
{
|
|
285
|
-
timeout: 5000,
|
|
286
|
-
retry: { attempts: 3, backoff: 'exponential' },
|
|
287
|
-
fallback: () => {
|
|
288
|
-
queue.add('payment.retry', { orderId: order.id })
|
|
289
|
-
return { status: 'pending', message: 'Processing...' }
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
)
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
**Idempotency example**:
|
|
296
|
-
```
|
|
297
|
-
# Problem: User clicks "Pay" twice, charged twice
|
|
298
|
-
|
|
299
|
-
# Solution: Idempotency key
|
|
300
|
-
route('/payments', async (req) => {
|
|
301
|
-
const existingPayment = await PaymentRepository.findByIdempotencyKey(
|
|
302
|
-
req.headers['idempotency-key']
|
|
303
|
-
)
|
|
304
|
-
|
|
305
|
-
if (existingPayment) {
|
|
306
|
-
return existingPayment # Return same result, don't process again
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const payment = await processPayment(req.body)
|
|
310
|
-
payment.idempotencyKey = req.headers['idempotency-key']
|
|
311
|
-
await PaymentRepository.save(payment)
|
|
312
|
-
return payment
|
|
313
|
-
})
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
---
|
|
317
|
-
|
|
318
|
-
### 7. Stateless Design
|
|
319
|
-
|
|
320
|
-
**Law**: Server should not remember anything between requests (store state externally).
|
|
321
|
-
|
|
322
|
-
**Why**: Enables horizontal scaling, survives server restarts, simplifies deployment.
|
|
323
|
-
|
|
324
|
-
**Patterns derived**:
|
|
325
|
-
|
|
326
|
-
| Pattern | State it Externalizes |
|
|
327
|
-
|---------|----------------------|
|
|
328
|
-
| JWT Tokens | Session data in token |
|
|
329
|
-
| External Session Store | Session data in Redis |
|
|
330
|
-
| Database | All persistent data |
|
|
331
|
-
| Shared Cache | Computed/temporary data |
|
|
332
|
-
| Object Storage | Files and uploads |
|
|
333
|
-
|
|
334
|
-
**Recognition signals**:
|
|
335
|
-
- Using server memory for sessions
|
|
336
|
-
- Files stored on local disk
|
|
337
|
-
- In-memory caches that miss after deploy
|
|
338
|
-
- "Works on one server, fails with two"
|
|
339
|
-
|
|
340
|
-
**Structure example**:
|
|
341
|
-
```
|
|
342
|
-
# BAD: Stateful (breaks with multiple servers)
|
|
343
|
-
const sessions = {} # In memory!
|
|
344
|
-
app.post('/login', (req) => {
|
|
345
|
-
sessions[userId] = { user, timestamp }
|
|
346
|
-
})
|
|
347
|
-
app.get('/me', (req) => {
|
|
348
|
-
return sessions[req.userId] # Other server doesn't have this!
|
|
349
|
-
})
|
|
350
|
-
|
|
351
|
-
# GOOD: Stateless (works with any number of servers)
|
|
352
|
-
app.post('/login', async (req) => {
|
|
353
|
-
const token = jwt.sign({ userId, role }) # State in token
|
|
354
|
-
await redis.set(`session:${userId}`, { lastLogin }) # State in Redis
|
|
355
|
-
return { token }
|
|
356
|
-
})
|
|
357
|
-
app.get('/me', async (req) => {
|
|
358
|
-
const payload = jwt.verify(req.token) # State from token
|
|
359
|
-
const session = await redis.get(`session:${payload.userId}`) # State from Redis
|
|
360
|
-
return { user: payload, session }
|
|
361
|
-
})
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
---
|
|
365
|
-
|
|
366
|
-
## Pattern Decision Matrix
|
|
367
|
-
|
|
368
|
-
Quick reference for choosing patterns:
|
|
369
|
-
|
|
370
|
-
| Situation | Apply These Patterns |
|
|
371
|
-
|-----------|---------------------|
|
|
372
|
-
| Code is getting messy, hard to test | Service Layer + Repository + DI |
|
|
373
|
-
| Same logic in multiple places | Extract to Domain Model or Service |
|
|
374
|
-
| API is slow | Caching, Queue, Pagination |
|
|
375
|
-
| High database load | Caching, Indexing, Read Replicas |
|
|
376
|
-
| External service unreliable | Circuit Breaker, Retry, Fallback |
|
|
377
|
-
| Need audit trail | Event Sourcing or Audit Log |
|
|
378
|
-
| Complex workflows | Saga, State Machine |
|
|
379
|
-
| Many services communicating | Event Bus, API Gateway |
|
|
380
|
-
| Users hitting API too hard | Rate Limiting, Throttling |
|
|
381
|
-
| File uploads | Object Storage, Signed URLs |
|
|
382
|
-
|
|
383
|
-
---
|
|
384
|
-
|
|
385
|
-
## Architecture Layers
|
|
386
|
-
|
|
387
|
-
Standard backend structure:
|
|
388
|
-
|
|
389
|
-
```
|
|
390
|
-
┌─────────────────────────────────────────────┐
|
|
391
|
-
│ HTTP Layer (Routes/Controllers) │
|
|
392
|
-
│ - Parse request │
|
|
393
|
-
│ - Call service │
|
|
394
|
-
│ - Format response │
|
|
395
|
-
├─────────────────────────────────────────────┤
|
|
396
|
-
│ Service Layer │
|
|
397
|
-
│ - Business logic │
|
|
398
|
-
│ - Orchestrate operations │
|
|
399
|
-
│ - Emit events │
|
|
400
|
-
├─────────────────────────────────────────────┤
|
|
401
|
-
│ Domain Layer (Models/Entities) │
|
|
402
|
-
│ - Business rules │
|
|
403
|
-
│ - Validation │
|
|
404
|
-
│ - State transitions │
|
|
405
|
-
├─────────────────────────────────────────────┤
|
|
406
|
-
│ Repository Layer │
|
|
407
|
-
│ - Data access │
|
|
408
|
-
│ - Query building │
|
|
409
|
-
│ - Caching │
|
|
410
|
-
├─────────────────────────────────────────────┤
|
|
411
|
-
│ Infrastructure (Database, Queue, Cache) │
|
|
412
|
-
└─────────────────────────────────────────────┘
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
**Rule**: Upper layers can call lower layers. Never the reverse.
|
|
416
|
-
|
|
417
|
-
---
|
|
418
|
-
|
|
419
|
-
## Checklist Before Implementation
|
|
420
|
-
|
|
421
|
-
- [ ] Which principle applies to this feature?
|
|
422
|
-
- [ ] What patterns does that principle suggest?
|
|
423
|
-
- [ ] Is there existing similar code to follow?
|
|
424
|
-
- [ ] Where does validation happen?
|
|
425
|
-
- [ ] What if this fails?
|
|
426
|
-
- [ ] What if 1000 users do this at once?
|
|
427
|
-
- [ ] Does this need to be synchronous?
|
|
428
|
-
- [ ] What state needs to be stored?
|
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: dev-coding-frontend
|
|
3
|
-
description: Frontend implementation patterns and workflows
|
|
4
|
-
version: 2.1.0
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# /dev-coding-frontend - Frontend Implementation
|
|
8
|
-
|
|
9
|
-
> **Loaded by**: `/dev-coding` when UI work needed
|
|
10
|
-
> **Tools**: shadcn MCP, Playwright, Context7
|
|
11
|
-
> **Before**: Backend API contract should be documented
|
|
12
|
-
|
|
13
|
-
Frontend-specific workflow for UI components, pages, and client-side logic.
|
|
14
|
-
|
|
15
|
-
## Fundamentals (MUST READ FIRST)
|
|
16
|
-
|
|
17
|
-
**Before implementing, understand the principles:**
|
|
18
|
-
|
|
19
|
-
→ Read `references/fundamentals.md`
|
|
20
|
-
|
|
21
|
-
This covers:
|
|
22
|
-
- **Core Mindset**: "Communicator with humans - clear, responsive, consistent"
|
|
23
|
-
- **6 Principles**: Always Communicate, Feel Instant, Stay Consistent, Work for Everyone, Single Source of Truth, Minimize Complexity
|
|
24
|
-
- **Pattern Recognition**: When to use Loading States, Optimistic UI, State Management, Lazy Loading, etc.
|
|
25
|
-
- **UI States**: Every component must handle loading, error, empty, success
|
|
26
|
-
|
|
27
|
-
**Key Decision**: For each piece of code, ask "which principle applies?" Then choose the pattern that principle suggests.
|
|
28
|
-
|
|
29
|
-
**CRITICAL - Consistency**: Before writing ANY code, check existing codebase for naming conventions, file structure, component patterns, and styling approach. Match them exactly.
|
|
30
|
-
|
|
31
|
-
## Knowledge Loading (CRITICAL)
|
|
32
|
-
|
|
33
|
-
Before implementing, load relevant knowledge:
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
1. Read stack.md → plans/scout/stack.md
|
|
37
|
-
→ Identify: Framework, UI library, state management
|
|
38
|
-
|
|
39
|
-
2. Load stack knowledge based on detected tech:
|
|
40
|
-
| If using... | Read... | Section |
|
|
41
|
-
|--------------|-----------------------------------|-------------------|
|
|
42
|
-
| Nuxt.js | knowledge/stacks/nuxt/_index.md | "For /dev-coding" |
|
|
43
|
-
| Next.js | knowledge/stacks/nextjs/_index.md | "For /dev-coding" |
|
|
44
|
-
| Directus | knowledge/stacks/directus/_index.md | "SDK Integration" |
|
|
45
|
-
|
|
46
|
-
3. Load domain knowledge (if applicable):
|
|
47
|
-
| If domain... | Read... | Section |
|
|
48
|
-
|--------------|-----------------------------------|-------------------|
|
|
49
|
-
| SaaS | knowledge/domains/saas/_index.md | UI patterns |
|
|
50
|
-
| E-commerce | knowledge/domains/ecommerce/_index.md | Checkout flows |
|
|
51
|
-
|
|
52
|
-
4. Use loaded knowledge for:
|
|
53
|
-
→ Correct data fetching (useFetch vs useEffect vs Server Component)
|
|
54
|
-
→ Framework-specific patterns (composables vs hooks)
|
|
55
|
-
→ Domain-specific UI flows
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Workflow
|
|
59
|
-
|
|
60
|
-
### Step 1: Extract Frontend Requirements
|
|
61
|
-
|
|
62
|
-
From UC spec, identify:
|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
[ ] Pages/Routes?
|
|
66
|
-
→ Path, layout, auth required?
|
|
67
|
-
|
|
68
|
-
[ ] Components?
|
|
69
|
-
→ New, modify existing, shared vs feature-specific
|
|
70
|
-
|
|
71
|
-
[ ] State management?
|
|
72
|
-
→ Local, global, server state
|
|
73
|
-
|
|
74
|
-
[ ] Forms?
|
|
75
|
-
→ Fields, validation, submit handling
|
|
76
|
-
|
|
77
|
-
[ ] API integration?
|
|
78
|
-
→ Endpoints, loading/error states
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Step 2: Review API Contract
|
|
82
|
-
|
|
83
|
-
From backend implementation:
|
|
84
|
-
|
|
85
|
-
```markdown
|
|
86
|
-
### POST /api/auth/login
|
|
87
|
-
- Request: `{ email, password }`
|
|
88
|
-
- Response: `{ token, user }`
|
|
89
|
-
- Errors: 400 (validation), 401 (credentials)
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Match component shapes to API.
|
|
93
|
-
|
|
94
|
-
### Step 3: Component Architecture
|
|
95
|
-
|
|
96
|
-
**Order:** Base components → Feature components → Pages
|
|
97
|
-
|
|
98
|
-
```
|
|
99
|
-
src/
|
|
100
|
-
├── components/
|
|
101
|
-
│ ├── ui/ # Shared (Button, Input)
|
|
102
|
-
│ └── features/
|
|
103
|
-
│ └── auth/ # Feature-specific (LoginForm)
|
|
104
|
-
├── app/ (or pages/)
|
|
105
|
-
│ └── login/page.tsx
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
**Follow project conventions** from scout.
|
|
109
|
-
|
|
110
|
-
### Step 4: Build Components
|
|
111
|
-
|
|
112
|
-
Essential component pattern:
|
|
113
|
-
|
|
114
|
-
```tsx
|
|
115
|
-
interface Props {
|
|
116
|
-
onSuccess?: (data: Data) => void;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function FeatureForm({ onSuccess }: Props) {
|
|
120
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
121
|
-
const [error, setError] = useState<string | null>(null);
|
|
122
|
-
|
|
123
|
-
const handleSubmit = async (e: FormEvent) => {
|
|
124
|
-
e.preventDefault();
|
|
125
|
-
setIsLoading(true);
|
|
126
|
-
setError(null);
|
|
127
|
-
|
|
128
|
-
try {
|
|
129
|
-
const result = await apiCall(formData);
|
|
130
|
-
onSuccess?.(result);
|
|
131
|
-
} catch (err) {
|
|
132
|
-
setError(err.message);
|
|
133
|
-
} finally {
|
|
134
|
-
setIsLoading(false);
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
return (
|
|
139
|
-
<form onSubmit={handleSubmit}>
|
|
140
|
-
{error && <Alert variant="error">{error}</Alert>}
|
|
141
|
-
{/* Form fields */}
|
|
142
|
-
<Button type="submit" disabled={isLoading}>
|
|
143
|
-
{isLoading ? 'Loading...' : 'Submit'}
|
|
144
|
-
</Button>
|
|
145
|
-
</form>
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### Step 5: Handle States
|
|
151
|
-
|
|
152
|
-
```tsx
|
|
153
|
-
// Loading
|
|
154
|
-
{isLoading && <Spinner />}
|
|
155
|
-
|
|
156
|
-
// Error
|
|
157
|
-
{error && <Alert variant="error">{error}</Alert>}
|
|
158
|
-
|
|
159
|
-
// Empty
|
|
160
|
-
{items.length === 0 && <EmptyState />}
|
|
161
|
-
|
|
162
|
-
// Success
|
|
163
|
-
{items.map(item => <Card key={item.id} {...item} />)}
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Step 6: Verify
|
|
167
|
-
|
|
168
|
-
Quick sanity check before `/dev-test`:
|
|
169
|
-
|
|
170
|
-
```typescript
|
|
171
|
-
// Visual snapshot
|
|
172
|
-
await mcp__playwright__browser_navigate({ url: 'http://localhost:3000/page' });
|
|
173
|
-
await mcp__playwright__browser_snapshot({});
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
```
|
|
177
|
-
[ ] Page renders without console errors
|
|
178
|
-
[ ] Components display correctly
|
|
179
|
-
[ ] Forms accept input
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
## Essential Checklists
|
|
183
|
-
|
|
184
|
-
### Accessibility
|
|
185
|
-
```
|
|
186
|
-
[ ] Images have alt text
|
|
187
|
-
[ ] Form inputs have labels
|
|
188
|
-
[ ] Buttons have accessible names
|
|
189
|
-
[ ] Keyboard navigation works
|
|
190
|
-
[ ] Focus states visible
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
### Responsive
|
|
194
|
-
```
|
|
195
|
-
[ ] Mobile (< 768px)
|
|
196
|
-
[ ] Tablet (768px - 1024px)
|
|
197
|
-
[ ] Desktop (> 1024px)
|
|
198
|
-
[ ] Touch targets 44px minimum
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
## Quick Debugging
|
|
202
|
-
|
|
203
|
-
```bash
|
|
204
|
-
# Console errors → Browser DevTools
|
|
205
|
-
# Network failures → Network tab, check CORS
|
|
206
|
-
# Styling issues → Elements panel, check classes
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
```typescript
|
|
210
|
-
// Playwright debugging
|
|
211
|
-
await mcp__playwright__browser_console_messages({ level: 'error' });
|
|
212
|
-
await mcp__playwright__browser_network_requests({});
|
|
213
|
-
await mcp__playwright__browser_take_screenshot({ filename: 'debug.png' });
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
## Stack-Specific Patterns
|
|
217
|
-
|
|
218
|
-
**Do not implement generic patterns. Load from stacks/:**
|
|
219
|
-
|
|
220
|
-
| Stack | What to load | Key patterns |
|
|
221
|
-
|-------|--------------|--------------|
|
|
222
|
-
| Nuxt.js | `stacks/nuxt/` | Composables, useFetch, SSR |
|
|
223
|
-
| Next.js | `stacks/nextjs/` | Server Components, Actions |
|
|
224
|
-
| Vue | `stacks/vue/` (future) | Composition API, reactivity |
|
|
225
|
-
| React | `stacks/react/` (future) | Hooks, state patterns |
|
|
226
|
-
|
|
227
|
-
**Example - if using Nuxt:**
|
|
228
|
-
```
|
|
229
|
-
1. Read knowledge/stacks/nuxt/_index.md
|
|
230
|
-
2. Use useFetch (not raw fetch)
|
|
231
|
-
3. Use composables pattern
|
|
232
|
-
4. Handle SSR hydration
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
## Domain-Specific UI
|
|
236
|
-
|
|
237
|
-
**Load from domains/ when applicable:**
|
|
238
|
-
|
|
239
|
-
| Domain | What to load | Key patterns |
|
|
240
|
-
|--------|--------------|--------------|
|
|
241
|
-
| SaaS | `domains/saas/_index.md` | Pricing tables, subscription UI |
|
|
242
|
-
| E-commerce | `domains/ecommerce/_index.md` | Cart, checkout, product cards |
|
|
243
|
-
|
|
244
|
-
## Tools
|
|
245
|
-
|
|
246
|
-
### shadcn/ui Components
|
|
247
|
-
|
|
248
|
-
```
|
|
249
|
-
# List components
|
|
250
|
-
mcp__shadcn__list_components
|
|
251
|
-
|
|
252
|
-
# Get component source
|
|
253
|
-
mcp__shadcn__get_component("button")
|
|
254
|
-
|
|
255
|
-
# Get usage demo
|
|
256
|
-
mcp__shadcn__get_component_demo("form")
|
|
257
|
-
|
|
258
|
-
# Get pre-built blocks
|
|
259
|
-
mcp__shadcn__list_blocks
|
|
260
|
-
mcp__shadcn__get_block("login-01")
|
|
261
|
-
mcp__shadcn__get_block("dashboard-01")
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
**Workflow:**
|
|
265
|
-
1. Check if project uses shadcn (look for `components.json`)
|
|
266
|
-
2. List available components
|
|
267
|
-
3. Get demos for patterns
|
|
268
|
-
4. Adapt to project's API
|
|
269
|
-
|
|
270
|
-
### Playwright (Visual Verification)
|
|
271
|
-
|
|
272
|
-
```
|
|
273
|
-
mcp__playwright__browser_navigate({ url })
|
|
274
|
-
mcp__playwright__browser_snapshot({})
|
|
275
|
-
mcp__playwright__browser_take_screenshot({ filename })
|
|
276
|
-
mcp__playwright__browser_console_messages({ level: "error" })
|
|
277
|
-
mcp__playwright__browser_network_requests({})
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
### Context7 (Documentation)
|
|
281
|
-
|
|
282
|
-
```typescript
|
|
283
|
-
// Find library
|
|
284
|
-
mcp__context7__resolve-library-id({
|
|
285
|
-
libraryName: "react-hook-form",
|
|
286
|
-
query: "form validation"
|
|
287
|
-
})
|
|
288
|
-
|
|
289
|
-
// Query docs
|
|
290
|
-
mcp__context7__query-docs({
|
|
291
|
-
libraryId: "/react-hook-form/react-hook-form",
|
|
292
|
-
query: "validate email field"
|
|
293
|
-
})
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
Use for: Framework patterns, library APIs, CSS framework docs.
|