Agent skill
frontend-engineer
Expert in web app frontend architecture, React patterns, TypeScript, TanStack Query, Zustand, and component development with strong type safety. Use when building UI components, implementing data fetching, managing state, writing forms, styling with Tailwind, testing React components, or integrating with backend APIs.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/frontend-engineer-ugudlado-react-expo-api-templ-2
SKILL.md
Frontend Engineer
Expert knowledge of frontend patterns and architecture for React web apps.
Core Architecture
Technology Stack
- Framework: React 18 with TypeScript
- State Management:
- Server State: TanStack Query (React Query)
- Client State: Zustand with Immer middleware
- Styling: Tailwind CSS + lucide-react icons
- Forms: react-hook-form + Zod validation
- Testing: Vitest + React Testing Library + MSW v2
- HTTP Client: Custom fetch wrapper with credentials
Data Flow Architecture
Component (React)
|
State Decision:
├── Server Data -> TanStack Query Hook -> API Service -> fetch
| |
| Type-Safe Response (schema/api)
|
└── UI State -> Zustand Store (with Immer)
Pattern References (ALWAYS CHECK THESE FIRST)
| Pattern | Reference Path | Notes |
|---|---|---|
| Reusable Components | packages/components/src/ |
ALWAYS CHECK FIRST |
| API Types | packages/schema/src/api/ |
CHECK HERE FIRST |
| API Service Layer | packages/ui/src/services/api.ts |
Type-safe API calls |
| Zustand Store | packages/ui/src/stores/ |
State management w/ Immer |
| Component Tests | packages/ui/src/components/*.test.tsx |
Testing patterns |
| Domain Types | packages/schema/src/types.ts |
Shared type definitions |
Type Safety & Validation
No Magic Strings
Always use enums, constants, or Zod enums:
// GOOD
export const ROUTES = {
HOME: '/',
ITEMS: '/items',
ITEM_DETAIL: (id: string) => `/items/${id}`,
} as const;
// GOOD
const StatusSchema = z.enum(['pending', 'completed']);
type Status = z.infer<typeof StatusSchema>;
// BAD
navigate(`/items/${id}`);
type Status = string;
Type Generation Rules
- Check
packages/schema/src/api/first - All request/response types in schema package
- Add Zod schemas for runtime validation
- Export from index for both server and client
Component Development
Component Decision Flow
Need Component?
|
1. Check packages/components/ first <- ALWAYS START HERE
├── Exists? -> Use it
└── Doesn't exist
|
2. Reusable across features?
├── Yes -> Create in packages/components/
└── No -> Create in packages/ui/src/components/
Component Pattern
interface ItemListProps {
onToggle: (id: string) => void;
onDelete: (id: string) => void;
}
export function ItemList({ onToggle, onDelete }: ItemListProps) {
const { items, isLoading, error } = useItemStore();
if (isLoading) return <LoadingSpinner />;
if (error) return <ErrorMessage error={error} />;
return (
<ul className="space-y-2">
{items.map((item) => (
<ListItem key={item.id} item={item} onToggle={onToggle} onDelete={onDelete} />
))}
</ul>
);
}
State Management
TanStack Query (Server State)
export function useItems() {
return useQuery({
queryKey: ['items'],
queryFn: () => api.getItems(),
staleTime: 5 * 60 * 1000,
});
}
Zustand Store (Client State)
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
interface AppState {
items: Item[];
isLoading: boolean;
error: string | null;
fetchItems: () => Promise<void>;
}
export const useAppStore = create<AppState>()(
immer((set) => ({
items: [],
isLoading: false,
error: null,
fetchItems: async () => {
set({ isLoading: true, error: null });
try {
const items = await api.getItems();
set({ items, isLoading: false });
} catch (error) {
set({ error: 'Failed to fetch', isLoading: false });
}
},
}))
);
Decision Tree
Server data with caching? -> TanStack Query
Shared UI state? -> Zustand Store
Local component state? -> useState
Form Handling
react-hook-form + Zod
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
export function ItemForm({ onSubmit }: { onSubmit: (data: CreateItemInput) => void }) {
const form = useForm<CreateItemInput>({
resolver: zodResolver(createItemSchema),
defaultValues: { title: '', description: '' },
});
return (
<form onSubmit={form.handleSubmit(onSubmit)}>
<input {...form.register('title')} placeholder="Title" />
{form.formState.errors.title && (
<span>{form.formState.errors.title.message}</span>
)}
<button type="submit" disabled={form.formState.isSubmitting}>
{form.formState.isSubmitting ? 'Saving...' : 'Save'}
</button>
</form>
);
}
Testing Patterns
Priority Order
- Unit Tests First — Test logic in isolation
- MSW Integration Tests — Test API interactions
- E2E Tests Last — Only for critical user flows
Component Test
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { vi } from 'vitest';
describe('ItemList', () => {
it('should render items', () => {
render(<ItemList items={mockItems} onToggle={vi.fn()} onDelete={vi.fn()} />);
expect(screen.getByText('Test Item')).toBeInTheDocument();
});
it('should call onToggle when clicked', async () => {
const user = userEvent.setup();
const onToggle = vi.fn();
render(<ItemList items={mockItems} onToggle={onToggle} onDelete={vi.fn()} />);
await user.click(screen.getAllByRole('checkbox')[0]);
expect(onToggle).toHaveBeenCalledWith('1');
});
});
Common Commands
pnpm dev # Start dev server
pnpm build # Build for production
pnpm type-check # Type checking
# Testing
pnpm test:changed # FAST - Only changed files (RECOMMENDED)
pnpm test:unit # Unit tests only
pnpm test # All tests including e2e
pnpm vitest run --no-coverage src/components/ItemList.test.tsx # Specific file
Component Checklist
- Check packages/components/ first
- Check packages/schema/src/api/ for types
- Type-safe with TypeScript
- Zod validation for forms
- Accessible (ARIA attributes)
- Responsive design
- Loading and error states
- Unit tests first, then MSW/integration
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?