SuperAPI AI Directory

component-design

Design & creation

View repository

Updated 10-16 06:23

About this skill

Component Design (Next.js)

Guiding principles for designing React components in Next.js App Router — focusing on API surface, composition, and the Server/Client boundary.

Core Principles

1. Server Component by Default

Prefer Server Components unless you need interactivity (hooks, event handlers, browser APIs). Every component that can be a Server Component should be one.

app/page.tsx         → Server Component (data fetching, layout)
app/page.tsx         → Client Component only if interactive
components/button.tsx → Client Component (has state/events)

2. Push Client Boundaries Down

When you need a Client Component, make it as thin as possible. Wrap the interactive part in a Client boundary and keep everything else on the server.

// ✅ Good: Server Component wraps minimal Client piece
// page.tsx (Server)
import { Comments } from './comments'
import { CommentList } from './comment-list'

export default function Page() {
  return (
    <div>
      <CommentList />           {/* Server: data fetching, rendering */}
      <Comments />              {/* Client: interactivity only */}
    </div>
  )
}

3. Interface First

Before writing implementation, define the component's public interface:

  • Props (required vs optional, types)
  • Children composition model (slots, render props, compound components)
  • Ref forwarding strategy
  • Loading, empty, error states

4. Test Through the Interface

If testing requires reaching into internal state or private methods, the interface is wrong. The public API should be the only test surface.

Server/Client Component Decision Tree

Does the component need hooks, events, or browser APIs?
├─ No  → Server Component ✅
└─ Yes → Client Component
         ├─ Can the interactive part be isolated?
         │   ├─ Yes → Extract into a thin Client wrapper, keep rest Server ✅
         │   └─ No  → Make the whole thing Client, but keep it focused
         └─ Do you need to pass Server data to it?
             ├─ Yes → Pass as props from the Server parent
             └─ No  → Fetch inside the Client Component

Seam Placement

A seam is where you can alter behavior without editing in that place. Good seams in Next.js:

Seam Purpose
layout.tsx Persistent shell, shared UI across routes
loading.tsx Streaming fallback per route segment
error.tsx Error boundary per route segment
not-found.tsx 404 boundary per route segment
Component props Polymorphism via different prop combinations
Slot props (children, named slots) Composition over configuration

Checklist

  • Can this be a Server Component? If yes, make it one
  • Is the Client boundary as thin as possible?
  • Are all states covered? (loading, empty, error, edge cases)
  • Is the interface the only test surface?
  • Is the component composable or configurable? (prefer composition)
  • Does the naming reflect what it does, not how it renders?
  • Could I delete this component without callers breaking unpredictably? (deletion test)