Skip to main content
component-builder React 19 + Server Component patterns from official Vercel/React docs. Component templates, hooks patterns, RSC boundaries, performance optimization.
Jump to install Skills Marketplace Discover and explore AI skills built by the community.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Copy promptShow prompt details A direct command skips the review prompt. Inspect the source before running it.
npx skills add https://github.com/ktg-one/goodai-mate --skill component-builderThe command stays on one line. Scroll horizontally to inspect it before copying.
Prefer a local copy? Download the files currently available to SkillsMP.
Download Zip Downloading... More from this repository
Related occupations SOC
Based on SOC occupation classification
Good'ai brutalist/direct-mail frontend: brand tokens, stamp UI, voice hero, asset registry, and ESLint gates. Use when building or reviewing UI in goodai-mate, fixing design fidelity, prepping demos (ABS), running lint, or when the user says /goodai-frontend, goodai frontend, brutalist mail board, stamp design, or frontend-design for this project.
name component-builder description React 19 + Server Component patterns from official Vercel/React docs. Component templates, hooks patterns, RSC boundaries, performance optimization. user-invocable false
Component Builder Patterns (Official React 19 + Vercel Source)
Based on React 19.2 docs, Vercel React Best Practices (57 rules), and Next.js Agent Skills.
Server Component (Default)
interface ProductCardProps {
id : string
title : string
price : number
description ?: string
}
export default async function ProductCard ({ id, title, price, description }: ProductCardProps ) {
const inventory = await getInventory (id)
(
)
}
return
<div className ="rounded-lg border p-4" >
<h3 className ="text-lg font-semibold" > {title}</h3 >
{description && <p className ="text-sm text-muted-foreground" > {description}</p > }
<p className ="mt-2 text-xl font-bold" > ${price}</p >
<span className ="text-xs text-muted-foreground" >
{inventory.count} in stock
</span >
</div >
Client Component (Interactive)
'use client'
import { useState, useCallback, useTransition } from 'react'
import { useRouter } from 'next/navigation'
interface SearchInputProps {
placeholder ?: string
defaultValue ?: string
}
export default function SearchInput ({
placeholder = 'Search...' ,
defaultValue = '' ,
}: SearchInputProps ) {
const [query, setQuery] = useState (defaultValue)
const [isPending, startTransition] = useTransition ()
const router = useRouter ()
const handleSearch = useCallback (
(value : string ) => {
setQuery (value)
startTransition (() => {
router.push (`/search?q=${encodeURIComponent (value)} ` )
})
},
[router]
)
return (
<input
type ="search"
value ={query}
onChange ={(e) => handleSearch(e.target.value)}
placeholder={placeholder}
className="w-full rounded-md border px-3 py-2"
aria-label="Search"
/>
)
}
Composition Pattern: Server + Client
import InteractiveChart from '@/components/features/interactive-chart'
export default async function DashboardPage ( ) {
const data = await getAnalytics ()
return (
<div >
<h1 > Dashboard</h1 >
<InteractiveChart data ={data} /> {/* client handles interactivity */}
</div >
)
}
'use client'
import { useState } from 'react'
interface InteractiveChartProps {
data : AnalyticsData []
}
export default function InteractiveChart ({ data }: InteractiveChartProps ) {
const [timeRange, setTimeRange] = useState<'day' | 'week' | 'month' >('week' )
const filtered = data.filter ((d ) => matchesRange (d, timeRange))
return ()
}
React 19 Hooks Reference
useState โ State management const [count, setCount] = useState (0 )
const [items, setItems] = useState<Item []>([])
const increment = useCallback (() => setCount ((c ) => c + 1 ), [])
const [data, setData] = useState (() => computeExpensiveDefault ())
useCallback โ Stable function references
const handleSubmit = useCallback (async (formData : FormData ) => {
await submitForm (formData)
}, [])
<button onClick={() => setOpen (true )}>Open </button> / / fine as -is
useMemo โ Expensive computation caching
const sortedItems = useMemo (
() => items.toSorted ((a, b ) => a.name .localeCompare (b.name )),
[items]
)
const isActive = status === 'active'
useTransition โ Non-urgent updates
const [isPending, startTransition] = useTransition ()
function handleTabChange (tab : string ) {
startTransition (() => {
setActiveTab (tab)
})
}
useRef โ Mutable values without re-renders
const inputRef = useRef<HTMLInputElement >(null )
const scrollPosition = useRef (0 )
use() โ React 19 context/promise consumer
import { use } from 'react'
function ThemeButton ( ) {
const theme = use (ThemeContext )
return <button className ={theme.buttonClass} > Click</button >
}
Heavy Component Loading
import dynamic from 'next/dynamic'
const CodeEditor = dynamic (() => import ('@/components/code-editor' ), {
ssr : false ,
loading : () => <div className ="h-96 animate-pulse rounded bg-muted" /> ,
})
const MapView = dynamic (() => import ('@/components/map-view' ), {
ssr : false ,
loading : () => <div className ="h-64 animate-pulse rounded bg-muted" /> ,
})
Component Rules (Enforced by cs-code-reviewer)
Default export always โ one component per file
Props interface above component , exported if reused
No barrel files โ import directly from component file path
Tailwind only โ no CSS modules, no styled-components
Use cn() from @/lib/utils for conditional classes
Server Component by default โ only 'use client' when needed
Minimize client boundary โ push 'use client' to smallest leaf component
Parallel fetch in server components โ Promise.all() for independent data
Suspense boundaries โ wrap async children for streaming
Every component gets a test in __tests__/unit/components/
Vercel Performance Rules (Top Priority) Rule Impact Pattern async-parallelCRITICAL Promise.all() for independent opsbundle-barrel-importsCRITICAL Import from specific file, not index bundle-dynamic-importsCRITICAL next/dynamic for heavy componentsserver-serializationHIGH Minimize data passed to client components rerender-memoMEDIUM Extract expensive work into memoized components rerender-derived-stateMEDIUM Subscribe to derived booleans, not raw values rendering-conditional-renderMEDIUM Use ternary ? :, not &&