Install any skill in seconds. Free to start, no credit card required.
Get Started Free →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.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-06 | ✗→✓ | ▲ Improved | 45% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 83% | 0% |
| case-08 | ✓→✓ | = Same ✓ | 61% | 0% |
| case-09 | ✓→✓ | = Same ✓ | 31% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 22% | 0% |
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 |
<!-- moai:evolvable-start id="rationalizations" -->
| 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. |
<!-- moai:evolvable-end -->
<!-- moai:evolvable-start id="red-flags" -->
<!-- moai:evolvable-end -->
<!-- moai:evolvable-start id="verification" -->
<!-- moai:evolvable-end -->
Other measured skills in the registry, with their headline benchmark lift.