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,403 @@
|
|
|
1
|
+
# Performance Rules - Next.js
|
|
2
|
+
|
|
3
|
+
Core Web Vitals optimization and performance patterns.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Core Web Vitals
|
|
8
|
+
|
|
9
|
+
### PERF-001: Optimize Largest Contentful Paint (LCP)
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// Priority loading for hero images
|
|
13
|
+
import Image from 'next/image';
|
|
14
|
+
|
|
15
|
+
// Above-the-fold images
|
|
16
|
+
<Image
|
|
17
|
+
src="/hero.jpg"
|
|
18
|
+
alt="Hero"
|
|
19
|
+
width={1200}
|
|
20
|
+
height={600}
|
|
21
|
+
priority // Preload this image
|
|
22
|
+
fetchPriority="high"
|
|
23
|
+
/>
|
|
24
|
+
|
|
25
|
+
// Preload critical fonts
|
|
26
|
+
// app/layout.tsx
|
|
27
|
+
import { Inter } from 'next/font/google';
|
|
28
|
+
|
|
29
|
+
const inter = Inter({
|
|
30
|
+
subsets: ['latin'],
|
|
31
|
+
display: 'swap', // Prevent FOIT
|
|
32
|
+
preload: true,
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### PERF-002: Minimize Cumulative Layout Shift (CLS)
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
// Always specify dimensions for images
|
|
40
|
+
<Image
|
|
41
|
+
src={user.avatar}
|
|
42
|
+
alt={user.name}
|
|
43
|
+
width={48}
|
|
44
|
+
height={48} // Prevents layout shift
|
|
45
|
+
/>
|
|
46
|
+
|
|
47
|
+
// Use aspect-ratio for dynamic content
|
|
48
|
+
<div className="aspect-video">
|
|
49
|
+
<iframe src={videoUrl} className="w-full h-full" />
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
// Reserve space for loading content
|
|
53
|
+
<div className="min-h-[200px]">
|
|
54
|
+
<Suspense fallback={<Skeleton className="h-[200px]" />}>
|
|
55
|
+
<DynamicContent />
|
|
56
|
+
</Suspense>
|
|
57
|
+
</div>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### PERF-003: Optimize First Input Delay (FID) / INP
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
// Defer non-critical JavaScript
|
|
64
|
+
import dynamic from 'next/dynamic';
|
|
65
|
+
|
|
66
|
+
// Load heavy components only when needed
|
|
67
|
+
const Analytics = dynamic(() => import('./Analytics'), {
|
|
68
|
+
ssr: false, // Client-only
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Use startTransition for non-urgent updates
|
|
72
|
+
import { startTransition } from 'react';
|
|
73
|
+
|
|
74
|
+
function SearchInput() {
|
|
75
|
+
const [query, setQuery] = useState('');
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<input
|
|
79
|
+
value={query}
|
|
80
|
+
onChange={(e) => {
|
|
81
|
+
// Immediate update for input
|
|
82
|
+
setQuery(e.target.value);
|
|
83
|
+
|
|
84
|
+
// Deferred update for search results
|
|
85
|
+
startTransition(() => {
|
|
86
|
+
setSearchResults(e.target.value);
|
|
87
|
+
});
|
|
88
|
+
}}
|
|
89
|
+
/>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Bundle Optimization
|
|
97
|
+
|
|
98
|
+
### PERF-004: Dynamic imports for large components
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import dynamic from 'next/dynamic';
|
|
102
|
+
|
|
103
|
+
// Heavy components
|
|
104
|
+
const Editor = dynamic(() => import('./Editor'), {
|
|
105
|
+
loading: () => <Skeleton className="h-96" />,
|
|
106
|
+
ssr: false,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const Chart = dynamic(() => import('./Chart'), {
|
|
110
|
+
loading: () => <Skeleton className="h-64" />,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Conditionally loaded
|
|
114
|
+
const AdminPanel = dynamic(() => import('./AdminPanel'));
|
|
115
|
+
|
|
116
|
+
function Dashboard({ isAdmin }) {
|
|
117
|
+
return (
|
|
118
|
+
<div>
|
|
119
|
+
<Chart data={data} />
|
|
120
|
+
{isAdmin && <AdminPanel />}
|
|
121
|
+
</div>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### PERF-005: Optimize imports
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
// BAD - Imports entire library
|
|
130
|
+
import { format } from 'date-fns';
|
|
131
|
+
import _ from 'lodash';
|
|
132
|
+
|
|
133
|
+
// GOOD - Tree-shakeable imports
|
|
134
|
+
import format from 'date-fns/format';
|
|
135
|
+
import debounce from 'lodash/debounce';
|
|
136
|
+
|
|
137
|
+
// Or use lighter alternatives
|
|
138
|
+
import { formatDistance } from 'date-fns/formatDistance';
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### PERF-006: Analyze bundle size
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
// next.config.js
|
|
145
|
+
const withBundleAnalyzer = require('@next/bundle-analyzer')({
|
|
146
|
+
enabled: process.env.ANALYZE === 'true',
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
module.exports = withBundleAnalyzer({
|
|
150
|
+
// config
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Run: ANALYZE=true npm run build
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Image Optimization
|
|
159
|
+
|
|
160
|
+
### PERF-007: Use responsive images
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
<Image
|
|
164
|
+
src="/hero.jpg"
|
|
165
|
+
alt="Hero"
|
|
166
|
+
width={1200}
|
|
167
|
+
height={600}
|
|
168
|
+
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
|
169
|
+
// Generates multiple sizes, browser picks best one
|
|
170
|
+
/>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### PERF-008: Lazy load below-fold images
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
// Default behavior - lazy loaded
|
|
177
|
+
<Image
|
|
178
|
+
src="/gallery/1.jpg"
|
|
179
|
+
alt="Gallery item"
|
|
180
|
+
width={400}
|
|
181
|
+
height={300}
|
|
182
|
+
loading="lazy" // Default, can be explicit
|
|
183
|
+
/>
|
|
184
|
+
|
|
185
|
+
// Only use priority for above-fold
|
|
186
|
+
<Image
|
|
187
|
+
src="/hero.jpg"
|
|
188
|
+
priority // Only for LCP image
|
|
189
|
+
/>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### PERF-009: Use modern formats
|
|
193
|
+
|
|
194
|
+
```javascript
|
|
195
|
+
// next.config.js
|
|
196
|
+
module.exports = {
|
|
197
|
+
images: {
|
|
198
|
+
formats: ['image/avif', 'image/webp'],
|
|
199
|
+
deviceSizes: [640, 750, 828, 1080, 1200, 1920],
|
|
200
|
+
imageSizes: [16, 32, 48, 64, 96, 128, 256],
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Caching
|
|
208
|
+
|
|
209
|
+
### PERF-010: Configure fetch caching
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
// Cached by default in Server Components
|
|
213
|
+
const data = await fetch('https://api.example.com/data');
|
|
214
|
+
|
|
215
|
+
// Revalidate every hour
|
|
216
|
+
const data = await fetch('https://api.example.com/data', {
|
|
217
|
+
next: { revalidate: 3600 },
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// No cache (dynamic data)
|
|
221
|
+
const data = await fetch('https://api.example.com/data', {
|
|
222
|
+
cache: 'no-store',
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// Tags for selective revalidation
|
|
226
|
+
const data = await fetch('https://api.example.com/users', {
|
|
227
|
+
next: { tags: ['users'] },
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Revalidate by tag
|
|
231
|
+
import { revalidateTag } from 'next/cache';
|
|
232
|
+
revalidateTag('users');
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### PERF-011: Use unstable_cache for DB queries
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
import { unstable_cache } from 'next/cache';
|
|
239
|
+
|
|
240
|
+
const getCachedUser = unstable_cache(
|
|
241
|
+
async (userId: string) => {
|
|
242
|
+
return db.user.findUnique({ where: { id: userId } });
|
|
243
|
+
},
|
|
244
|
+
['user'], // Cache key parts
|
|
245
|
+
{
|
|
246
|
+
revalidate: 3600, // 1 hour
|
|
247
|
+
tags: ['users'],
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
// Usage
|
|
252
|
+
const user = await getCachedUser(userId);
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### PERF-012: Implement stale-while-revalidate
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
// Route segment config
|
|
259
|
+
export const revalidate = 60; // Revalidate at most every 60 seconds
|
|
260
|
+
|
|
261
|
+
// Or per-fetch
|
|
262
|
+
const data = await fetch(url, {
|
|
263
|
+
next: { revalidate: 60 },
|
|
264
|
+
});
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Streaming & Suspense
|
|
270
|
+
|
|
271
|
+
### PERF-013: Stream long-running data fetches
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
import { Suspense } from 'react';
|
|
275
|
+
|
|
276
|
+
export default function Page() {
|
|
277
|
+
return (
|
|
278
|
+
<div>
|
|
279
|
+
{/* Renders immediately */}
|
|
280
|
+
<Header />
|
|
281
|
+
|
|
282
|
+
{/* Streams when ready */}
|
|
283
|
+
<Suspense fallback={<StatsSkeleton />}>
|
|
284
|
+
<SlowStats />
|
|
285
|
+
</Suspense>
|
|
286
|
+
|
|
287
|
+
{/* Another stream */}
|
|
288
|
+
<Suspense fallback={<RecommendationsSkeleton />}>
|
|
289
|
+
<Recommendations />
|
|
290
|
+
</Suspense>
|
|
291
|
+
|
|
292
|
+
{/* Renders immediately */}
|
|
293
|
+
<Footer />
|
|
294
|
+
</div>
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### PERF-014: Parallel data fetching
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
// BAD - Sequential (waterfall)
|
|
303
|
+
async function Page() {
|
|
304
|
+
const user = await getUser();
|
|
305
|
+
const posts = await getPosts();
|
|
306
|
+
const comments = await getComments();
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// GOOD - Parallel
|
|
310
|
+
async function Page() {
|
|
311
|
+
const [user, posts, comments] = await Promise.all([
|
|
312
|
+
getUser(),
|
|
313
|
+
getPosts(),
|
|
314
|
+
getComments(),
|
|
315
|
+
]);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// BETTER - Stream independently
|
|
319
|
+
function Page() {
|
|
320
|
+
return (
|
|
321
|
+
<>
|
|
322
|
+
<Suspense fallback={<UserSkeleton />}>
|
|
323
|
+
<UserSection />
|
|
324
|
+
</Suspense>
|
|
325
|
+
<Suspense fallback={<PostsSkeleton />}>
|
|
326
|
+
<PostsSection />
|
|
327
|
+
</Suspense>
|
|
328
|
+
</>
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Font Optimization
|
|
336
|
+
|
|
337
|
+
### PERF-015: Use next/font
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
// app/layout.tsx
|
|
341
|
+
import { Inter, Roboto_Mono } from 'next/font/google';
|
|
342
|
+
|
|
343
|
+
const inter = Inter({
|
|
344
|
+
subsets: ['latin'],
|
|
345
|
+
display: 'swap',
|
|
346
|
+
variable: '--font-inter',
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
const robotoMono = Roboto_Mono({
|
|
350
|
+
subsets: ['latin'],
|
|
351
|
+
display: 'swap',
|
|
352
|
+
variable: '--font-roboto-mono',
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
export default function RootLayout({ children }) {
|
|
356
|
+
return (
|
|
357
|
+
<html className={`${inter.variable} ${robotoMono.variable}`}>
|
|
358
|
+
<body className="font-sans">{children}</body>
|
|
359
|
+
</html>
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// tailwind.config.js
|
|
364
|
+
module.exports = {
|
|
365
|
+
theme: {
|
|
366
|
+
fontFamily: {
|
|
367
|
+
sans: ['var(--font-inter)'],
|
|
368
|
+
mono: ['var(--font-roboto-mono)'],
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
};
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Monitoring
|
|
377
|
+
|
|
378
|
+
### PERF-016: Track Web Vitals
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
// app/layout.tsx
|
|
382
|
+
import { SpeedInsights } from '@vercel/speed-insights/next';
|
|
383
|
+
import { Analytics } from '@vercel/analytics/react';
|
|
384
|
+
|
|
385
|
+
export default function RootLayout({ children }) {
|
|
386
|
+
return (
|
|
387
|
+
<html>
|
|
388
|
+
<body>
|
|
389
|
+
{children}
|
|
390
|
+
<SpeedInsights />
|
|
391
|
+
<Analytics />
|
|
392
|
+
</body>
|
|
393
|
+
</html>
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Or custom reporting
|
|
398
|
+
// app/web-vitals.ts
|
|
399
|
+
export function reportWebVitals(metric) {
|
|
400
|
+
console.log(metric);
|
|
401
|
+
// Send to analytics
|
|
402
|
+
}
|
|
403
|
+
```
|