
react-frontend-expert
React/TypeScript frontend implementation patterns. Use during the implementation phase when creating or modifying React components, custom hooks, pages, data fetching logic with TanStack Query, forms, or routing. Covers component structure, hooks rules, custom hook design (useAuth, useDebounce, usePagination), TypeScript strict-mode conventions, form handling, accessibility requirements, and project structure. Does NOT cover testing (use react-testing-patterns), E2E testing (use e2e-testing), or deployment.
- Installs
- 203
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/hieutrtr/ai1-skills --skill react-frontend-expert- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads react-frontend-expert automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
React Frontend Expert
When to Use
Activate this skill when:
- Creating or modifying React components (functional components only)
- Writing custom hooks (
useXxx) - Building pages with routing
- Implementing data fetching with TanStack Query
- Handling forms with validation
- Setting up project structure for a React/TypeScript application
Do NOT use this skill for:
- Writing component or hook tests (use
react-testing-patterns) - E2E browser testing (use
e2e-testing) - API contract design (use
api-design-patterns) - Backend implementation (use
python-backend-expert) - Deployment or CI/CD (use
deployment-pipeline)
Instructions
Project Structure
src/
├── api/ # API client functions and query options
│ ├── client.ts # Axios/fetch instance with interceptors
│ ├── users.ts # User API functions + query options
│ └── posts.ts
├── components/ # Shared, reusable UI components
│ ├── Button.tsx
│ ├── Modal.tsx
│ ├── Table/
│ │ ├── Table.tsx
│ │ └── TablePagination.tsx
│ └── Form/
│ ├── Input.tsx
│ └── Select.tsx
├── features/ # Domain-specific feature components
│ ├── users/
│ │ ├── UserList.tsx
│ │ └── UserProfile.tsx
│ └── posts/
│ └── PostEditor.tsx
├── hooks/ # Custom hooks
│ ├── useAuth.ts
│ ├── useDebounce.ts
│ └── usePagination.ts
├── layouts/ # Layout components
│ ├── MainLayout.tsx
│ └── AuthLayout.tsx
├── pages/ # Route-level page components
│ ├── HomePage.tsx
│ ├── LoginPage.tsx
│ └── users/
│ ├── UserListPage.tsx
│ └── UserDetailPage.tsx
├── types/ # Shared TypeScript types
│ ├── api.ts # API response types
│ └── user.ts
├── App.tsx # Root component with providers and router
└── main.tsx # Entry point
Component Structure
Functional Components Only
interface UserCardProps {
user: User;
onEdit: (userId: number) => void;
showEmail?: boolean;
}
export function UserCard({ user, onEdit, showEmail = false }: UserCardProps) {
return (
<article className="user-card">
<h3>{user.displayName}</h3>
{showEmail && <p>{user.email}</p>}
<button type="button" onClick={() => onEdit(user.id)}>
Edit
</button>
</article>
);
}
Component rules:
- Named exports for shared components:
export function Button - Default exports for page components:
export default function UserListPage - Props interface named
{Component}Props - Destructure props in function signature
- Keep components under 200 lines — extract sub-components or hooks when larger
- Use
childrenand composition over deep prop drilling - Never use
React.FC— use plain function syntax
Component File Organization
For complex components, co-locate related files:
UserProfile/
├── UserProfile.tsx # Main component
├── UserProfile.css # Styles (or .module.css)
├── UserAvatar.tsx # Sub-component
└── index.ts # Re-export: export { UserProfile } from './UserProfile'
Hooks Rules and Custom Hooks
Rules of Hooks
- Only call hooks at the top level — never inside loops, conditions, or nested functions
- Only call hooks from React function components or custom hooks
- Custom hooks must start with
use
Custom Hook Patterns
useDebounce:
export function useDebounce<T>(value: T, delayMs: number): T {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delayMs);
return () => clearTimeout(timer);
}, [value, delayMs]);
return debouncedValue;
}
useAuth:
interface AuthContext {
user: User | null;
isAuthenticated: boolean;
login: (credentials: LoginCredentials) => Promise<void>;
logout: () => void;
}
const AuthContext = createContext<AuthContext | null>(null);
export function useAuth(): AuthContext {
const context = useContext(AuthContext);
if (!context) {
throw new Error("useAuth must be used within AuthProvider");
}
return context;
}
usePagination:
interface PaginationState {
cursor: string | null;
hasMore: boolean;
goToNext: (nextCursor: string) => void;
reset: () => void;
}
export function usePagination(): PaginationState {
const [cursor, setCursor] = useState<string | null>(null);
const [hasMore, setHasMore] = useState(true);
return {
cursor,
hasMore,
goToNext: (nextCursor: string) => {
setCursor(nextCursor);
},
reset: () => {
setCursor(null);
setHasMore(true);
},
};
}
When to extract a custom hook:
- Logic is reused across 2+ components
- Component has complex state management (>3
useStatecalls) - Side effects need encapsulation (subscriptions, timers)
- Data fetching logic can be shared
Data Fetching with TanStack Query
Query Options Factory (Recommended)
Centralize query key and function definitions to prevent key collisions:
// api/users.ts
import { queryOptions } from "@tanstack/react-query";
export const userQueries = {
all: () =>
queryOptions({
queryKey: ["users"],
queryFn: () => apiClient.get<UserListResponse>("/users"),
}),
detail: (userId: number) =>
queryOptions({
queryKey: ["users", userId],
queryFn: () => apiClient.get<UserResponse>(`/users/${userId}`),
}),
search: (query: string) =>
queryOptions({
queryKey: ["users", "search", query],
queryFn: () => apiClient.get<UserListResponse>(`/users?q=${query}`),
enabled: query.length > 0,
}),
};
Using Queries in Components
export function UserDetailPage({ userId }: { userId: number }) {
const { data: user, isPending, isError, error } = useQuery(
userQueries.detail(userId)
);
if (isPending) return <Spinner />;
if (isError) return <ErrorMessage error={error} />;
return <UserProfile user={user} />;
}
Mutations with Cache Invalidation
export function useCreateUser() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: UserCreate) =>
apiClient.post<UserResponse>("/users", data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["users"] });
},
});
}
TanStack Query rules:
- Set
staleTime> 0 (default 0 is too aggressive):staleTime: 5 * 60 * 1000(5 min) - Use
invalidateQueries()after mutations — never manualrefetch() - Handle all states:
isPending,isError,data - Use
queryOptions()factory — prevents key typos and duplication - Use
enabledto prevent queries from running with incomplete parameters
TypeScript Conventions
// Use `interface` for object shapes (components props, API responses)
interface User {
id: number;
email: string;
displayName: string;
role: "admin" | "editor" | "member";
}
// Use `type` for unions, intersections, and computed types
type UserRole = User["role"];
type CreateOrUpdate = UserCreate | UserUpdate;
// Discriminated unions for state machines
type AsyncState<T> =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: T }
| { status: "error"; error: Error };
TypeScript rules:
- Enable
strict: trueintsconfig.json— no exceptions - Never use
any— useunknownfor truly unknown types - Use
as constfor literal object types - Prefer
interfacefor extensible types,typefor everything else - Use generics for reusable utility types and hooks
- Export types from
types/directory for shared use
Form Handling
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const userSchema = z.object({
email: z.string().email("Invalid email"),
displayName: z.string().min(1, "Required").max(100),
role: z.enum(["admin", "editor", "member"]),
});
type UserFormData = z.infer<typeof userSchema>;
export function UserForm({ onSubmit }: { onSubmit: (data: UserFormData) => void }) {
const {
register,
handleSubmit,
formState: { errors, isSubmitting },
} = useForm<UserFormData>({
resolver: zodResolver(userSchema),
});
return (
<form onSubmit={handleSubmit(onSubmit)} noValidate>
<label htmlFor="email">Email</label>
<input id="email" type="email" {...register("email")} aria-invalid={!!errors.email} />
{errors.email && <span role="alert">{errors.email.message}</span>}
<label htmlFor="displayName">Name</label>
<input id="displayName" {...register("displayName")} aria-invalid={!!errors.displayName} />
{errors.displayName && <span role="alert">{errors.displayName.message}</span>}
<button type="submit" disabled={isSubmitting}>Save</button>
</form>
);
}
Accessibility Requirements
Every component must meet WCAG 2.1 AA:
- Semantic HTML first: Use
<button>,<nav>,<main>,<article>— not<div onClick> - Labels: Every form input has a
<label>with matchinghtmlFor/id - ARIA only when needed:
aria-labelfor icon-only buttons,aria-livefor dynamic updates,role="alert"for errors - Keyboard navigation: All interactive elements reachable via Tab, activatable via Enter/Space
- Focus management: Set focus to main content on route change, trap focus in modals
- Color contrast: Minimum 4.5:1 for normal text, 3:1 for large text
- Alt text: All
<img>tags have descriptivealt(oralt=""for decorative images)
Examples
User List Page with Search and Pagination
export default function UserListPage() {
const [search, setSearch] = useState("");
const debouncedSearch = useDebounce(search, 300);
const pagination = usePagination();
const { data, isPending } = useQuery(
userQueries.list({ q: debouncedSearch, cursor: pagination.cursor })
);
return (
<main>
<h1>Users</h1>
<input
type="search"
value={search}
onChange={(e) => { setSearch(e.target.value); pagination.reset(); }}
placeholder="Search users..."
aria-label="Search users"
/>
{isPending ? <Spinner /> : (
<>
<UserTable users={data.items} />
{data.hasMore && (
<button onClick={() => pagination.goToNext(data.nextCursor)}>
Load more
</button>
)}
</>
)}
</main>
);
}
Edge Cases
-
Stale closures in hooks: When using callbacks that reference state, use
useReffor mutable values that change frequently, or include dependencies in useCallback/useEffect arrays. -
TanStack Query key collisions: Structure keys hierarchically:
["users"]for list,["users", id]for detail,["users", { q, page }]for filtered list. UsequeryOptions()factory to centralize key definitions. -
Infinite re-renders: Common causes: missing dependency arrays, creating new objects/arrays in render (wrap in
useMemo), state updates in useEffect without proper conditions. -
Hydration mismatches: Avoid rendering content that depends on browser-only APIs (window, localStorage) during initial render. Use
useEffector checktypeof window !== "undefined". -
Memory leaks: Cancel async operations in useEffect cleanup. TanStack Query handles this automatically for queries.
See references/component-templates.md for annotated component templates.
See references/tanstack-query-patterns.md for CRUD query patterns.
FAQ
What does the react-frontend-expert skill do?
React/TypeScript frontend implementation patterns. Use during the implementation phase when creating or modifying React components, custom hooks, pages, data fetching logic with TanStack Query, forms, or routing. Covers component structure, hooks rules, custom hook design (useAuth, useDebounce, usePagination), TypeScript strict-mode conventions, form handling, accessibility requirements, and project structure. Does NOT cover testing (use react-testing-patterns), E2E testing (use e2e-testing), or deployment.
How do I install react-frontend-expert?
Run npx skills add https://github.com/hieutrtr/ai1-skills --skill react-frontend-expert in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/react-frontend-expert/ (personal) or .claude/skills/react-frontend-expert/ (project).
Which AI agents can use react-frontend-expert?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is react-frontend-expert safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains react-frontend-expert?
It is published by hieutrtr in hieutrtr/ai1-skills. It has 203 recorded installs.
More from hieutrtr/ai1-skills
e2e-testing
hieutrtr/ai1-skills
End-to-end testing patterns with Playwright for full-stack Python/React applications. Use when writing E2E tests for complete user workflows (login, CRUD, navigation), critical path regression tests, or cross-browser validation. Covers test structure, page object model, selector strategy (data-testid role label), wait strategies, auth state reuse, test data management, and CI integration. Does NOT cover unit tests or component tests (use pytest-patterns or react-testing-patterns).
code-review-security
hieutrtr/ai1-skills
Security-focused code review checklist and automated scanning patterns. Use when reviewing pull requests for security issues, auditing authentication/authorization code, checking for OWASP Top 10 vulnerabilities, or validating input sanitization. Covers SQL injection prevention, XSS protection, CSRF tokens, authentication flow review, secrets detection, dependency vulnerability scanning, and secure coding patterns for Python (FastAPI) and React. Does NOT cover deployment security (use docker-best-practices) or incident handling (use incident-response).
react-testing-patterns
hieutrtr/ai1-skills
Open the skill to read its SKILL.md instructions.
python-backend-expert
hieutrtr/ai1-skills
Open the skill to read its SKILL.md instructions.
ui-design-system
hieutrtr/ai1-skills
Open the skill to read its SKILL.md instructions.
pytest-patterns
hieutrtr/ai1-skills
Python backend testing patterns with pytest for FastAPI applications. Use when writing Python tests: unit tests for services and repositories, integration tests for API endpoints with httpx.AsyncClient, fixture creation, factory setup with factoryboy, async testing with pytest-asyncio, mocking strategies, and parametrized tests. Covers test organization (tests/unit, tests/integration), conftest hierarchy, and coverage requirements. Does NOT cover frontend tests (use react-testing-patterns) or E2E browser tests (use e2e-testing).
Popular frontend & design skills
setup-matt-pocock-skills
mattpocock/skills
Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.
frontend-design
anthropics/skills
Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
hyperframes-animation
heygen-com/hyperframes
All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.
prototype
mattpocock/skills
Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.
hyperframes-core
heygen-com/hyperframes
The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.
vercel-react-best-practices
vercel-labs/agent-skills
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.