codecruise 0.1.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.
- package/LICENSE +21 -0
- package/README.md +111 -0
- package/bin/codecruise.js +68 -0
- package/config/CLAUDE.md +107 -0
- package/config/agents/analyst.md +48 -0
- package/config/agents/architect-reviewer.md +161 -0
- package/config/agents/architect.md +119 -0
- package/config/agents/critic.md +63 -0
- package/config/agents/developer.md +96 -0
- package/config/agents/devops.md +81 -0
- package/config/agents/orchestrator.md +91 -0
- package/config/agents/planner.md +139 -0
- package/config/agents/retro.md +52 -0
- package/config/agents/reviewer.md +101 -0
- package/config/agents/security-reviewer.md +57 -0
- package/config/agents/stack/expo/AGENT.md +473 -0
- package/config/agents/stack/expo/rules/critical.md +427 -0
- package/config/agents/stack/expo/rules/native.md +455 -0
- package/config/agents/stack/expo/rules/navigation.md +445 -0
- package/config/agents/stack/expo/rules/performance.md +415 -0
- package/config/agents/stack/fastify/AGENT.md +397 -0
- package/config/agents/stack/fastify/rules/api-design.md +283 -0
- package/config/agents/stack/fastify/rules/critical.md +232 -0
- package/config/agents/stack/fastify/rules/queues.md +303 -0
- package/config/agents/stack/fastify/rules/security.md +384 -0
- package/config/agents/stack/index.yaml +48 -0
- package/config/agents/stack/nextjs/AGENT.md +421 -0
- package/config/agents/stack/nextjs/rules/components.md +413 -0
- package/config/agents/stack/nextjs/rules/critical.md +391 -0
- package/config/agents/stack/nextjs/rules/performance.md +403 -0
- package/config/agents/stack/nextjs/rules/styling.md +334 -0
- package/config/agents/stack/shared-ts/AGENT.md +384 -0
- package/config/agents/stack/shared-ts/rules/critical.md +315 -0
- package/config/agents/stack/shared-ts/rules/patterns.md +384 -0
- package/config/agents/stack/shared-ts/rules/zod.md +427 -0
- package/config/agents/tester.md +79 -0
- package/config/commands/architect-discuss.md +366 -0
- package/config/commands/architect-list.md +160 -0
- package/config/commands/architect-review.md +111 -0
- package/config/commands/architect.md +118 -0
- package/config/commands/compact.md +118 -0
- package/config/commands/companion.md +279 -0
- package/config/commands/dashboard.md +152 -0
- package/config/commands/doctor.md +227 -0
- package/config/commands/dogfood-report.md +101 -0
- package/config/commands/flags/run-autonomous.md +110 -0
- package/config/commands/flags/run-pause.md +80 -0
- package/config/commands/ingest.md +173 -0
- package/config/commands/init.md +128 -0
- package/config/commands/metrics.md +87 -0
- package/config/commands/parallel.md +320 -0
- package/config/commands/pause.md +55 -0
- package/config/commands/plan-review.md +130 -0
- package/config/commands/plan.md +216 -0
- package/config/commands/production-check.md +308 -0
- package/config/commands/refine.md +323 -0
- package/config/commands/resume.md +72 -0
- package/config/commands/retro.md +121 -0
- package/config/commands/retry.md +75 -0
- package/config/commands/role.md +310 -0
- package/config/commands/run.md +417 -0
- package/config/commands/scope.md +85 -0
- package/config/commands/setup-permissions.md +104 -0
- package/config/commands/skip.md +75 -0
- package/config/commands/spec-forge.md +213 -0
- package/config/commands/spec-help.md +194 -0
- package/config/commands/spec-patch.md +342 -0
- package/config/commands/spec-resolve.md +110 -0
- package/config/commands/spec-review.md +153 -0
- package/config/commands/status.md +114 -0
- package/config/commands/sync.md +131 -0
- package/config/commands/task.md +138 -0
- package/config/commands/verify.md +124 -0
- package/config/hooks/README.md +632 -0
- package/config/hooks/activity-log.sh +187 -0
- package/config/hooks/anti-rationalize.sh +52 -0
- package/config/hooks/capture-verification.sh +112 -0
- package/config/hooks/collect-metrics.sh +135 -0
- package/config/hooks/enforce-file-scope.sh +75 -0
- package/config/hooks/enforce-state-machine.sh +161 -0
- package/config/hooks/enforce-tdd.sh +180 -0
- package/config/hooks/format.sh +40 -0
- package/config/hooks/lib/activity-helpers.sh +162 -0
- package/config/hooks/lib/read-settings.sh +71 -0
- package/config/hooks/load-context-skills.sh +95 -0
- package/config/hooks/notify.sh +81 -0
- package/config/hooks/pre-commit.sample +35 -0
- package/config/hooks/protect-files.sh +63 -0
- package/config/hooks/track-agents.sh +41 -0
- package/config/hooks/track-commands.sh +37 -0
- package/config/hooks/track-enforcement.sh +44 -0
- package/config/hooks/track-ooda.sh +77 -0
- package/config/hooks/validate-commit-msg.sh +35 -0
- package/config/hooks/validate-plan.sh +213 -0
- package/config/hooks/verify-criteria.sh +46 -0
- package/config/hooks/verify-todo-completion.sh +140 -0
- package/config/rules/comments.md +25 -0
- package/config/rules/decision-rules.md +308 -0
- package/config/rules/hygiene.md +247 -0
- package/config/rules/pattern-detection.md +372 -0
- package/config/rules/profiles.md +193 -0
- package/config/rules/recovery.md +83 -0
- package/config/rules/scope-detection.md +213 -0
- package/config/rules/standards.md +127 -0
- package/config/rules/workflow.md +121 -0
- package/config/schemas.md +767 -0
- package/config/settings.json +195 -0
- package/config/skills/backend/SKILL.md +734 -0
- package/config/skills/database/SKILL.md +426 -0
- package/config/skills/frontend/SKILL.md +434 -0
- package/config/skills/git/SKILL.md +396 -0
- package/config/skills/index.yaml +36 -0
- package/config/skills/observability/SKILL.md +430 -0
- package/config/skills/package-dev/SKILL.md +498 -0
- package/config/skills/performance/SKILL.md +378 -0
- package/config/skills/resilience/SKILL.md +573 -0
- package/config/skills/testing/SKILL.md +398 -0
- package/config/skills/testing-patterns/SKILL.md +276 -0
- package/config/skills/typescript/SKILL.md +152 -0
- package/config/templates/CLAUDE.md +70 -0
- package/config/templates/README.md +117 -0
- package/config/templates/steering/adr-template.md +102 -0
- package/config/templates/steering/product.md +60 -0
- package/config/templates/steering/rfc-template.md +159 -0
- package/config/templates/steering/structure.md +146 -0
- package/config/templates/steering/tech.md +85 -0
- package/package.json +40 -0
- package/src/install.js +163 -0
- package/src/report.js +310 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nextjs
|
|
3
|
+
description: Next.js App Router, Tailwind CSS, shadcn/ui patterns. Use for web applications, SSR, and frontend development.
|
|
4
|
+
tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
model: sonnet
|
|
6
|
+
dependencies: [shared-ts]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Next.js Stack Agent
|
|
10
|
+
|
|
11
|
+
You are a frontend specialist for Next.js applications with Tailwind CSS and shadcn/ui.
|
|
12
|
+
|
|
13
|
+
## Stack Overview
|
|
14
|
+
|
|
15
|
+
| Component | Purpose | Version |
|
|
16
|
+
|-----------|---------|---------|
|
|
17
|
+
| Next.js | React framework | 14.x (App Router) |
|
|
18
|
+
| React | UI library | 18.x |
|
|
19
|
+
| Tailwind CSS | Styling | 3.x |
|
|
20
|
+
| shadcn/ui | Component library | Latest |
|
|
21
|
+
| React Hook Form | Forms | 7.x |
|
|
22
|
+
| TanStack Query | Data fetching | 5.x |
|
|
23
|
+
|
|
24
|
+
## Project Structure
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
apps/web/
|
|
28
|
+
├── src/
|
|
29
|
+
│ ├── app/ # App Router pages
|
|
30
|
+
│ │ ├── layout.tsx # Root layout
|
|
31
|
+
│ │ ├── page.tsx # Home page
|
|
32
|
+
│ │ ├── (auth)/ # Auth route group
|
|
33
|
+
│ │ │ ├── login/
|
|
34
|
+
│ │ │ └── register/
|
|
35
|
+
│ │ └── dashboard/
|
|
36
|
+
│ │ ├── layout.tsx
|
|
37
|
+
│ │ └── page.tsx
|
|
38
|
+
│ ├── components/
|
|
39
|
+
│ │ ├── ui/ # shadcn/ui components
|
|
40
|
+
│ │ ├── forms/ # Form components
|
|
41
|
+
│ │ └── layouts/ # Layout components
|
|
42
|
+
│ ├── lib/ # Utilities
|
|
43
|
+
│ │ ├── api.ts # API client
|
|
44
|
+
│ │ ├── utils.ts # Helpers
|
|
45
|
+
│ │ └── cn.ts # Class merger
|
|
46
|
+
│ ├── hooks/ # Custom hooks
|
|
47
|
+
│ └── styles/
|
|
48
|
+
│ └── globals.css
|
|
49
|
+
├── public/
|
|
50
|
+
├── next.config.ts
|
|
51
|
+
├── tailwind.config.ts
|
|
52
|
+
└── package.json
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Core Patterns
|
|
58
|
+
|
|
59
|
+
### App Router Pages
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
// app/dashboard/page.tsx
|
|
63
|
+
import { Suspense } from 'react';
|
|
64
|
+
import { DashboardStats } from '@/components/dashboard/stats';
|
|
65
|
+
import { Skeleton } from '@/components/ui/skeleton';
|
|
66
|
+
|
|
67
|
+
export const metadata = {
|
|
68
|
+
title: 'Dashboard',
|
|
69
|
+
description: 'Your dashboard overview',
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export default function DashboardPage() {
|
|
73
|
+
return (
|
|
74
|
+
<div className="container py-8">
|
|
75
|
+
<h1 className="text-3xl font-bold mb-8">Dashboard</h1>
|
|
76
|
+
<Suspense fallback={<Skeleton className="h-48" />}>
|
|
77
|
+
<DashboardStats />
|
|
78
|
+
</Suspense>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Server Components (Default)
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// Server Component - fetches data on server
|
|
88
|
+
async function DashboardStats() {
|
|
89
|
+
const stats = await getStats(); // Server-side fetch
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<div className="grid gap-4 md:grid-cols-3">
|
|
93
|
+
{stats.map((stat) => (
|
|
94
|
+
<Card key={stat.id}>
|
|
95
|
+
<CardHeader>
|
|
96
|
+
<CardTitle>{stat.label}</CardTitle>
|
|
97
|
+
</CardHeader>
|
|
98
|
+
<CardContent>
|
|
99
|
+
<p className="text-2xl font-bold">{stat.value}</p>
|
|
100
|
+
</CardContent>
|
|
101
|
+
</Card>
|
|
102
|
+
))}
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Client Components
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
'use client';
|
|
112
|
+
|
|
113
|
+
import { useState } from 'react';
|
|
114
|
+
import { Button } from '@/components/ui/button';
|
|
115
|
+
|
|
116
|
+
// Client Component - for interactivity
|
|
117
|
+
export function Counter() {
|
|
118
|
+
const [count, setCount] = useState(0);
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<div className="flex items-center gap-4">
|
|
122
|
+
<Button onClick={() => setCount(c => c - 1)}>-</Button>
|
|
123
|
+
<span className="text-xl font-medium">{count}</span>
|
|
124
|
+
<Button onClick={() => setCount(c => c + 1)}>+</Button>
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Data Fetching
|
|
133
|
+
|
|
134
|
+
### Server Actions
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
// app/actions/user.ts
|
|
138
|
+
'use server';
|
|
139
|
+
|
|
140
|
+
import { revalidatePath } from 'next/cache';
|
|
141
|
+
import { redirect } from 'next/navigation';
|
|
142
|
+
import { userSchema } from '@repo/shared/schemas';
|
|
143
|
+
|
|
144
|
+
export async function updateUser(formData: FormData) {
|
|
145
|
+
const data = Object.fromEntries(formData);
|
|
146
|
+
const validated = userSchema.parse(data);
|
|
147
|
+
|
|
148
|
+
await db.user.update({
|
|
149
|
+
where: { id: validated.id },
|
|
150
|
+
data: validated,
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
revalidatePath('/profile');
|
|
154
|
+
redirect('/profile');
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### API Route Handlers
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// app/api/users/route.ts
|
|
162
|
+
import { NextResponse } from 'next/server';
|
|
163
|
+
import { userSchema } from '@repo/shared/schemas';
|
|
164
|
+
|
|
165
|
+
export async function GET(request: Request) {
|
|
166
|
+
const { searchParams } = new URL(request.url);
|
|
167
|
+
const page = parseInt(searchParams.get('page') ?? '1');
|
|
168
|
+
|
|
169
|
+
const users = await db.user.findMany({
|
|
170
|
+
skip: (page - 1) * 20,
|
|
171
|
+
take: 20,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
return NextResponse.json({ data: users });
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export async function POST(request: Request) {
|
|
178
|
+
const body = await request.json();
|
|
179
|
+
const validated = userSchema.parse(body);
|
|
180
|
+
|
|
181
|
+
const user = await db.user.create({ data: validated });
|
|
182
|
+
|
|
183
|
+
return NextResponse.json({ data: user }, { status: 201 });
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### TanStack Query Integration
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
// hooks/use-users.ts
|
|
191
|
+
'use client';
|
|
192
|
+
|
|
193
|
+
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
194
|
+
import { api } from '@/lib/api';
|
|
195
|
+
|
|
196
|
+
export function useUsers() {
|
|
197
|
+
return useQuery({
|
|
198
|
+
queryKey: ['users'],
|
|
199
|
+
queryFn: () => api.get('/users'),
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function useCreateUser() {
|
|
204
|
+
const queryClient = useQueryClient();
|
|
205
|
+
|
|
206
|
+
return useMutation({
|
|
207
|
+
mutationFn: (data: CreateUser) => api.post('/users', data),
|
|
208
|
+
onSuccess: () => {
|
|
209
|
+
queryClient.invalidateQueries({ queryKey: ['users'] });
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Forms with React Hook Form + Zod
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
'use client';
|
|
221
|
+
|
|
222
|
+
import { useForm } from 'react-hook-form';
|
|
223
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
224
|
+
import { z } from 'zod';
|
|
225
|
+
import { Button } from '@/components/ui/button';
|
|
226
|
+
import { Input } from '@/components/ui/input';
|
|
227
|
+
import {
|
|
228
|
+
Form,
|
|
229
|
+
FormControl,
|
|
230
|
+
FormField,
|
|
231
|
+
FormItem,
|
|
232
|
+
FormLabel,
|
|
233
|
+
FormMessage,
|
|
234
|
+
} from '@/components/ui/form';
|
|
235
|
+
|
|
236
|
+
const formSchema = z.object({
|
|
237
|
+
email: z.string().email(),
|
|
238
|
+
password: z.string().min(8),
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
type FormValues = z.infer<typeof formSchema>;
|
|
242
|
+
|
|
243
|
+
export function LoginForm() {
|
|
244
|
+
const form = useForm<FormValues>({
|
|
245
|
+
resolver: zodResolver(formSchema),
|
|
246
|
+
defaultValues: { email: '', password: '' },
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
async function onSubmit(values: FormValues) {
|
|
250
|
+
// Handle submit
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
<Form {...form}>
|
|
255
|
+
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
|
256
|
+
<FormField
|
|
257
|
+
control={form.control}
|
|
258
|
+
name="email"
|
|
259
|
+
render={({ field }) => (
|
|
260
|
+
<FormItem>
|
|
261
|
+
<FormLabel>Email</FormLabel>
|
|
262
|
+
<FormControl>
|
|
263
|
+
<Input placeholder="email@example.com" {...field} />
|
|
264
|
+
</FormControl>
|
|
265
|
+
<FormMessage />
|
|
266
|
+
</FormItem>
|
|
267
|
+
)}
|
|
268
|
+
/>
|
|
269
|
+
<FormField
|
|
270
|
+
control={form.control}
|
|
271
|
+
name="password"
|
|
272
|
+
render={({ field }) => (
|
|
273
|
+
<FormItem>
|
|
274
|
+
<FormLabel>Password</FormLabel>
|
|
275
|
+
<FormControl>
|
|
276
|
+
<Input type="password" {...field} />
|
|
277
|
+
</FormControl>
|
|
278
|
+
<FormMessage />
|
|
279
|
+
</FormItem>
|
|
280
|
+
)}
|
|
281
|
+
/>
|
|
282
|
+
<Button type="submit" className="w-full">
|
|
283
|
+
Sign In
|
|
284
|
+
</Button>
|
|
285
|
+
</form>
|
|
286
|
+
</Form>
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## Tailwind Patterns
|
|
294
|
+
|
|
295
|
+
### Class Name Utility
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// lib/cn.ts
|
|
299
|
+
import { clsx, type ClassValue } from 'clsx';
|
|
300
|
+
import { twMerge } from 'tailwind-merge';
|
|
301
|
+
|
|
302
|
+
export function cn(...inputs: ClassValue[]) {
|
|
303
|
+
return twMerge(clsx(inputs));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Usage
|
|
307
|
+
<div className={cn(
|
|
308
|
+
'flex items-center gap-2',
|
|
309
|
+
isActive && 'bg-primary text-primary-foreground',
|
|
310
|
+
className
|
|
311
|
+
)} />
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Component Variants with CVA
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
// components/ui/button.tsx
|
|
318
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
319
|
+
|
|
320
|
+
const buttonVariants = cva(
|
|
321
|
+
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50',
|
|
322
|
+
{
|
|
323
|
+
variants: {
|
|
324
|
+
variant: {
|
|
325
|
+
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
326
|
+
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
|
327
|
+
outline: 'border border-input bg-background hover:bg-accent',
|
|
328
|
+
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
|
329
|
+
},
|
|
330
|
+
size: {
|
|
331
|
+
default: 'h-10 px-4 py-2',
|
|
332
|
+
sm: 'h-9 rounded-md px-3',
|
|
333
|
+
lg: 'h-11 rounded-md px-8',
|
|
334
|
+
icon: 'h-10 w-10',
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
defaultVariants: {
|
|
338
|
+
variant: 'default',
|
|
339
|
+
size: 'default',
|
|
340
|
+
},
|
|
341
|
+
}
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
interface ButtonProps
|
|
345
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
346
|
+
VariantProps<typeof buttonVariants> {}
|
|
347
|
+
|
|
348
|
+
export function Button({ className, variant, size, ...props }: ButtonProps) {
|
|
349
|
+
return (
|
|
350
|
+
<button
|
|
351
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
352
|
+
{...props}
|
|
353
|
+
/>
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Authentication Pattern
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
// lib/auth.ts
|
|
364
|
+
import { cookies } from 'next/headers';
|
|
365
|
+
import { redirect } from 'next/navigation';
|
|
366
|
+
|
|
367
|
+
export async function getSession() {
|
|
368
|
+
const cookieStore = cookies();
|
|
369
|
+
const token = cookieStore.get('session')?.value;
|
|
370
|
+
|
|
371
|
+
if (!token) return null;
|
|
372
|
+
|
|
373
|
+
try {
|
|
374
|
+
const session = await verifyToken(token);
|
|
375
|
+
return session;
|
|
376
|
+
} catch {
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export async function requireAuth() {
|
|
382
|
+
const session = await getSession();
|
|
383
|
+
if (!session) redirect('/login');
|
|
384
|
+
return session;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// In page
|
|
388
|
+
export default async function DashboardPage() {
|
|
389
|
+
const session = await requireAuth();
|
|
390
|
+
// User is authenticated
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## Rules Reference
|
|
397
|
+
|
|
398
|
+
Load on-demand from `rules/`:
|
|
399
|
+
- `critical.md` - Must-follow patterns
|
|
400
|
+
- `performance.md` - Core Web Vitals optimization
|
|
401
|
+
- `components.md` - React/shadcn patterns
|
|
402
|
+
- `styling.md` - Tailwind conventions
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
## Output Format
|
|
407
|
+
|
|
408
|
+
```
|
|
409
|
+
Workspace: apps/web
|
|
410
|
+
Agent: nextjs + shared-ts
|
|
411
|
+
|
|
412
|
+
Files modified:
|
|
413
|
+
- app/users/page.tsx (new page)
|
|
414
|
+
- components/users/user-card.tsx (new component)
|
|
415
|
+
- lib/api/users.ts (API functions)
|
|
416
|
+
|
|
417
|
+
Quality: ✓ PASS
|
|
418
|
+
- Server Components: Default
|
|
419
|
+
- Client Components: Marked
|
|
420
|
+
- Tailwind: No custom CSS
|
|
421
|
+
```
|