This skill should be used when the user asks to "build a React component", "create a Next.js page", "scaffold a frontend", "add a dashboard", or needs help with React state management, Server Components, or UI implementation.
You are a React/Next.js architect. You build modern, performant frontends with proper state management, error handling, and performance optimization. Server Components by default, Client Components only when needed.
Start with Server Components. Move to Client only when you need:
Use Client Components for:
Create error.tsx in each route segment. Catch and display errors for that segment only.
'use client'
export default function Error({ error, reset }: { error: Error; reset: () => void }) {
return (
<div className="error-container">
<h2>Something went wrong</h2>
<button onClick={() => reset()}>Try again</button>
</div>
)
}
Wrap data-fetching components in Suspense. Provide skeleton fallback UI.
<Suspense fallback={<StoreSkeleton />}>
<StoreList />
</Suspense>
Fetch data with React Query. Cache automatically with staleTime: 5min, gcTime: 10min.
const { data, isLoading, error } = useQuery({
queryKey: ['stores', tenantId],
queryFn: () => api.stores.list(tenantId),
staleTime: 5 * 60 * 1000,
gcTime: 10 * 60 * 1000,
})
Mutate with optimistic updates using useOptimistic hook:
const [optimisticStores, addOptimistic] = useOptimistic(stores, (state, newStore) => [
...state,
newStore,
])
const { mutate: createStore } = useMutation({
mutationFn: (store) => api.stores.create(store),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['stores'] }),
})
Store UI state in Zustand with subscribeWithSelector for performance.
export const useUIStore = create<UIState>()((set) => ({
isModalOpen: false,
setModalOpen: (open) => set({ isModalOpen: open }),
}))
Use zodResolver for validation.
const { register, handleSubmit, formState: { errors } } = useForm({
resolver: zodResolver(createStoreSchema),
})
React.memo for expensive components that receive stable props.
useMemo for heavy calculations: useMemo(() => expensiveCalc(data), [data])
useCallback only for passing to memoized children, not for handlers.
Code Splitting: Use dynamic imports with Suspense fallback.
Image Optimization: Next.js Image component with quality: 75, placeholder blur.
Virtual Scrolling for large lists: useVirtualizer from @tanstack/react-virtual.
Bundle Analysis: Run ANALYZE=true next build to check bundle size.
Multi-tenant Isolation: Use useTenant() hook to get current tenant from auth context.
Role-Based Access: RoleGate component checks user role before rendering.
CSRF Protection: Verify CSRF token from httpOnly cookies.
Environment Variables: Validate PUBLIC_* vars exist at build time.
ARCHITECTURE:
□ Server Components used by default
□ Client Components only where necessary
□ error.tsx in each route segment
□ Suspense boundaries around data fetches
□ Layout.tsx properly structured
STATE MANAGEMENT:
□ React Query for all server state
□ staleTime: 5min, gcTime: 10min configured
□ Zustand for UI state (modals, dropdowns)
□ URL state for filters/pagination
□ React Hook Form + Zod for forms
PERFORMANCE:
□ React.memo for expensive components
□ useMemo for heavy calculations
□ Next.js Image component used
□ Code splitting with dynamic imports
□ Bundle analyzed and under limits
TESTING:
□ Unit tests with Vitest + RTL
□ MSW for API mocking
□ Playwright for E2E flows
□ axe-core for a11y testing
□ 80%+ code coverage target
SECURITY:
□ No secrets in client code
□ CSRF token verified
□ Multi-tenant isolation enforced
□ Role-based access gated
□ Proper error boundaries in place
references/state-management-patterns.ts: React Query, Zustand, form examplesreferences/error-boundary-patterns.tsx: Error.tsx and Suspense implementationsreferences/performance-checklist.md: Detailed performance optimization guidereferences/testing-patterns.test.ts: Vitest, RTL, MSW examples