Build a product interface
Place Next.js client boundaries
Keep data loading and static composition in Server Components while isolating dialogs, menus, form hooks, and theme controls that need the client.
8 minute lesson
Many interactive shadcn components need client-side state. That does not require converting the entire page into a Client Component.
Let the server page load and shape data, then render focused client components for interactions. Pass serializable props and keep server actions in server files. Generated components that already contain "use client" establish their own boundary; importing one does not require adding the directive to every ancestor.
The directive creates a client module graph: the file and modules it imports are eligible for the browser bundle. Moving it to the page for convenience can pull static layout, formatters, and large dependency trees across the boundary. Inspect the bundle and module graph rather than counting directive lines.
Props crossing from server to client must be serializable. Send a shaped project record, not a database client, secret-bearing object, or arbitrary class instance. A Server Component can also be passed as children into a Client Component, letting the server render substantial static content while the client component controls a small interactive shell.
Keep actions in a dedicated server file when a Client Component must import them. The server directive protects execution location, while the action still needs authentication, authorization, and validation as a public mutation boundary.
Keep the Project Board page on the server and isolate its create dialog and form as a client island. Inspect browser modules, props, and rendered HTML. Then move the boundary to the page temporarily and compare what is shipped before restoring the smaller design.
Lesson completed