cc-codeconductor 0.2.1

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 (93) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +319 -0
  3. package/dist/index.js +12741 -0
  4. package/package.json +51 -0
  5. package/policy.yml +124 -0
  6. package/presets/claude/CLAUDE.md +598 -0
  7. package/presets/claude/commands/cc/feature.md +115 -0
  8. package/presets/claude/commands/cc/fix.md +121 -0
  9. package/presets/claude/commands/cc/refactor.md +148 -0
  10. package/presets/claude/commands/cc/review.md +126 -0
  11. package/presets/claude/commands/cc/tdd-cycle.md +226 -0
  12. package/presets/claude/commands/cc/test-plan.md +138 -0
  13. package/presets/claude/settings.json +37 -0
  14. package/presets/claude/skills/api-versioning/SKILL.md +389 -0
  15. package/presets/claude/skills/django-orm/SKILL.md +455 -0
  16. package/presets/claude/skills/django-testing/SKILL.md +409 -0
  17. package/presets/claude/skills/jpa-postgres/SKILL.md +618 -0
  18. package/presets/claude/skills/python/SKILL.md +606 -0
  19. package/presets/claude/skills/python-django-stack/SKILL.md +492 -0
  20. package/presets/claude/skills/python-fastapi-stack/SKILL.md +457 -0
  21. package/presets/claude/skills/spring-boot-feature/SKILL.md +558 -0
  22. package/presets/claude/skills/spring-boot-kotlin/SKILL.md +400 -0
  23. package/presets/claude/skills/sqlalchemy/SKILL.md +466 -0
  24. package/presets/claude/skills/testing-strategy/SKILL.md +479 -0
  25. package/presets/codex/AGENTS.md +883 -0
  26. package/presets/codex/README.md +102 -0
  27. package/presets/codex/skills/api-versioning/SKILL.md +389 -0
  28. package/presets/codex/skills/django-orm/SKILL.md +455 -0
  29. package/presets/codex/skills/django-testing/SKILL.md +409 -0
  30. package/presets/codex/skills/jpa-postgres/SKILL.md +618 -0
  31. package/presets/codex/skills/python/SKILL.md +606 -0
  32. package/presets/codex/skills/python-django-stack/SKILL.md +492 -0
  33. package/presets/codex/skills/python-fastapi-stack/SKILL.md +457 -0
  34. package/presets/codex/skills/spring-boot-feature/SKILL.md +558 -0
  35. package/presets/codex/skills/spring-boot-kotlin/SKILL.md +400 -0
  36. package/presets/codex/skills/sqlalchemy/SKILL.md +466 -0
  37. package/presets/codex/skills/testing-strategy/SKILL.md +479 -0
  38. package/presets/opencode/README.md +191 -0
  39. package/presets/opencode/agents/architect.md +133 -0
  40. package/presets/opencode/agents/docs.md +113 -0
  41. package/presets/opencode/agents/implementer.md +116 -0
  42. package/presets/opencode/agents/orchestrator.md +248 -0
  43. package/presets/opencode/agents/repo-explorer.md +119 -0
  44. package/presets/opencode/agents/reviewer.md +130 -0
  45. package/presets/opencode/agents/task-coach.md +103 -0
  46. package/presets/opencode/agents/tester.md +269 -0
  47. package/presets/opencode/commands/cc-feature.md +114 -0
  48. package/presets/opencode/commands/cc-fix.md +123 -0
  49. package/presets/opencode/commands/cc-refactor.md +148 -0
  50. package/presets/opencode/commands/cc-review.md +141 -0
  51. package/presets/opencode/commands/cc-tdd-cycle.md +225 -0
  52. package/presets/opencode/commands/cc-test-plan.md +144 -0
  53. package/presets/opencode/opencode.jsonc +89 -0
  54. package/presets/opencode/prompts/v0.1.0/architect.md +213 -0
  55. package/presets/opencode/prompts/v0.1.0/docs.md +181 -0
  56. package/presets/opencode/prompts/v0.1.0/implementer.md +154 -0
  57. package/presets/opencode/prompts/v0.1.0/orchestrator.md +169 -0
  58. package/presets/opencode/prompts/v0.1.0/repo-explorer.md +102 -0
  59. package/presets/opencode/prompts/v0.1.0/reviewer.md +183 -0
  60. package/presets/opencode/prompts/v0.1.0/task-coach.md +142 -0
  61. package/presets/opencode/prompts/v0.1.0/tester.md +160 -0
  62. package/presets/opencode/prompts/v0.2.0/architect.md +219 -0
  63. package/presets/opencode/prompts/v0.2.0/docs.md +187 -0
  64. package/presets/opencode/prompts/v0.2.0/implementer.md +160 -0
  65. package/presets/opencode/prompts/v0.2.0/orchestrator.md +238 -0
  66. package/presets/opencode/prompts/v0.2.0/repo-explorer.md +108 -0
  67. package/presets/opencode/prompts/v0.2.0/reviewer.md +190 -0
  68. package/presets/opencode/prompts/v0.2.0/task-coach.md +153 -0
  69. package/presets/opencode/prompts/v0.2.0/tester.md +249 -0
  70. package/presets/opencode/skills/api-versioning/SKILL.md +388 -0
  71. package/presets/opencode/skills/astro/SKILL.md +313 -0
  72. package/presets/opencode/skills/code-review/SKILL.md +202 -0
  73. package/presets/opencode/skills/django-orm/SKILL.md +455 -0
  74. package/presets/opencode/skills/django-testing/SKILL.md +408 -0
  75. package/presets/opencode/skills/django-uv/SKILL.md +400 -0
  76. package/presets/opencode/skills/jpa-postgres/SKILL.md +617 -0
  77. package/presets/opencode/skills/nextjs-typescript/SKILL.md +385 -0
  78. package/presets/opencode/skills/python/SKILL.md +605 -0
  79. package/presets/opencode/skills/python-django-stack/SKILL.md +491 -0
  80. package/presets/opencode/skills/python-fastapi-stack/SKILL.md +456 -0
  81. package/presets/opencode/skills/security/SKILL.md +376 -0
  82. package/presets/opencode/skills/spring-boot-feature/SKILL.md +557 -0
  83. package/presets/opencode/skills/spring-boot-kotlin/SKILL.md +399 -0
  84. package/presets/opencode/skills/spring-boot-testing-strategy/SKILL.md +470 -0
  85. package/presets/opencode/skills/sqlalchemy/SKILL.md +465 -0
  86. package/presets/opencode/skills/testing-tdd/SKILL.md +586 -0
  87. package/src/presets/council/council.yml +59 -0
  88. package/src/presets/manifests/claude.yml +23 -0
  89. package/src/presets/manifests/codex.yml +12 -0
  90. package/src/presets/manifests/opencode.yml +18 -0
  91. package/src/presets/models/claude.yml +37 -0
  92. package/src/presets/models/codex.yml +38 -0
  93. package/src/presets/models/opencode.yml +37 -0
@@ -0,0 +1,385 @@
1
+ ---
2
+ id: nextjs-typescript
3
+ version: 1.0.0
4
+ name: Next.js + TypeScript
5
+ description: >
6
+ Provides expert knowledge for building Next.js 15+ applications with the App Router, TypeScript, Server Components, Server Actions, and TanStack Query.
7
+
8
+ compatibility:
9
+ tools: [claude, codex, opencode]
10
+ stacks:
11
+ languages: []
12
+ frameworks: []
13
+
14
+ risk:
15
+ level: medium
16
+ can_execute_shell: false
17
+ can_modify_files: true
18
+ requires_network: false
19
+
20
+ inputs: []
21
+
22
+ outputs: []
23
+
24
+ quality:
25
+ reviewed_by: codeconductor-core
26
+ version: 0.1.0
27
+ ---
28
+
29
+
30
+
31
+ # Next.js + TypeScript
32
+
33
+ ## Server vs Client Components
34
+
35
+ The App Router defaults to Server Components. Every component is a Server
36
+ Component unless it explicitly opts in to the client.
37
+
38
+ ### Decision Rule
39
+
40
+ ```text
41
+ Does the component need any of the following?
42
+ - useState / useReducer
43
+ - useEffect / lifecycle methods
44
+ - Browser APIs (window, document, localStorage)
45
+ - Event listeners (onClick, onChange, onSubmit)
46
+ - Third-party libraries that require the DOM
47
+
48
+ YES → Client Component (`"use client"` directive)
49
+ NO → Server Component (default, no directive needed)
50
+ ```
51
+
52
+ Keep the `"use client"` boundary as far down the component tree as possible.
53
+ Wrap only the interactive leaf node, not the entire page.
54
+
55
+ ### Server Component (default)
56
+
57
+ ```tsx
58
+ // app/users/page.tsx — no directive needed
59
+ import { db } from '@/lib/db';
60
+
61
+ export default async function UsersPage() {
62
+ // Direct database access — no API round-trip needed
63
+ const users = await db.user.findMany({ orderBy: { createdAt: 'desc' } });
64
+
65
+ return (
66
+ <ul>
67
+ {users.map(user => (
68
+ <li key={user.id}>{user.email}</li>
69
+ ))}
70
+ </ul>
71
+ );
72
+ }
73
+ ```
74
+
75
+ ### Client Component
76
+
77
+ ```tsx
78
+ // components/ui/counter.tsx
79
+ 'use client';
80
+
81
+ import { useState } from 'react';
82
+
83
+ interface Props {
84
+ initialCount?: number;
85
+ }
86
+
87
+ export function Counter({ initialCount = 0 }: Props) {
88
+ const [count, setCount] = useState(initialCount);
89
+ return <button onClick={() => setCount(c => c + 1)}>Count: {count}</button>;
90
+ }
91
+ ```
92
+
93
+ ### Composing Server and Client
94
+
95
+ ```tsx
96
+ // app/dashboard/page.tsx — Server Component
97
+ import { Counter } from '@/components/ui/counter'; // Client
98
+ import { getUser } from '@/lib/queries'; // Server-only function
99
+
100
+ export default async function DashboardPage() {
101
+ const user = await getUser(); // runs on the server
102
+
103
+ return (
104
+ <div>
105
+ <h1>Welcome, {user.name}</h1>
106
+ <Counter initialCount={user.loginCount} /> {/* client island */}
107
+ </div>
108
+ );
109
+ }
110
+ ```
111
+
112
+ Passing server data to client components as props is correct. The server
113
+ renders the Server Component tree first, serializes the props, and sends them
114
+ to the client.
115
+
116
+ ## Data Fetching
117
+
118
+ ### Server Component Fetching (recommended for initial data)
119
+
120
+ ```tsx
121
+ // app/posts/[id]/page.tsx
122
+ interface Props {
123
+ params: Promise<{ id: string }>;
124
+ }
125
+
126
+ export default async function PostPage({ params }: Props) {
127
+ const { id } = await params;
128
+ const post = await fetch(`https://api.example.com/posts/${id}`, {
129
+ next: { revalidate: 3600 }, // ISR: revalidate every hour
130
+ }).then(r => r.json());
131
+
132
+ if (!post) notFound();
133
+
134
+ return <article>{post.title}</article>;
135
+ }
136
+ ```
137
+
138
+ Cache strategies:
139
+
140
+ | `cache` option | Behavior |
141
+ |----------------|----------|
142
+ | `force-cache` | Cache indefinitely (default for fetch in RSC) |
143
+ | `no-store` | Never cache — fresh on every request |
144
+ | `next: { revalidate: N }` | ISR — revalidate after N seconds |
145
+ | `next: { tags: ['posts'] }` | On-demand revalidation via tag |
146
+
147
+ ### Server Actions (mutations)
148
+
149
+ Server Actions run on the server. Use them for form submissions and mutations.
150
+ Never use them for reads.
151
+
152
+ ```tsx
153
+ // app/posts/create/actions.ts
154
+ 'use server';
155
+
156
+ import { revalidatePath } from 'next/cache';
157
+ import { redirect } from 'next/navigation';
158
+ import { z } from 'zod';
159
+ import { db } from '@/lib/db';
160
+
161
+ const CreatePostSchema = z.object({
162
+ title: z.string().min(1).max(200),
163
+ content: z.string().min(1),
164
+ });
165
+
166
+ export async function createPost(formData: FormData) {
167
+ const parsed = CreatePostSchema.safeParse({
168
+ title: formData.get('title'),
169
+ content: formData.get('content'),
170
+ });
171
+
172
+ if (!parsed.success) {
173
+ return { error: parsed.error.flatten().fieldErrors };
174
+ }
175
+
176
+ await db.post.create({ data: parsed.data });
177
+
178
+ revalidatePath('/posts');
179
+ redirect('/posts');
180
+ }
181
+ ```
182
+
183
+ ```tsx
184
+ // app/posts/create/page.tsx
185
+ import { createPost } from './actions';
186
+
187
+ export default function CreatePostPage() {
188
+ return (
189
+ <form action={createPost}>
190
+ <input name="title" type="text" required />
191
+ <textarea name="content" required />
192
+ <button type="submit">Create</button>
193
+ </form>
194
+ );
195
+ }
196
+ ```
197
+
198
+ Rules for Server Actions:
199
+
200
+ - Always validate input with Zod — do not trust `FormData` values
201
+ - Return error objects for validation failures; use `redirect()` for success
202
+ - Call `revalidatePath()` or `revalidateTag()` after mutations that affect
203
+ cached data
204
+ - Never put secrets or auth logic in Client Components — keep it in actions
205
+
206
+ ### TanStack Query (client-side data)
207
+
208
+ Use TanStack Query for data that must stay fresh on the client: real-time
209
+ feeds, user-specific data after mutations, optimistic updates.
210
+
211
+ ```tsx
212
+ // components/posts/post-list.tsx
213
+ 'use client';
214
+
215
+ import { useQuery } from '@tanstack/react-query';
216
+
217
+ interface Post {
218
+ id: string;
219
+ title: string;
220
+ }
221
+
222
+ export function PostList() {
223
+ const { data, isLoading, error } = useQuery<Post[]>({
224
+ queryKey: ['posts'],
225
+ queryFn: () => fetch('/api/posts').then(r => r.json()),
226
+ staleTime: 60_000, // treat data as fresh for 60 seconds
227
+ });
228
+
229
+ if (isLoading) return <p>Loading...</p>;
230
+ if (error) return <p>Failed to load posts.</p>;
231
+
232
+ return (
233
+ <ul>
234
+ {data?.map(post => <li key={post.id}>{post.title}</li>)}
235
+ </ul>
236
+ );
237
+ }
238
+ ```
239
+
240
+ Do not use TanStack Query for data that a Server Component can fetch directly.
241
+ The extra client-side fetch is unnecessary when the data can be fetched at
242
+ render time on the server.
243
+
244
+ ## Route Handlers
245
+
246
+ Use route handlers for: webhooks, third-party OAuth callbacks, or endpoints
247
+ consumed by non-Next.js clients.
248
+
249
+ ```typescript
250
+ // app/api/posts/route.ts
251
+ import { NextRequest, NextResponse } from 'next/server';
252
+ import { z } from 'zod';
253
+ import { db } from '@/lib/db';
254
+
255
+ const CreatePostBody = z.object({
256
+ title: z.string().min(1),
257
+ content: z.string().min(1),
258
+ });
259
+
260
+ export async function GET() {
261
+ const posts = await db.post.findMany({ orderBy: { createdAt: 'desc' } });
262
+ return NextResponse.json(posts);
263
+ }
264
+
265
+ export async function POST(request: NextRequest) {
266
+ const body = await request.json();
267
+ const parsed = CreatePostBody.safeParse(body);
268
+
269
+ if (!parsed.success) {
270
+ return NextResponse.json(
271
+ { error: parsed.error.flatten() },
272
+ { status: 400 }
273
+ );
274
+ }
275
+
276
+ const post = await db.post.create({ data: parsed.data });
277
+ return NextResponse.json(post, { status: 201 });
278
+ }
279
+ ```
280
+
281
+ ## Metadata API
282
+
283
+ ```tsx
284
+ // app/posts/[id]/page.tsx
285
+ import type { Metadata } from 'next';
286
+
287
+ interface Props {
288
+ params: Promise<{ id: string }>;
289
+ }
290
+
291
+ export async function generateMetadata({ params }: Props): Promise<Metadata> {
292
+ const { id } = await params;
293
+ const post = await fetch(`/api/posts/${id}`).then(r => r.json());
294
+
295
+ return {
296
+ title: post.title,
297
+ description: post.excerpt,
298
+ openGraph: {
299
+ title: post.title,
300
+ images: [{ url: post.coverImage }],
301
+ },
302
+ };
303
+ }
304
+ ```
305
+
306
+ Never hardcode metadata in `<head>` tags — use the Metadata API. It handles
307
+ deduplication, inheritance, and streaming correctly.
308
+
309
+ ## Streaming with Suspense
310
+
311
+ ```tsx
312
+ // app/dashboard/page.tsx
313
+ import { Suspense } from 'react';
314
+ import { UserStats } from './user-stats'; // slow data fetch
315
+ import { RecentActivity } from './recent'; // fast data fetch
316
+
317
+ export default function DashboardPage() {
318
+ return (
319
+ <div>
320
+ <RecentActivity /> {/* renders immediately */}
321
+ <Suspense fallback={<p>Loading stats...</p>}>
322
+ <UserStats /> {/* streams in when ready */}
323
+ </Suspense>
324
+ </div>
325
+ );
326
+ }
327
+ ```
328
+
329
+ Wrap independently slow data sources in their own `<Suspense>` boundaries.
330
+ Do not wrap the entire page — that defeats streaming.
331
+
332
+ ## TypeScript Conventions
333
+
334
+ ```typescript
335
+ // Use type imports for type-only imports
336
+ import type { User } from '@prisma/client';
337
+
338
+ // Prefer interfaces for object shapes that may be extended
339
+ interface UserCardProps {
340
+ user: Pick<User, 'id' | 'name' | 'email'>;
341
+ onSelect?: (id: string) => void;
342
+ }
343
+
344
+ // Use type aliases for unions and computed types
345
+ type Status = 'active' | 'inactive' | 'pending';
346
+ type UserWithPosts = User & { posts: Post[] };
347
+ ```
348
+
349
+ Rules:
350
+
351
+ - Never use `any` — use `unknown` and narrow with type guards
352
+ - Use `satisfies` to validate objects against a type without widening
353
+ - Co-locate type definitions with the component or function that uses them;
354
+ export only what other modules need
355
+ - Use `next/navigation` hooks (`useRouter`, `usePathname`) not `next/router` —
356
+ the latter is Pages Router only
357
+
358
+ ## Project Structure
359
+
360
+ ```text
361
+ app/
362
+ (auth)/ — route group, no URL segment
363
+ login/page.tsx
364
+ register/page.tsx
365
+ (dashboard)/
366
+ dashboard/page.tsx
367
+ posts/
368
+ [id]/page.tsx
369
+ create/
370
+ page.tsx
371
+ actions.ts
372
+ api/
373
+ posts/route.ts
374
+ layout.tsx — root layout
375
+ not-found.tsx
376
+
377
+ components/
378
+ ui/ — generic, reusable components
379
+ posts/ — domain-specific components
380
+
381
+ lib/
382
+ db.ts — database client
383
+ auth.ts — auth configuration
384
+ queries.ts — reusable server-side query functions
385
+ ```