@codihaus/claude-skills 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 (46) hide show
  1. package/README.md +167 -0
  2. package/bin/cli.js +58 -0
  3. package/package.json +46 -0
  4. package/skills/_quality-attributes.md +392 -0
  5. package/skills/_registry.md +189 -0
  6. package/skills/debrief/SKILL.md +647 -0
  7. package/skills/debrief/references/change-request-template.md +124 -0
  8. package/skills/debrief/references/file-patterns.md +173 -0
  9. package/skills/debrief/references/group-codes.md +72 -0
  10. package/skills/debrief/references/research-queries.md +106 -0
  11. package/skills/debrief/references/use-case-template.md +141 -0
  12. package/skills/debrief/scripts/generate_questionnaire.py +195 -0
  13. package/skills/dev-arch/SKILL.md +747 -0
  14. package/skills/dev-changelog/SKILL.md +378 -0
  15. package/skills/dev-coding/SKILL.md +470 -0
  16. package/skills/dev-coding-backend/SKILL.md +361 -0
  17. package/skills/dev-coding-frontend/SKILL.md +534 -0
  18. package/skills/dev-coding-frontend/references/nextjs.md +477 -0
  19. package/skills/dev-review/SKILL.md +548 -0
  20. package/skills/dev-scout/SKILL.md +723 -0
  21. package/skills/dev-scout/references/feature-patterns.md +210 -0
  22. package/skills/dev-scout/references/file-patterns.md +252 -0
  23. package/skills/dev-scout/references/tech-detection.md +211 -0
  24. package/skills/dev-scout/scripts/scout-analyze.sh +280 -0
  25. package/skills/dev-specs/SKILL.md +577 -0
  26. package/skills/dev-specs/references/checklist.md +176 -0
  27. package/skills/dev-specs/references/spec-templates.md +460 -0
  28. package/skills/dev-test/SKILL.md +364 -0
  29. package/skills/utils/diagram/SKILL.md +205 -0
  30. package/skills/utils/diagram/references/common-errors.md +305 -0
  31. package/skills/utils/diagram/references/diagram-types.md +636 -0
  32. package/skills/utils/docs-graph/SKILL.md +204 -0
  33. package/skills/utils/gemini/SKILL.md +292 -0
  34. package/skills/utils/gemini/scripts/gemini-scan.py +340 -0
  35. package/skills/utils/gemini/scripts/setup.sh +169 -0
  36. package/src/commands/add.js +64 -0
  37. package/src/commands/doctor.js +179 -0
  38. package/src/commands/init.js +251 -0
  39. package/src/commands/list.js +88 -0
  40. package/src/commands/remove.js +60 -0
  41. package/src/commands/update.js +72 -0
  42. package/src/index.js +26 -0
  43. package/src/utils/config.js +272 -0
  44. package/src/utils/deps.js +599 -0
  45. package/src/utils/skills.js +253 -0
  46. package/templates/CLAUDE.md.template +58 -0
@@ -0,0 +1,477 @@
1
+ # Next.js Best Practices
2
+
3
+ Performance optimization patterns for Next.js App Router applications.
4
+
5
+ ## Rule Categories by Priority
6
+
7
+ | Priority | Category | Impact |
8
+ |----------|----------|--------|
9
+ | 1 | Eliminating Waterfalls | CRITICAL |
10
+ | 2 | Bundle Optimization | CRITICAL |
11
+ | 3 | Server Components | HIGH |
12
+ | 4 | Client Components | MEDIUM-HIGH |
13
+ | 5 | Re-render Optimization | MEDIUM |
14
+
15
+ ---
16
+
17
+ ## 1. Eliminating Waterfalls (CRITICAL)
18
+
19
+ ### Parallel Data Fetching
20
+
21
+ **Bad (sequential, 3 round trips):**
22
+ ```typescript
23
+ const user = await fetchUser()
24
+ const posts = await fetchPosts()
25
+ const comments = await fetchComments()
26
+ ```
27
+
28
+ **Good (parallel, 1 round trip):**
29
+ ```typescript
30
+ const [user, posts, comments] = await Promise.all([
31
+ fetchUser(),
32
+ fetchPosts(),
33
+ fetchComments()
34
+ ])
35
+ ```
36
+
37
+ ### Move Await Into Branches
38
+
39
+ **Bad (always waits):**
40
+ ```typescript
41
+ async function getUser(id: string, options?: { includeProfile: boolean }) {
42
+ const user = await db.user.findUnique({ where: { id } })
43
+ const profile = await db.profile.findUnique({ where: { userId: id } })
44
+
45
+ if (options?.includeProfile) {
46
+ return { ...user, profile }
47
+ }
48
+ return user
49
+ }
50
+ ```
51
+
52
+ **Good (only waits when needed):**
53
+ ```typescript
54
+ async function getUser(id: string, options?: { includeProfile: boolean }) {
55
+ const user = await db.user.findUnique({ where: { id } })
56
+
57
+ if (options?.includeProfile) {
58
+ const profile = await db.profile.findUnique({ where: { userId: id } })
59
+ return { ...user, profile }
60
+ }
61
+ return user
62
+ }
63
+ ```
64
+
65
+ ### Use Suspense Boundaries
66
+
67
+ ```tsx
68
+ // Stream content as it loads
69
+ export default function Page() {
70
+ return (
71
+ <div>
72
+ <Header />
73
+ <Suspense fallback={<PostsSkeleton />}>
74
+ <Posts />
75
+ </Suspense>
76
+ <Suspense fallback={<CommentsSkeleton />}>
77
+ <Comments />
78
+ </Suspense>
79
+ </div>
80
+ )
81
+ }
82
+ ```
83
+
84
+ ---
85
+
86
+ ## 2. Bundle Optimization (CRITICAL)
87
+
88
+ ### Avoid Barrel File Imports
89
+
90
+ Barrel files (index.js re-exports) load thousands of unused modules.
91
+
92
+ **Bad (imports entire library):**
93
+ ```tsx
94
+ import { Check, X, Menu } from 'lucide-react'
95
+ // Loads 1,583 modules, 200-800ms runtime cost
96
+ ```
97
+
98
+ **Good (direct imports):**
99
+ ```tsx
100
+ import Check from 'lucide-react/dist/esm/icons/check'
101
+ import X from 'lucide-react/dist/esm/icons/x'
102
+ ```
103
+
104
+ **Alternative (Next.js 13.5+):**
105
+ ```js
106
+ // next.config.js
107
+ module.exports = {
108
+ experimental: {
109
+ optimizePackageImports: ['lucide-react', '@mui/material']
110
+ }
111
+ }
112
+ ```
113
+
114
+ ### Dynamic Imports for Heavy Components
115
+
116
+ ```tsx
117
+ import dynamic from 'next/dynamic'
118
+
119
+ // Only load when needed
120
+ const HeavyChart = dynamic(() => import('@/components/Chart'), {
121
+ loading: () => <ChartSkeleton />,
122
+ ssr: false // If client-only
123
+ })
124
+ ```
125
+
126
+ ### Defer Third-Party Scripts
127
+
128
+ ```tsx
129
+ // Load after hydration
130
+ useEffect(() => {
131
+ import('analytics').then(({ init }) => init())
132
+ }, [])
133
+
134
+ // Or use next/script
135
+ <Script src="analytics.js" strategy="afterInteractive" />
136
+ ```
137
+
138
+ ---
139
+
140
+ ## 3. Server Components (HIGH)
141
+
142
+ ### Default to Server Components
143
+
144
+ ```tsx
145
+ // app/posts/page.tsx - Server Component (default)
146
+ export default async function PostsPage() {
147
+ const posts = await getPosts() // Direct DB access
148
+ return <PostList posts={posts} />
149
+ }
150
+ ```
151
+
152
+ ### Use React.cache() for Deduplication
153
+
154
+ ```typescript
155
+ import { cache } from 'react'
156
+
157
+ export const getCurrentUser = cache(async () => {
158
+ const session = await auth()
159
+ if (!session?.user?.id) return null
160
+ return await db.user.findUnique({
161
+ where: { id: session.user.id }
162
+ })
163
+ })
164
+
165
+ // Multiple components can call getCurrentUser()
166
+ // Only runs once per request
167
+ ```
168
+
169
+ **Important:** Use primitives as arguments, not objects:
170
+
171
+ ```typescript
172
+ // Bad - always cache miss (new object each call)
173
+ const getUser = cache(async (params: { uid: number }) => {...})
174
+
175
+ // Good - cache hit on same value
176
+ const getUser = cache(async (uid: number) => {...})
177
+ ```
178
+
179
+ ### Minimize Client Component Data
180
+
181
+ ```tsx
182
+ // Bad - sends entire user object to client
183
+ <ClientComponent user={user} />
184
+
185
+ // Good - send only needed fields
186
+ <ClientComponent userName={user.name} userAvatar={user.avatar} />
187
+ ```
188
+
189
+ ### Parallel Server Fetching
190
+
191
+ ```tsx
192
+ // Bad - sequential in parent
193
+ async function Page() {
194
+ const user = await getUser()
195
+ const posts = await getPosts()
196
+ return <Content user={user} posts={posts} />
197
+ }
198
+
199
+ // Good - parallel in children
200
+ async function Page() {
201
+ return (
202
+ <>
203
+ <UserSection /> {/* fetches user */}
204
+ <PostsSection /> {/* fetches posts in parallel */}
205
+ </>
206
+ )
207
+ }
208
+ ```
209
+
210
+ ---
211
+
212
+ ## 4. Client Components (MEDIUM-HIGH)
213
+
214
+ ### Mark Client Components Explicitly
215
+
216
+ ```tsx
217
+ 'use client'
218
+
219
+ import { useState } from 'react'
220
+
221
+ export function Counter() {
222
+ const [count, setCount] = useState(0)
223
+ return <button onClick={() => setCount(c => c + 1)}>{count}</button>
224
+ }
225
+ ```
226
+
227
+ ### Use SWR for Client Data Fetching
228
+
229
+ ```tsx
230
+ 'use client'
231
+
232
+ import useSWR from 'swr'
233
+
234
+ export function UserProfile({ userId }: { userId: string }) {
235
+ const { data, error, isLoading } = useSWR(
236
+ `/api/users/${userId}`,
237
+ fetcher
238
+ )
239
+
240
+ if (isLoading) return <Skeleton />
241
+ if (error) return <Error message={error.message} />
242
+ return <Profile user={data} />
243
+ }
244
+ ```
245
+
246
+ ### Deduplicate Event Listeners
247
+
248
+ ```tsx
249
+ // Bad - each component adds listener
250
+ function Component() {
251
+ useEffect(() => {
252
+ window.addEventListener('resize', handleResize)
253
+ return () => window.removeEventListener('resize', handleResize)
254
+ }, [])
255
+ }
256
+
257
+ // Good - shared hook with single listener
258
+ const useWindowSize = create(() => {
259
+ // Single listener shared across all components
260
+ })
261
+ ```
262
+
263
+ ---
264
+
265
+ ## 5. Re-render Optimization (MEDIUM)
266
+
267
+ ### Don't Subscribe to Unused State
268
+
269
+ ```tsx
270
+ // Bad - re-renders on every position change
271
+ function ClickHandler() {
272
+ const position = useMousePosition()
273
+ return <button onClick={() => console.log(position)}>Log</button>
274
+ }
275
+
276
+ // Good - no subscription, read on demand
277
+ function ClickHandler() {
278
+ const getPosition = useMousePositionRef()
279
+ return <button onClick={() => console.log(getPosition())}>Log</button>
280
+ }
281
+ ```
282
+
283
+ ### Use Primitive Dependencies
284
+
285
+ ```tsx
286
+ // Bad - effect runs on every render (new object)
287
+ useEffect(() => {
288
+ fetch(`/api/user/${user.id}`)
289
+ }, [user])
290
+
291
+ // Good - effect runs only when id changes
292
+ useEffect(() => {
293
+ fetch(`/api/user/${userId}`)
294
+ }, [userId])
295
+ ```
296
+
297
+ ### Derived State as Booleans
298
+
299
+ ```tsx
300
+ // Bad - re-renders on any cart change
301
+ function CheckoutButton() {
302
+ const cart = useCart()
303
+ if (cart.items.length === 0) return null
304
+ return <Button>Checkout</Button>
305
+ }
306
+
307
+ // Good - only re-renders when emptiness changes
308
+ function CheckoutButton() {
309
+ const hasItems = useCartHasItems()
310
+ if (!hasItems) return null
311
+ return <Button>Checkout</Button>
312
+ }
313
+ ```
314
+
315
+ ### Functional setState for Stable Callbacks
316
+
317
+ ```tsx
318
+ // Bad - new callback each render
319
+ <button onClick={() => setCount(count + 1)}>+1</button>
320
+
321
+ // Good - stable callback
322
+ <button onClick={() => setCount(c => c + 1)}>+1</button>
323
+ ```
324
+
325
+ ### Lazy State Initialization
326
+
327
+ ```tsx
328
+ // Bad - runs expensive function every render
329
+ const [data] = useState(expensiveComputation())
330
+
331
+ // Good - only runs once
332
+ const [data] = useState(() => expensiveComputation())
333
+ ```
334
+
335
+ ---
336
+
337
+ ## 6. Rendering Patterns
338
+
339
+ ### Conditional Rendering
340
+
341
+ ```tsx
342
+ // Bad - can render 0
343
+ {items.length && <List items={items} />}
344
+
345
+ // Good - explicit boolean
346
+ {items.length > 0 && <List items={items} />}
347
+
348
+ // Better - ternary
349
+ {items.length > 0 ? <List items={items} /> : null}
350
+ ```
351
+
352
+ ### Hoist Static JSX
353
+
354
+ ```tsx
355
+ // Bad - creates new object each render
356
+ function Component() {
357
+ const icon = <Icon />
358
+ return <div>{icon}</div>
359
+ }
360
+
361
+ // Good - stable reference
362
+ const icon = <Icon />
363
+ function Component() {
364
+ return <div>{icon}</div>
365
+ }
366
+ ```
367
+
368
+ ### Content Visibility for Long Lists
369
+
370
+ ```css
371
+ .list-item {
372
+ content-visibility: auto;
373
+ contain-intrinsic-size: 0 50px;
374
+ }
375
+ ```
376
+
377
+ ---
378
+
379
+ ## 7. Next.js Specific
380
+
381
+ ### Route Handlers
382
+
383
+ ```typescript
384
+ // app/api/users/route.ts
385
+ export async function GET() {
386
+ const users = await getUsers()
387
+ return Response.json(users)
388
+ }
389
+
390
+ export async function POST(request: Request) {
391
+ const body = await request.json()
392
+ const user = await createUser(body)
393
+ return Response.json(user, { status: 201 })
394
+ }
395
+ ```
396
+
397
+ ### Metadata
398
+
399
+ ```typescript
400
+ // Static
401
+ export const metadata = {
402
+ title: 'My Page',
403
+ description: 'Page description'
404
+ }
405
+
406
+ // Dynamic
407
+ export async function generateMetadata({ params }) {
408
+ const post = await getPost(params.id)
409
+ return { title: post.title }
410
+ }
411
+ ```
412
+
413
+ ### Loading & Error States
414
+
415
+ ```tsx
416
+ // app/posts/loading.tsx
417
+ export default function Loading() {
418
+ return <PostsSkeleton />
419
+ }
420
+
421
+ // app/posts/error.tsx
422
+ 'use client'
423
+ export default function Error({ error, reset }) {
424
+ return (
425
+ <div>
426
+ <p>Something went wrong</p>
427
+ <button onClick={reset}>Try again</button>
428
+ </div>
429
+ )
430
+ }
431
+ ```
432
+
433
+ ### Image Optimization
434
+
435
+ ```tsx
436
+ import Image from 'next/image'
437
+
438
+ <Image
439
+ src="/hero.jpg"
440
+ alt="Hero"
441
+ width={1200}
442
+ height={600}
443
+ priority // For above-fold images
444
+ />
445
+ ```
446
+
447
+ ### Link Prefetching
448
+
449
+ ```tsx
450
+ import Link from 'next/link'
451
+
452
+ <Link href="/about" prefetch={true}>About</Link>
453
+
454
+ // Prefetch on hover for dynamic routes
455
+ <Link href={`/posts/${id}`} prefetch={false}>
456
+ Post
457
+ </Link>
458
+ ```
459
+
460
+ ---
461
+
462
+ ## Common Gotchas
463
+
464
+ 1. **Server vs Client confusion** - Default is Server, add 'use client' only when needed
465
+ 2. **Fetching in useEffect** - Prefer Server Components or SWR
466
+ 3. **Barrel imports** - Use optimizePackageImports or direct imports
467
+ 4. **Object dependencies** - Use primitives in useEffect/useMemo deps
468
+ 5. **Missing Suspense** - Wrap async components for streaming
469
+ 6. **Hydration mismatch** - Ensure server/client render same content
470
+
471
+ ---
472
+
473
+ ## References
474
+
475
+ - [Next.js App Router Docs](https://nextjs.org/docs/app)
476
+ - [React Server Components](https://react.dev/reference/react/use-server)
477
+ - [Vercel React Best Practices](https://github.com/vercel/react-best-practices)