@caddis/cli 0.0.0 → 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.
Files changed (153) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -1
  3. package/bundles/antigravity-plugin/agents/code-reviewer.md +47 -0
  4. package/bundles/antigravity-plugin/agents/preflight.md +53 -0
  5. package/bundles/antigravity-plugin/guard_agy.py +338 -0
  6. package/bundles/antigravity-plugin/hooks.json +36 -0
  7. package/bundles/antigravity-plugin/mcp_config.json +8 -0
  8. package/bundles/antigravity-plugin/mcp_ping_server.py +55 -0
  9. package/bundles/antigravity-plugin/plugin.json +5 -0
  10. package/bundles/antigravity-plugin/session_end_agy.py +57 -0
  11. package/bundles/antigravity-plugin/skills/_registry.md +115 -0
  12. package/bundles/antigravity-plugin/skills/add-rules/SKILL.md +45 -0
  13. package/bundles/antigravity-plugin/skills/api-design/SKILL.md +249 -0
  14. package/bundles/antigravity-plugin/skills/backend-development/SKILL.md +305 -0
  15. package/bundles/antigravity-plugin/skills/best-practices/SKILL.md +500 -0
  16. package/bundles/antigravity-plugin/skills/best-practices/agents/best-practices-referencer.md +263 -0
  17. package/bundles/antigravity-plugin/skills/best-practices/agents/codebase-context-builder.md +326 -0
  18. package/bundles/antigravity-plugin/skills/best-practices/agents/task-intent-analyzer.md +245 -0
  19. package/bundles/antigravity-plugin/skills/best-practices/references/anti-patterns.md +571 -0
  20. package/bundles/antigravity-plugin/skills/best-practices/references/before-after-examples.md +1114 -0
  21. package/bundles/antigravity-plugin/skills/best-practices/references/best-practices-guide.md +513 -0
  22. package/bundles/antigravity-plugin/skills/best-practices/references/common-workflows.md +692 -0
  23. package/bundles/antigravity-plugin/skills/best-practices/references/prompt-patterns.md +547 -0
  24. package/bundles/antigravity-plugin/skills/brainstorming/SKILL.md +57 -0
  25. package/bundles/antigravity-plugin/skills/ci-cd-pipeline/SKILL.md +315 -0
  26. package/bundles/antigravity-plugin/skills/code-documentation/SKILL.md +271 -0
  27. package/bundles/antigravity-plugin/skills/code-review/SKILL.md +122 -0
  28. package/bundles/antigravity-plugin/skills/codebase-audit/SKILL.md +204 -0
  29. package/bundles/antigravity-plugin/skills/context-curator/SKILL.md +157 -0
  30. package/bundles/antigravity-plugin/skills/cross-review/SKILL.md +40 -0
  31. package/bundles/antigravity-plugin/skills/css-architecture/SKILL.md +305 -0
  32. package/bundles/antigravity-plugin/skills/css-architecture/references/RESPONSIVE-DESIGN.md +604 -0
  33. package/bundles/antigravity-plugin/skills/database-design/SKILL.md +177 -0
  34. package/bundles/antigravity-plugin/skills/db-diagram/SKILL.md +148 -0
  35. package/bundles/antigravity-plugin/skills/db-diagram/scripts/sql_to_graph.py +1212 -0
  36. package/bundles/antigravity-plugin/skills/digress/SKILL.md +61 -0
  37. package/bundles/antigravity-plugin/skills/draw-io/SKILL.md +162 -0
  38. package/bundles/antigravity-plugin/skills/draw-io/references/aws-icons.md +677 -0
  39. package/bundles/antigravity-plugin/skills/draw-io/references/layout-guidelines.md +142 -0
  40. package/bundles/antigravity-plugin/skills/draw-io/references/troubleshooting.md +118 -0
  41. package/bundles/antigravity-plugin/skills/draw-io/references/workflows.md +103 -0
  42. package/bundles/antigravity-plugin/skills/draw-io/scripts/convert-drawio-to-png.sh +25 -0
  43. package/bundles/antigravity-plugin/skills/draw-io/scripts/find_aws_icon.py +79 -0
  44. package/bundles/antigravity-plugin/skills/error-handling/SKILL.md +260 -0
  45. package/bundles/antigravity-plugin/skills/excalidraw-db/SKILL.md +38 -0
  46. package/bundles/antigravity-plugin/skills/fastapi-dev/SKILL.md +300 -0
  47. package/bundles/antigravity-plugin/skills/feature-plan/SKILL.md +198 -0
  48. package/bundles/antigravity-plugin/skills/frontend-design/SKILL.md +193 -0
  49. package/bundles/antigravity-plugin/skills/frontend-design/references/my-tech-stack.md +127 -0
  50. package/bundles/antigravity-plugin/skills/gh-cli/SKILL.md +195 -0
  51. package/bundles/antigravity-plugin/skills/git-commit/SKILL.md +285 -0
  52. package/bundles/antigravity-plugin/skills/golden-plan/SKILL.md +577 -0
  53. package/bundles/antigravity-plugin/skills/handoff/SKILL.md +100 -0
  54. package/bundles/antigravity-plugin/skills/implement/SKILL.md +114 -0
  55. package/bundles/antigravity-plugin/skills/javascript-typescript/SKILL.md +142 -0
  56. package/bundles/antigravity-plugin/skills/kb/SKILL.md +60 -0
  57. package/bundles/antigravity-plugin/skills/mermaid-db/SKILL.md +33 -0
  58. package/bundles/antigravity-plugin/skills/mermaid-diagrams/SKILL.md +236 -0
  59. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/ENHANCEMENTS.md +264 -0
  60. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/MERMAID-SUMMARY.md +137 -0
  61. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/advanced-features.md +556 -0
  62. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/architecture-diagrams.md +192 -0
  63. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/c4-diagrams.md +410 -0
  64. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/class-diagrams.md +361 -0
  65. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/erd-diagrams.md +510 -0
  66. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/flowcharts.md +450 -0
  67. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/sequence-diagrams.md +394 -0
  68. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/troubleshooting.md +335 -0
  69. package/bundles/antigravity-plugin/skills/mermaid-diagrams/references/workflows.md +418 -0
  70. package/bundles/antigravity-plugin/skills/migrate-dir/SKILL.md +68 -0
  71. package/bundles/antigravity-plugin/skills/mockup/SKILL.md +242 -0
  72. package/bundles/antigravity-plugin/skills/particle-art/SKILL.md +243 -0
  73. package/bundles/antigravity-plugin/skills/particle-art/references/canvas-utils.ts +171 -0
  74. package/bundles/antigravity-plugin/skills/particle-art/references/dot-field.template.tsx +203 -0
  75. package/bundles/antigravity-plugin/skills/particle-art/references/flow-field.template.tsx +263 -0
  76. package/bundles/antigravity-plugin/skills/particle-art/references/node-shape.template.tsx +261 -0
  77. package/bundles/antigravity-plugin/skills/particle-art/references/shape-sampler.ts +281 -0
  78. package/bundles/antigravity-plugin/skills/particle-art/references/stipple-morph.template.tsx +167 -0
  79. package/bundles/antigravity-plugin/skills/particle-art/references/stipple.template.tsx +175 -0
  80. package/bundles/antigravity-plugin/skills/particle-art/references/trail-ghost.template.tsx +266 -0
  81. package/bundles/antigravity-plugin/skills/particle-art/references/usage-examples.md +320 -0
  82. package/bundles/antigravity-plugin/skills/playwright/API_REFERENCE.md +653 -0
  83. package/bundles/antigravity-plugin/skills/playwright/SKILL.md +454 -0
  84. package/bundles/antigravity-plugin/skills/playwright/lib/helpers.js +441 -0
  85. package/bundles/antigravity-plugin/skills/playwright/package.json +26 -0
  86. package/bundles/antigravity-plugin/skills/playwright/run.js +228 -0
  87. package/bundles/antigravity-plugin/skills/prd/SKILL.md +107 -0
  88. package/bundles/antigravity-plugin/skills/preflight/SKILL.md +435 -0
  89. package/bundles/antigravity-plugin/skills/python/SKILL.md +388 -0
  90. package/bundles/antigravity-plugin/skills/react-best-practices/SKILL.md +269 -0
  91. package/bundles/antigravity-plugin/skills/react-dev/README.md +404 -0
  92. package/bundles/antigravity-plugin/skills/react-dev/SKILL.md +459 -0
  93. package/bundles/antigravity-plugin/skills/react-dev/examples/generic-components.md +579 -0
  94. package/bundles/antigravity-plugin/skills/react-dev/examples/server-components.md +579 -0
  95. package/bundles/antigravity-plugin/skills/react-dev/references/event-handlers.md +574 -0
  96. package/bundles/antigravity-plugin/skills/react-dev/references/hooks.md +456 -0
  97. package/bundles/antigravity-plugin/skills/react-dev/references/react-19-patterns.md +638 -0
  98. package/bundles/antigravity-plugin/skills/react-dev/references/react-router.md +1002 -0
  99. package/bundles/antigravity-plugin/skills/react-dev/references/tanstack-router.md +587 -0
  100. package/bundles/antigravity-plugin/skills/refactoring/SKILL.md +486 -0
  101. package/bundles/antigravity-plugin/skills/resume/SKILL.md +36 -0
  102. package/bundles/antigravity-plugin/skills/security-review/SKILL.md +196 -0
  103. package/bundles/antigravity-plugin/skills/setup-project-ai/SKILL.md +61 -0
  104. package/bundles/antigravity-plugin/skills/ship/SKILL.md +107 -0
  105. package/bundles/antigravity-plugin/skills/ship-merge/SKILL.md +103 -0
  106. package/bundles/antigravity-plugin/skills/ship-pr/SKILL.md +102 -0
  107. package/bundles/antigravity-plugin/skills/skill-creator/LICENSE.txt +202 -0
  108. package/bundles/antigravity-plugin/skills/skill-creator/SKILL.md +491 -0
  109. package/bundles/antigravity-plugin/skills/skill-creator/agents/analyzer.md +274 -0
  110. package/bundles/antigravity-plugin/skills/skill-creator/agents/comparator.md +202 -0
  111. package/bundles/antigravity-plugin/skills/skill-creator/agents/grader.md +223 -0
  112. package/bundles/antigravity-plugin/skills/skill-creator/assets/eval_review.html +146 -0
  113. package/bundles/antigravity-plugin/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  114. package/bundles/antigravity-plugin/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  115. package/bundles/antigravity-plugin/skills/skill-creator/references/schemas.md +430 -0
  116. package/bundles/antigravity-plugin/skills/skill-creator/scripts/__init__.py +0 -0
  117. package/bundles/antigravity-plugin/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  118. package/bundles/antigravity-plugin/skills/skill-creator/scripts/generate_report.py +326 -0
  119. package/bundles/antigravity-plugin/skills/skill-creator/scripts/improve_description.py +247 -0
  120. package/bundles/antigravity-plugin/skills/skill-creator/scripts/package_skill.py +136 -0
  121. package/bundles/antigravity-plugin/skills/skill-creator/scripts/quick_validate.py +103 -0
  122. package/bundles/antigravity-plugin/skills/skill-creator/scripts/run_eval.py +310 -0
  123. package/bundles/antigravity-plugin/skills/skill-creator/scripts/run_loop.py +328 -0
  124. package/bundles/antigravity-plugin/skills/skill-creator/scripts/utils.py +47 -0
  125. package/bundles/antigravity-plugin/skills/sql/SKILL.md +321 -0
  126. package/bundles/antigravity-plugin/skills/tdd/SKILL.md +37 -0
  127. package/bundles/antigravity-plugin/skills/tdd-workflow/SKILL.md +188 -0
  128. package/bundles/antigravity-plugin/skills/technical-writing/SKILL.md +286 -0
  129. package/bundles/antigravity-plugin/skills/test-strategy/SKILL.md +155 -0
  130. package/bundles/antigravity-plugin/skills/ui-brief/SKILL.md +84 -0
  131. package/bundles/antigravity-plugin/skills/ui-review/SKILL.md +176 -0
  132. package/bundles/antigravity-plugin/skills/ui-review/references/framework-fixes.md +471 -0
  133. package/bundles/antigravity-plugin/skills/ui-review/references/visual-checklist.md +236 -0
  134. package/bundles/antigravity-plugin/skills/usage-review/SKILL.md +77 -0
  135. package/bundles/antigravity-plugin/skills/use-model/SKILL.md +64 -0
  136. package/bundles/antigravity-plugin/skills/using-git-worktrees/SKILL.md +217 -0
  137. package/bundles/antigravity-plugin/skills/version/SKILL.md +18 -0
  138. package/bundles/antigravity-plugin/skills/warm-editorial-ui/DESIGN_TOKENS.md +487 -0
  139. package/bundles/antigravity-plugin/skills/warm-editorial-ui/IMPLEMENTATION_GUIDE.md +177 -0
  140. package/bundles/antigravity-plugin/skills/warm-editorial-ui/SKILL.md +732 -0
  141. package/bundles/antigravity-plugin/skills/webapp-testing/LICENSE.txt +202 -0
  142. package/bundles/antigravity-plugin/skills/webapp-testing/SKILL.md +97 -0
  143. package/bundles/antigravity-plugin/skills/webapp-testing/examples/console_logging.py +35 -0
  144. package/bundles/antigravity-plugin/skills/webapp-testing/examples/element_discovery.py +40 -0
  145. package/bundles/antigravity-plugin/skills/webapp-testing/examples/static_html_automation.py +33 -0
  146. package/bundles/antigravity-plugin/skills/webapp-testing/scripts/with_server.py +106 -0
  147. package/bundles/antigravity-plugin/skills/windows-deployment/SKILL.md +880 -0
  148. package/bundles/antigravity-plugin/skills/writing-plans/SKILL.md +384 -0
  149. package/bundles/antigravity-plugin/statusline-command-agy.sh +91 -0
  150. package/bundles/antigravity-plugin/warm_start_agy.py +149 -0
  151. package/bundles/manifest.json +6 -0
  152. package/dist/cli.js +5363 -0
  153. package/package.json +61 -4
@@ -0,0 +1,579 @@
1
+ # Server Components and Server Actions
2
+
3
+ React 19 Server Components run on server, can be async, enable zero-bundle data fetching. Server Actions handle mutations with progressive enhancement.
4
+
5
+ ## Async Server Component
6
+
7
+ Server Components can be async functions — await data fetching directly.
8
+
9
+ ```typescript
10
+ // app/users/[id]/page.tsx
11
+ type PageProps = {
12
+ params: { id: string };
13
+ searchParams?: { tab?: string; edit?: string };
14
+ };
15
+
16
+ export default async function UserPage({ params, searchParams }: PageProps) {
17
+ // Runs on server - no client bundle
18
+ const user = await fetchUser(params.id);
19
+ const posts = await fetchUserPosts(params.id);
20
+
21
+ return (
22
+ <div>
23
+ <header>
24
+ <h1>{user.name}</h1>
25
+ <p>{user.email}</p>
26
+ </header>
27
+
28
+ <UserTabs user={user} posts={posts} activeTab={searchParams?.tab} />
29
+
30
+ {searchParams?.edit === 'true' && (
31
+ <UserEditForm user={user} />
32
+ )}
33
+ </div>
34
+ );
35
+ }
36
+
37
+ async function fetchUser(id: string): Promise<User> {
38
+ const res = await fetch(`https://api.example.com/users/${id}`, {
39
+ cache: 'no-store', // Or 'force-cache', 'revalidate'
40
+ });
41
+ if (!res.ok) throw new Error('Failed to fetch user');
42
+ return res.json();
43
+ }
44
+ ```
45
+
46
+ ## Parallel Data Fetching
47
+
48
+ Fetch multiple resources in parallel with Promise.all.
49
+
50
+ ```typescript
51
+ type DashboardProps = {
52
+ params: { userId: string };
53
+ };
54
+
55
+ export default async function Dashboard({ params }: DashboardProps) {
56
+ // Parallel fetching
57
+ const [user, stats, activity] = await Promise.all([
58
+ fetchUser(params.userId),
59
+ fetchUserStats(params.userId),
60
+ fetchRecentActivity(params.userId),
61
+ ]);
62
+
63
+ return (
64
+ <div>
65
+ <UserHeader user={user} />
66
+ <StatsGrid stats={stats} />
67
+ <ActivityFeed items={activity} />
68
+ </div>
69
+ );
70
+ }
71
+ ```
72
+
73
+ ## Sequential vs Waterfall Fetching
74
+
75
+ ```typescript
76
+ // ❌ Waterfall - slow
77
+ async function SlowPage() {
78
+ const user = await fetchUser('123');
79
+ const posts = await fetchUserPosts(user.id); // Waits for user
80
+ const comments = await fetchPostComments(posts[0].id); // Waits for posts
81
+ return <div>...</div>;
82
+ }
83
+
84
+ // ✅ Parallel - fast
85
+ async function FastPage() {
86
+ const userPromise = fetchUser('123');
87
+ const postsPromise = fetchUserPosts('123');
88
+
89
+ const [user, posts] = await Promise.all([userPromise, postsPromise]);
90
+
91
+ // If comments depend on posts, fetch after
92
+ const comments = await fetchPostComments(posts[0].id);
93
+
94
+ return <div>...</div>;
95
+ }
96
+ ```
97
+
98
+ ## Server Actions - Form Mutations
99
+
100
+ Server Actions marked with 'use server' — run on server, callable from client.
101
+
102
+ ```typescript
103
+ // actions/user.ts
104
+ 'use server';
105
+
106
+ import { revalidatePath, revalidateTag } from 'next/cache';
107
+ import { redirect } from 'next/navigation';
108
+ import { z } from 'zod';
109
+
110
+ const updateUserSchema = z.object({
111
+ name: z.string().min(2, 'Name must be at least 2 characters'),
112
+ email: z.string().email('Invalid email address'),
113
+ bio: z.string().max(500, 'Bio must be less than 500 characters').optional(),
114
+ });
115
+
116
+ type FormState = {
117
+ success?: boolean;
118
+ errors?: Record<string, string[]>;
119
+ message?: string;
120
+ };
121
+
122
+ export async function updateUser(
123
+ userId: string,
124
+ prevState: FormState,
125
+ formData: FormData
126
+ ): Promise<FormState> {
127
+ // Validate
128
+ const parsed = updateUserSchema.safeParse({
129
+ name: formData.get('name'),
130
+ email: formData.get('email'),
131
+ bio: formData.get('bio'),
132
+ });
133
+
134
+ if (!parsed.success) {
135
+ return {
136
+ success: false,
137
+ errors: parsed.error.flatten().fieldErrors,
138
+ };
139
+ }
140
+
141
+ try {
142
+ // Mutate database
143
+ await db.user.update({
144
+ where: { id: userId },
145
+ data: parsed.data,
146
+ });
147
+
148
+ // Revalidate cached data
149
+ revalidatePath(`/users/${userId}`);
150
+ revalidateTag(`user-${userId}`);
151
+
152
+ return { success: true, message: 'Profile updated successfully' };
153
+ } catch (error) {
154
+ return {
155
+ success: false,
156
+ message: 'Failed to update profile. Please try again.',
157
+ };
158
+ }
159
+ }
160
+
161
+ export async function deleteUser(userId: string) {
162
+ await db.user.delete({ where: { id: userId } });
163
+ revalidatePath('/users');
164
+ redirect('/users'); // Navigate after mutation
165
+ }
166
+ ```
167
+
168
+ ## Client Component Using Server Action
169
+
170
+ ```typescript
171
+ // components/UserForm.tsx
172
+ 'use client';
173
+
174
+ import { useActionState } from 'react';
175
+ import { updateUser } from '@/actions/user';
176
+
177
+ type FormState = {
178
+ success?: boolean;
179
+ errors?: Record<string, string[]>;
180
+ message?: string;
181
+ };
182
+
183
+ export function UserEditForm({ userId, initialData }: Props) {
184
+ const [state, formAction, isPending] = useActionState<FormState, FormData>(
185
+ (prevState, formData) => updateUser(userId, prevState, formData),
186
+ {}
187
+ );
188
+
189
+ return (
190
+ <form action={formAction}>
191
+ <div>
192
+ <label htmlFor="name">Name</label>
193
+ <input
194
+ id="name"
195
+ name="name"
196
+ defaultValue={initialData.name}
197
+ required
198
+ aria-invalid={!!state.errors?.name}
199
+ />
200
+ {state.errors?.name?.map((error) => (
201
+ <p key={error} className="error">
202
+ {error}
203
+ </p>
204
+ ))}
205
+ </div>
206
+
207
+ <div>
208
+ <label htmlFor="email">Email</label>
209
+ <input
210
+ id="email"
211
+ name="email"
212
+ type="email"
213
+ defaultValue={initialData.email}
214
+ required
215
+ aria-invalid={!!state.errors?.email}
216
+ />
217
+ {state.errors?.email?.map((error) => (
218
+ <p key={error} className="error">
219
+ {error}
220
+ </p>
221
+ ))}
222
+ </div>
223
+
224
+ <div>
225
+ <label htmlFor="bio">Bio</label>
226
+ <textarea
227
+ id="bio"
228
+ name="bio"
229
+ defaultValue={initialData.bio}
230
+ aria-invalid={!!state.errors?.bio}
231
+ />
232
+ {state.errors?.bio?.map((error) => (
233
+ <p key={error} className="error">
234
+ {error}
235
+ </p>
236
+ ))}
237
+ </div>
238
+
239
+ {state.message && (
240
+ <div className={state.success ? 'success' : 'error'}>{state.message}</div>
241
+ )}
242
+
243
+ <button type="submit" disabled={isPending}>
244
+ {isPending ? 'Saving...' : 'Save Changes'}
245
+ </button>
246
+ </form>
247
+ );
248
+ }
249
+ ```
250
+
251
+ ## Programmatic Server Action
252
+
253
+ Call Server Actions directly from client code, not just forms.
254
+
255
+ ```typescript
256
+ 'use client';
257
+
258
+ import { deleteUser } from '@/actions/user';
259
+ import { useTransition } from 'react';
260
+
261
+ export function DeleteButton({ userId }: { userId: string }) {
262
+ const [isPending, startTransition] = useTransition();
263
+
264
+ const handleDelete = () => {
265
+ if (!confirm('Are you sure you want to delete this user?')) return;
266
+
267
+ startTransition(async () => {
268
+ try {
269
+ await deleteUser(userId);
270
+ // deleteUser calls redirect(), navigation happens automatically
271
+ } catch (error) {
272
+ console.error('Failed to delete user:', error);
273
+ }
274
+ });
275
+ };
276
+
277
+ return (
278
+ <button onClick={handleDelete} disabled={isPending}>
279
+ {isPending ? 'Deleting...' : 'Delete User'}
280
+ </button>
281
+ );
282
+ }
283
+ ```
284
+
285
+ ## use() Hook - Unwrapping Promises
286
+
287
+ Pass promises from Server to Client components, unwrap with use().
288
+
289
+ ```typescript
290
+ // Server Component
291
+ async function UserPage({ params }: { params: { id: string } }) {
292
+ // Don't await - pass promise to client
293
+ const userPromise = fetchUser(params.id);
294
+
295
+ return (
296
+ <Suspense fallback={<UserSkeleton />}>
297
+ <UserProfile userPromise={userPromise} />
298
+ </Suspense>
299
+ );
300
+ }
301
+
302
+ // Client Component
303
+ 'use client';
304
+
305
+ import { use } from 'react';
306
+
307
+ type Props = {
308
+ userPromise: Promise<User>;
309
+ };
310
+
311
+ export function UserProfile({ userPromise }: Props) {
312
+ // Suspends until resolved
313
+ const user = use(userPromise);
314
+
315
+ return (
316
+ <div>
317
+ <h1>{user.name}</h1>
318
+ <p>{user.email}</p>
319
+ </div>
320
+ );
321
+ }
322
+ ```
323
+
324
+ ## use() with Context
325
+
326
+ use() also unwraps context — alternative to useContext.
327
+
328
+ ```typescript
329
+ 'use client';
330
+
331
+ import { use } from 'react';
332
+ import { ThemeContext } from './ThemeProvider';
333
+
334
+ export function ThemedButton() {
335
+ const theme = use(ThemeContext); // Same as useContext(ThemeContext)
336
+
337
+ return <button className={theme.mode}>{theme.primaryColor}</button>;
338
+ }
339
+ ```
340
+
341
+ ## Streaming with Suspense
342
+
343
+ Stream components as they resolve — faster initial page load.
344
+
345
+ ```typescript
346
+ // Server Component
347
+ export default async function Page() {
348
+ return (
349
+ <div>
350
+ <h1>Dashboard</h1>
351
+
352
+ {/* Renders immediately */}
353
+ <StaticContent />
354
+
355
+ {/* Streams when ready */}
356
+ <Suspense fallback={<Spinner />}>
357
+ <SlowComponent />
358
+ </Suspense>
359
+
360
+ {/* Independent stream */}
361
+ <Suspense fallback={<Skeleton />}>
362
+ <AnotherSlowComponent />
363
+ </Suspense>
364
+ </div>
365
+ );
366
+ }
367
+
368
+ async function SlowComponent() {
369
+ const data = await slowFetch(); // Takes 2s
370
+ return <div>{data}</div>;
371
+ }
372
+
373
+ async function AnotherSlowComponent() {
374
+ const data = await anotherSlowFetch(); // Takes 1s
375
+ return <div>{data}</div>;
376
+ }
377
+ ```
378
+
379
+ ## Error Handling in Server Components
380
+
381
+ Use error.tsx for error boundaries.
382
+
383
+ ```typescript
384
+ // app/users/[id]/error.tsx
385
+ 'use client';
386
+
387
+ export default function Error({
388
+ error,
389
+ reset,
390
+ }: {
391
+ error: Error & { digest?: string };
392
+ reset: () => void;
393
+ }) {
394
+ return (
395
+ <div>
396
+ <h2>Something went wrong!</h2>
397
+ <p>{error.message}</p>
398
+ <button onClick={reset}>Try again</button>
399
+ </div>
400
+ );
401
+ }
402
+
403
+ // Server Component throws error
404
+ export default async function UserPage({ params }: Props) {
405
+ const user = await fetchUser(params.id);
406
+
407
+ if (!user) {
408
+ throw new Error('User not found'); // Caught by error.tsx
409
+ }
410
+
411
+ return <div>{user.name}</div>;
412
+ }
413
+ ```
414
+
415
+ ## Loading States with loading.tsx
416
+
417
+ ```typescript
418
+ // app/users/[id]/loading.tsx
419
+ export default function Loading() {
420
+ return <UserSkeleton />;
421
+ }
422
+
423
+ // Automatically wraps page in Suspense
424
+ // No need for manual Suspense boundary
425
+ ```
426
+
427
+ ## Server-Only Code
428
+
429
+ Ensure code never runs on client.
430
+
431
+ ```typescript
432
+ // lib/server-only-utils.ts
433
+ import 'server-only'; // Throws if imported in client component
434
+
435
+ export async function getSecretKey() {
436
+ return process.env.SECRET_KEY; // Safe - never in client bundle
437
+ }
438
+
439
+ export async function hashPassword(password: string) {
440
+ const bcrypt = await import('bcrypt');
441
+ return bcrypt.hash(password, 10);
442
+ }
443
+ ```
444
+
445
+ ## Client-Only Code
446
+
447
+ Ensure code never runs on server.
448
+
449
+ ```typescript
450
+ // lib/client-only-utils.ts
451
+ import 'client-only';
452
+
453
+ export function useLocalStorage(key: string) {
454
+ // localStorage only available in browser
455
+ const [value, setValue] = useState(() => localStorage.getItem(key));
456
+
457
+ useEffect(() => {
458
+ localStorage.setItem(key, value || '');
459
+ }, [key, value]);
460
+
461
+ return [value, setValue] as const;
462
+ }
463
+ ```
464
+
465
+ ## Mixing Server and Client Components
466
+
467
+ ```typescript
468
+ // app/page.tsx (Server Component)
469
+ export default async function Page() {
470
+ const data = await fetchData();
471
+
472
+ return (
473
+ <div>
474
+ {/* Server Component - can be async */}
475
+ <ServerComponent data={data} />
476
+
477
+ {/* Client Component - interactive */}
478
+ <ClientComponent initialData={data} />
479
+ </div>
480
+ );
481
+ }
482
+
483
+ // ServerComponent.tsx (Server Component - default)
484
+ export function ServerComponent({ data }: { data: Data }) {
485
+ return <div>{data.title}</div>;
486
+ }
487
+
488
+ // ClientComponent.tsx (Client Component)
489
+ 'use client';
490
+
491
+ export function ClientComponent({ initialData }: { initialData: Data }) {
492
+ const [data, setData] = useState(initialData);
493
+
494
+ return (
495
+ <button onClick={() => setData({ ...data, count: data.count + 1 })}>
496
+ {data.count}
497
+ </button>
498
+ );
499
+ }
500
+ ```
501
+
502
+ ## Server Component Patterns
503
+
504
+ ```typescript
505
+ // ✅ Server Component can:
506
+ // - Be async
507
+ // - Fetch data directly
508
+ // - Access backend resources (DB, filesystem)
509
+ // - Use server-only packages
510
+ // - Pass serializable props to client components
511
+
512
+ export default async function Page() {
513
+ const db = await connectDB(); // Direct DB access
514
+ const users = await db.user.findMany();
515
+
516
+ return <UserList users={users} />; // Pass serializable data
517
+ }
518
+
519
+ // ❌ Server Component cannot:
520
+ // - Use hooks (useState, useEffect, etc)
521
+ // - Use browser APIs (localStorage, window, etc)
522
+ // - Add event listeners (onClick, onChange, etc)
523
+ // - Use React Context
524
+
525
+ // ✅ Client Component can:
526
+ // - Use hooks
527
+ // - Use browser APIs
528
+ // - Add event listeners
529
+ // - Use React Context
530
+ // - Import Server Components as children
531
+
532
+ 'use client';
533
+
534
+ export function Layout({ children }: { children: React.ReactNode }) {
535
+ const [theme, setTheme] = useState('light');
536
+
537
+ return (
538
+ <div className={theme}>
539
+ <button onClick={() => setTheme('dark')}>Toggle</button>
540
+ {children} {/* Server Component can be child */}
541
+ </div>
542
+ );
543
+ }
544
+
545
+ // ❌ Client Component cannot:
546
+ // - Be async
547
+ // - Directly access backend resources
548
+ // - Import server-only packages
549
+ ```
550
+
551
+ ## Progressive Enhancement with Server Actions
552
+
553
+ Forms work without JavaScript when using Server Actions.
554
+
555
+ ```typescript
556
+ // components/AddTodoForm.tsx
557
+ import { addTodo } from '@/actions/todos';
558
+
559
+ export function AddTodoForm() {
560
+ return (
561
+ <form action={addTodo}>
562
+ <input name="title" required />
563
+ <button type="submit">Add Todo</button>
564
+ {/* Works without JS - progressive enhancement */}
565
+ </form>
566
+ );
567
+ }
568
+
569
+ // actions/todos.ts
570
+ 'use server';
571
+
572
+ export async function addTodo(formData: FormData) {
573
+ const title = formData.get('title');
574
+ if (typeof title !== 'string') return;
575
+
576
+ await db.todo.create({ data: { title } });
577
+ revalidatePath('/todos');
578
+ }
579
+ ```