| name | new-component |
| description | Create new React/Next.js components for this project (Next.js 16 + React 19). Use when asked to create, add, or implement a new component. Enforces: component type selection (Server/Client/Cache), Suspense and Static Shell optimization, composition patterns, props definition style, and naming conventions. Triggers on: "create a component", "add a new component", "implement a [Name] component", or any request to build a new UI piece.
|
| metadata | {"argument-hint":"<ComponentName>"} |
| allowed-tools | Read Write Edit Glob Grep Bash(pnpm:*) |
New Component
The argument $ARGUMENTS is the component name (PascalCase).
Step 0: Check Composition Patterns First
Before writing any component API, read .agents/skills/vercel-composition-patterns/SKILL.md.
Key rules (React 19 project):
- Avoid boolean props — use composition or explicit variant components instead
- No
forwardRef — pass refs as plain props
- Use
use() instead of useContext()
- Prefer
children over render props
Step 1: Choose Component Type
| Need | Type | Directive |
|---|
| State, event handlers, browser APIs, custom hooks | Client Component | 'use client' at top of file |
| Cacheable async data (same for all users) | Cache Component | 'use cache' inside function body |
Request-time data (cookies, headers, searchParams) | Server Component | none — wrap call site in <Suspense> |
| Pure UI / no async | Server Component | none |
See references/component-types.md for detailed guidance.
Step 2: Define Props and Component
Always use the FC pattern. For async Server Components, make the arrow function async.
Template:
import { type FC } from 'react'
type ${ARGUMENTS}Props = {
}
export const $ARGUMENTS: FC<${ARGUMENTS}Props> = ({ ...props }) => {
return (
<div className="">
{/* Implementation */}
</div>
)
}
Async Server Component:
import { type FC } from 'react'
type ${ARGUMENTS}Props = {
id: string
}
export const $ARGUMENTS: FC<${ARGUMENTS}Props> = async ({ id }) => {
const data = await fetchData(id)
return <div>{data.name}</div>
}
Rules:
- Props type:
type ${ARGUMENTS}Props = { ... } — always defined separately
- Component:
export const $ARGUMENTS: FC<${ARGUMENTS}Props> = ... — const arrow function, named export
- Import
FC as a type: import { type FC } from 'react'
- Do not use
React.FC or function declarations for components
Step 3: Apply Static Shell / Suspense Pattern
- Static content and
'use cache' components → included in the static shell automatically
- Request-time dynamic content → wrap in
<Suspense fallback={...}>
- Never leave uncached async components unwrapped — Next.js 16 raises a build error
export default function Page() {
return (
<>
<StaticHeader /> {/* static shell */}
<CachedBlogPosts /> {/* 'use cache' — static shell */}
<Suspense fallback={<p>Loading...</p>}>
<DynamicUserGreeting /> {/* streams at request time */}
</Suspense>
</>
);
}
See references/patterns.md for full code examples.
Step 4: After Implementation
Run type check:
pnpm check
Naming Conventions
- Component name: PascalCase (e.g.,
UserProfile, BlogCard)
- File name: kebab-case (e.g.,
user-profile.tsx, blog-card.tsx)
- Custom hooks:
use prefix (e.g., useAuth, useCart)
- Props type:
${ARGUMENTS}Props