React/Next.js component design patterns, state management strategies, and project structure reference for frontend development. Agent-extending skill that amplifies frontend domain work (spawned via Agent(general-purpose) with frontend instructions) with production-grade React patterns. NOT for: backend API design, database modeling, DevOps, mobile apps.
68
83%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Frontend domain work spawned via Agent(general-purpose) with frontend instructions - Applies these patterns directly to component design and state management.
Parent and child share implicit state via Context.
Suited for: Tab, Accordion, Dropdown, Select
Structure: <Select> + <Select.Trigger> + <Select.Option>
Extract state logic into reusable hooks.
Suited for: Form management, API calls, localStorage, debounce
Naming: use prefix required - useForm, useDebounce, useAuth
Separate data logic (Container) from UI (Presentational).
Suited for: Large apps, when testability is needed Container: Data fetch, state management, event handlers Presentational: Renders only from props, functionally pure
Provides behavior/state without UI.
Suited for: Design system-independent logic
Examples: headless useCombobox, useDialog, useTable
| State Type | Tool | Rationale |
|---|---|---|
| UI Local | useState, useReducer | Component-internal |
| Server State | React Query / TanStack Query | Caching, refetch, optimistic |
| Global Client | Zustand | Concise, minimal boilerplate |
| Complex Global | Zustand + Immer | Immutability convenience |
| URL State | nuqs / useSearchParams | Filters, pagination |
| Form State | React Hook Form + Zod | Integrated validation |
| Theme/i18n | Context + Provider | Low change frequency |
Restorable from URL? -> URL state (nuqs)
Server data? -> React Query
Shared across components? -> Zustand
Component-internal? -> useState
Complex transitions? -> useReducersrc/
├── app/ # App Router
│ ├── (auth)/ # Auth route group
│ │ ├── login/page.tsx
│ │ └── register/page.tsx
│ ├── (main)/ # Main route group
│ │ ├── dashboard/page.tsx
│ │ └── settings/page.tsx
│ ├── api/ # API Routes
│ ├── layout.tsx # Root layout
│ └── page.tsx # Home
├── components/
│ ├── ui/ # Base UI (Button, Input, Modal)
│ └── features/ # Feature components
│ ├── auth/
│ └── dashboard/
├── hooks/ # Custom hooks
├── lib/ # Utilities, config
├── stores/ # Zustand stores
├── types/ # TypeScript types
└── styles/ # Global styles| Item | Standard |
|---|---|
| Component Size | Under 200 lines (split if exceeded) |
| Props | 5 or fewer (group into object if exceeded) |
| Custom Hooks | Always extract when reusing logic |
| Error Boundaries | Set at the page level |
| Loading States | Provide loading UI for all async ops |
| Form Validation | Validate on both client and server |
| Pattern | When | Tool |
|---|---|---|
| Memoization | Expensive computation | useMemo, React.memo |
| Lazy Loading | Bundle size | React.lazy, next/dynamic |
| Virtualization | 1000+ item lists | @tanstack/react-virtual |
| Image Optimization | Image loading | next/image |
| Optimistic Updates | Immediate feedback | React Query onMutate |
| Debounce | Search, input | useDeferredValue or custom hook |
RootErrorBoundary (global)
└── LayoutErrorBoundary (per section)
└── ComponentErrorFallback (individual)| HTTP Status | Client Handling |
|---|---|
| 401 | Auto logout + redirect |
| 403 | Unauthorized UI |
| 404 | Not Found page |
| 422 | Per-field form error |
| 429 | Retry + wait notice |
| 500 | Generic error + retry button |
| Rationalization | Reality |
|---|---|
| "useEffect is fine for data fetching in React 19" | React 19 provides use() and server components for data fetching. useEffect for fetch is a legacy pattern that causes waterfalls. |
| "Global state is simpler than prop drilling" | Global state couples distant components. Prop drilling or composition via children is more predictable and testable. |
| "I will add TypeScript types later" | Untyped components accumulate any-typed callers. Retrofitting types into a used component is much harder than starting typed. |
| "This component does not need memoization" | Premature memoization is waste, but components rendering lists or expensive trees should be profiled, not assumed fast. |
| "CSS-in-JS is fine, everyone uses it" | CSS-in-JS adds runtime overhead and bundle size. Tailwind or CSS Modules achieve the same scoping without the cost. |
05117b6
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.