@qazuor/claude-code-config 0.5.0 → 0.6.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 (57) hide show
  1. package/README.md +106 -41
  2. package/dist/bin.cjs +963 -84
  3. package/dist/bin.cjs.map +1 -1
  4. package/dist/bin.js +963 -84
  5. package/dist/bin.js.map +1 -1
  6. package/dist/index.cjs +73 -56
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +2 -0
  9. package/dist/index.d.ts +2 -0
  10. package/dist/index.js +73 -56
  11. package/dist/index.js.map +1 -1
  12. package/package.json +23 -24
  13. package/templates/CLAUDE.md.template +60 -5
  14. package/templates/agents/README.md +58 -39
  15. package/templates/agents/_registry.json +43 -202
  16. package/templates/agents/engineering/{hono-engineer.md → api-engineer.md} +61 -70
  17. package/templates/agents/engineering/database-engineer.md +253 -0
  18. package/templates/agents/engineering/frontend-engineer.md +302 -0
  19. package/templates/hooks/on-notification.sh +0 -0
  20. package/templates/scripts/add-changelogs.sh +0 -0
  21. package/templates/scripts/generate-code-registry.ts +0 -0
  22. package/templates/scripts/health-check.sh +0 -0
  23. package/templates/scripts/sync-registry.sh +0 -0
  24. package/templates/scripts/telemetry-report.ts +0 -0
  25. package/templates/scripts/validate-docs.sh +0 -0
  26. package/templates/scripts/validate-registry.sh +0 -0
  27. package/templates/scripts/validate-structure.sh +0 -0
  28. package/templates/scripts/worktree-cleanup.sh +0 -0
  29. package/templates/scripts/worktree-create.sh +0 -0
  30. package/templates/skills/README.md +99 -90
  31. package/templates/skills/_registry.json +323 -16
  32. package/templates/skills/api-frameworks/express-patterns.md +411 -0
  33. package/templates/skills/api-frameworks/fastify-patterns.md +419 -0
  34. package/templates/skills/api-frameworks/hono-patterns.md +388 -0
  35. package/templates/skills/api-frameworks/nestjs-patterns.md +497 -0
  36. package/templates/skills/database/drizzle-patterns.md +449 -0
  37. package/templates/skills/database/mongoose-patterns.md +503 -0
  38. package/templates/skills/database/prisma-patterns.md +487 -0
  39. package/templates/skills/frontend-frameworks/astro-patterns.md +415 -0
  40. package/templates/skills/frontend-frameworks/nextjs-patterns.md +470 -0
  41. package/templates/skills/frontend-frameworks/react-patterns.md +516 -0
  42. package/templates/skills/frontend-frameworks/tanstack-start-patterns.md +469 -0
  43. package/templates/skills/patterns/atdd-methodology.md +364 -0
  44. package/templates/skills/patterns/bdd-methodology.md +281 -0
  45. package/templates/skills/patterns/clean-architecture.md +444 -0
  46. package/templates/skills/patterns/hexagonal-architecture.md +567 -0
  47. package/templates/skills/patterns/vertical-slice-architecture.md +502 -0
  48. package/templates/agents/engineering/astro-engineer.md +0 -293
  49. package/templates/agents/engineering/db-drizzle-engineer.md +0 -360
  50. package/templates/agents/engineering/express-engineer.md +0 -316
  51. package/templates/agents/engineering/fastify-engineer.md +0 -399
  52. package/templates/agents/engineering/mongoose-engineer.md +0 -473
  53. package/templates/agents/engineering/nestjs-engineer.md +0 -429
  54. package/templates/agents/engineering/nextjs-engineer.md +0 -451
  55. package/templates/agents/engineering/prisma-engineer.md +0 -432
  56. package/templates/agents/engineering/react-senior-dev.md +0 -394
  57. package/templates/agents/engineering/tanstack-start-engineer.md +0 -447
@@ -0,0 +1,470 @@
1
+ # Next.js App Router Patterns
2
+
3
+ ## Overview
4
+
5
+ Next.js is a React framework with server-side rendering and App Router. This skill provides patterns for building Next.js applications.
6
+
7
+ ---
8
+
9
+ ## Server Components (Default)
10
+
11
+ ### Data Fetching in Server Components
12
+
13
+ ```typescript
14
+ // app/items/page.tsx
15
+ import { getItems } from '@/lib/actions/items';
16
+ import { ItemList } from '@/components/features/item-list';
17
+
18
+ export default async function ItemsPage() {
19
+ const items = await getItems();
20
+
21
+ return (
22
+ <main className="container py-8">
23
+ <h1 className="text-2xl font-bold mb-4">Items</h1>
24
+ <ItemList items={items} />
25
+ </main>
26
+ );
27
+ }
28
+ ```
29
+
30
+ ### With Search Params
31
+
32
+ ```typescript
33
+ // app/items/page.tsx
34
+ interface PageProps {
35
+ searchParams: { q?: string; page?: string };
36
+ }
37
+
38
+ export default async function ItemsPage({ searchParams }: PageProps) {
39
+ const query = searchParams.q || '';
40
+ const page = Number(searchParams.page) || 1;
41
+
42
+ const { items, totalPages } = await getItems({ query, page });
43
+
44
+ return (
45
+ <main>
46
+ <SearchBar defaultValue={query} />
47
+ <ItemList items={items} />
48
+ <Pagination currentPage={page} totalPages={totalPages} />
49
+ </main>
50
+ );
51
+ }
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Client Components
57
+
58
+ ### Interactive Components
59
+
60
+ ```typescript
61
+ 'use client';
62
+
63
+ import { useState } from 'react';
64
+ import { Button } from '@/components/ui/button';
65
+ import { updateItem } from '@/lib/actions/items';
66
+ import { useToast } from '@/hooks/use-toast';
67
+
68
+ interface ItemCardProps {
69
+ item: { id: string; title: string };
70
+ }
71
+
72
+ export function ItemCard({ item }: ItemCardProps) {
73
+ const [isPending, setIsPending] = useState(false);
74
+ const { toast } = useToast();
75
+
76
+ const handleUpdate = async () => {
77
+ setIsPending(true);
78
+ try {
79
+ await updateItem(item.id, { title: 'Updated' });
80
+ toast({ title: 'Item updated' });
81
+ } catch (error) {
82
+ toast({ title: 'Error updating item', variant: 'destructive' });
83
+ } finally {
84
+ setIsPending(false);
85
+ }
86
+ };
87
+
88
+ return (
89
+ <div className="p-4 border rounded">
90
+ <p>{item.title}</p>
91
+ <Button onClick={handleUpdate} disabled={isPending}>
92
+ {isPending ? 'Updating...' : 'Update'}
93
+ </Button>
94
+ </div>
95
+ );
96
+ }
97
+ ```
98
+
99
+ ---
100
+
101
+ ## Server Actions
102
+
103
+ ### Form Action
104
+
105
+ ```typescript
106
+ // lib/actions/items.ts
107
+ 'use server';
108
+
109
+ import { revalidatePath } from 'next/cache';
110
+ import { redirect } from 'next/navigation';
111
+ import { z } from 'zod';
112
+ import { db } from '@/lib/db';
113
+ import { getSession } from '@/lib/auth';
114
+
115
+ const createItemSchema = z.object({
116
+ title: z.string().min(1),
117
+ description: z.string().optional(),
118
+ });
119
+
120
+ export async function createItem(formData: FormData) {
121
+ const session = await getSession();
122
+ if (!session?.user) {
123
+ throw new Error('Unauthorized');
124
+ }
125
+
126
+ const data = {
127
+ title: formData.get('title'),
128
+ description: formData.get('description'),
129
+ };
130
+
131
+ const parsed = createItemSchema.parse(data);
132
+
133
+ const item = await db.item.create({
134
+ data: {
135
+ ...parsed,
136
+ authorId: session.user.id,
137
+ },
138
+ });
139
+
140
+ revalidatePath('/items');
141
+ redirect(`/items/${item.id}`);
142
+ }
143
+ ```
144
+
145
+ ### Action with Return Value
146
+
147
+ ```typescript
148
+ 'use server';
149
+
150
+ import { revalidatePath } from 'next/cache';
151
+
152
+ type ActionResult =
153
+ | { success: true; data: Item }
154
+ | { success: false; error: string };
155
+
156
+ export async function updateItem(
157
+ id: string,
158
+ data: Partial<Item>
159
+ ): Promise<ActionResult> {
160
+ try {
161
+ const session = await getSession();
162
+ if (!session?.user) {
163
+ return { success: false, error: 'Unauthorized' };
164
+ }
165
+
166
+ const item = await db.item.update({
167
+ where: { id, authorId: session.user.id },
168
+ data,
169
+ });
170
+
171
+ revalidatePath('/items');
172
+ revalidatePath(`/items/${id}`);
173
+
174
+ return { success: true, data: item };
175
+ } catch (error) {
176
+ return { success: false, error: 'Failed to update item' };
177
+ }
178
+ }
179
+ ```
180
+
181
+ ---
182
+
183
+ ## Route Handlers
184
+
185
+ ### API Route
186
+
187
+ ```typescript
188
+ // app/api/items/route.ts
189
+ import { NextResponse } from 'next/server';
190
+ import { db } from '@/lib/db';
191
+ import { getSession } from '@/lib/auth';
192
+
193
+ export async function GET(request: Request) {
194
+ const { searchParams } = new URL(request.url);
195
+ const page = Number(searchParams.get('page')) || 1;
196
+ const limit = Number(searchParams.get('limit')) || 10;
197
+
198
+ const items = await db.item.findMany({
199
+ where: { status: 'active' },
200
+ take: limit,
201
+ skip: (page - 1) * limit,
202
+ });
203
+
204
+ return NextResponse.json({ data: items });
205
+ }
206
+
207
+ export async function POST(request: Request) {
208
+ const session = await getSession();
209
+ if (!session?.user) {
210
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
211
+ }
212
+
213
+ const body = await request.json();
214
+
215
+ const item = await db.item.create({
216
+ data: { ...body, authorId: session.user.id },
217
+ });
218
+
219
+ return NextResponse.json({ data: item }, { status: 201 });
220
+ }
221
+ ```
222
+
223
+ ### Dynamic Route Handler
224
+
225
+ ```typescript
226
+ // app/api/items/[id]/route.ts
227
+ import { NextResponse } from 'next/server';
228
+
229
+ interface RouteParams {
230
+ params: { id: string };
231
+ }
232
+
233
+ export async function GET(request: Request, { params }: RouteParams) {
234
+ const item = await db.item.findUnique({
235
+ where: { id: params.id },
236
+ });
237
+
238
+ if (!item) {
239
+ return NextResponse.json({ error: 'Not found' }, { status: 404 });
240
+ }
241
+
242
+ return NextResponse.json({ data: item });
243
+ }
244
+ ```
245
+
246
+ ---
247
+
248
+ ## Layouts and Loading States
249
+
250
+ ### Root Layout
251
+
252
+ ```typescript
253
+ // app/layout.tsx
254
+ import { Inter } from 'next/font/google';
255
+ import { Providers } from '@/components/providers';
256
+ import { Header } from '@/components/layout/header';
257
+ import './globals.css';
258
+
259
+ const inter = Inter({ subsets: ['latin'] });
260
+
261
+ export const metadata = {
262
+ title: 'My App',
263
+ description: 'App description',
264
+ };
265
+
266
+ export default function RootLayout({
267
+ children,
268
+ }: {
269
+ children: React.ReactNode;
270
+ }) {
271
+ return (
272
+ <html lang="en">
273
+ <body className={inter.className}>
274
+ <Providers>
275
+ <Header />
276
+ {children}
277
+ </Providers>
278
+ </body>
279
+ </html>
280
+ );
281
+ }
282
+ ```
283
+
284
+ ### Loading State
285
+
286
+ ```typescript
287
+ // app/items/loading.tsx
288
+ import { Skeleton } from '@/components/ui/skeleton';
289
+
290
+ export default function Loading() {
291
+ return (
292
+ <div className="container py-8">
293
+ <Skeleton className="h-8 w-48 mb-4" />
294
+ <div className="grid gap-4">
295
+ {[1, 2, 3].map((i) => (
296
+ <Skeleton key={i} className="h-24 w-full" />
297
+ ))}
298
+ </div>
299
+ </div>
300
+ );
301
+ }
302
+ ```
303
+
304
+ ### Error Handling
305
+
306
+ ```typescript
307
+ // app/items/error.tsx
308
+ 'use client';
309
+
310
+ import { Button } from '@/components/ui/button';
311
+
312
+ interface ErrorProps {
313
+ error: Error & { digest?: string };
314
+ reset: () => void;
315
+ }
316
+
317
+ export default function Error({ error, reset }: ErrorProps) {
318
+ return (
319
+ <div className="container py-8">
320
+ <div className="p-4 border border-red-500 rounded">
321
+ <h2 className="text-lg font-bold">Something went wrong!</h2>
322
+ <p className="text-sm text-muted-foreground">{error.message}</p>
323
+ <Button onClick={reset} className="mt-4">
324
+ Try again
325
+ </Button>
326
+ </div>
327
+ </div>
328
+ );
329
+ }
330
+ ```
331
+
332
+ ---
333
+
334
+ ## Caching and Revalidation
335
+
336
+ ### Static Generation
337
+
338
+ ```typescript
339
+ // Generate static pages at build time
340
+ export async function generateStaticParams() {
341
+ const items = await db.item.findMany({
342
+ select: { id: true },
343
+ });
344
+
345
+ return items.map((item) => ({
346
+ id: item.id,
347
+ }));
348
+ }
349
+ ```
350
+
351
+ ### Revalidation Options
352
+
353
+ ```typescript
354
+ // Time-based revalidation
355
+ export const revalidate = 3600; // Revalidate every hour
356
+
357
+ // On-demand revalidation in Server Actions
358
+ import { revalidatePath, revalidateTag } from 'next/cache';
359
+
360
+ export async function createItem() {
361
+ // ... create item
362
+ revalidatePath('/items');
363
+ revalidateTag('items');
364
+ }
365
+ ```
366
+
367
+ ### Fetch with Cache Options
368
+
369
+ ```typescript
370
+ // Cache forever (default)
371
+ const data = await fetch(url);
372
+
373
+ // Don't cache
374
+ const data = await fetch(url, { cache: 'no-store' });
375
+
376
+ // Revalidate after time
377
+ const data = await fetch(url, { next: { revalidate: 3600 } });
378
+
379
+ // Tag-based revalidation
380
+ const data = await fetch(url, { next: { tags: ['items'] } });
381
+ ```
382
+
383
+ ---
384
+
385
+ ## Middleware
386
+
387
+ ```typescript
388
+ // middleware.ts
389
+ import { NextResponse } from 'next/server';
390
+ import type { NextRequest } from 'next/server';
391
+ import { getToken } from 'next-auth/jwt';
392
+
393
+ export async function middleware(request: NextRequest) {
394
+ const token = await getToken({ req: request });
395
+ const isAuth = !!token;
396
+ const isAuthPage = request.nextUrl.pathname.startsWith('/login');
397
+
398
+ if (isAuthPage) {
399
+ if (isAuth) {
400
+ return NextResponse.redirect(new URL('/dashboard', request.url));
401
+ }
402
+ return NextResponse.next();
403
+ }
404
+
405
+ if (!isAuth) {
406
+ return NextResponse.redirect(new URL('/login', request.url));
407
+ }
408
+
409
+ return NextResponse.next();
410
+ }
411
+
412
+ export const config = {
413
+ matcher: ['/dashboard/:path*', '/login'],
414
+ };
415
+ ```
416
+
417
+ ---
418
+
419
+ ## Project Structure
420
+
421
+ ```
422
+ app/
423
+ ├── layout.tsx # Root layout
424
+ ├── page.tsx # Home page
425
+ ├── loading.tsx # Loading UI
426
+ ├── error.tsx # Error UI
427
+ ├── not-found.tsx # 404 page
428
+ ├── (auth)/ # Route group (no URL impact)
429
+ │ ├── login/page.tsx
430
+ │ └── register/page.tsx
431
+ ├── items/
432
+ │ ├── layout.tsx
433
+ │ ├── page.tsx
434
+ │ ├── loading.tsx
435
+ │ └── [id]/
436
+ │ ├── page.tsx
437
+ │ └── edit/page.tsx
438
+ ├── api/
439
+ │ └── items/
440
+ │ └── route.ts
441
+ components/
442
+ ├── ui/ # Base UI components
443
+ └── features/ # Feature components
444
+ lib/
445
+ ├── actions/ # Server Actions
446
+ ├── db/ # Database client
447
+ ├── auth/ # Authentication
448
+ └── utils/
449
+ ```
450
+
451
+ ---
452
+
453
+ ## Best Practices
454
+
455
+ ### Good
456
+
457
+ - Use Server Components by default
458
+ - Use Client Components only for interactivity
459
+ - Use Server Actions for mutations
460
+ - Use loading.tsx for instant feedback
461
+ - Use error.tsx for graceful error handling
462
+ - Use generateStaticParams for static pages
463
+
464
+ ### Bad
465
+
466
+ - 'use client' everywhere (loses server benefits)
467
+ - Client-side fetching when server fetch works
468
+ - No error handling
469
+ - Ignoring caching strategies
470
+ - Not using revalidation