--- name: sdlc-server-component-patterns description: | React Server Components vs Client Components in Next.js: the boundary discipline, "use client" / "use server" directives, Server Actions, what serializes across the boundary, common pitfalls. Use this skill to: - Decide whether a component should be RSC or Client. - Push the "use client" boundary as deep as possible. - Implement Server Actions correctly (auth, validation, revalidation). - Compose RSC and Client components without breaking the model. - Pass data across the boundary safely. Do NOT use this skill for: - General Next.js conventions (see nextjs-conventions). - Specific data-fetching APIs and caching (see nextjs-data-fetching). - Routing (see nextjs-routing). paths: ["app/**", "src/app/**"] --- # RSC + Server Actions Patterns The single most important skill for working in App Router. Get the boundary wrong and you'll get build errors, runtime errors, or silent serialization failures. ## Mental model - **Server Component (RSC)** — rendered on the server. Has access to: `async/await`, server-only modules (DB clients, fs, filesystem), env vars (including secrets). Does NOT have: `useState`, `useEffect`, `useRef`, browser APIs (`window`, `document`), event handlers. - **Client Component** — rendered on the client (after initial HTML hydration). Has access to: hooks, browser APIs, event handlers. Does NOT have: server-only modules, secrets, async/await directly in the component body (the function itself isn't async; data flows in via props or hooks). - **Server Actions** — async functions marked `"use server"`. Callable from Client Components but execute on the server. Form-friendly via `
); } ``` Or directly from event handlers: ```tsx 'use client'; import { deleteUser } from '../actions'; export function DeleteButton({ id }: { id: string }) { return ; } ``` ### Server Action security rules (NON-NEGOTIABLE) 1. **Authorize at the top of every Server Action.** They are public RPC endpoints. 2. **Validate input.** FormData and arguments come from the network — treat as untrusted. 3. **Don't return secrets.** Return values are sent to the client. 4. **Use `revalidatePath` / `revalidateTag` after mutations** — otherwise the client sees stale data. 5. **Configure `serverActions.allowedOrigins` in `next.config.js`** for production CORS-like protection. ## `useFormStatus` and `useFormState` ```tsx 'use client'; import { useFormStatus } from 'react-dom'; function SubmitButton() { const { pending } = useFormStatus(); return ; } ``` `useFormStatus` MUST be inside a `