| name | frontend-dev |
| description | Frontend workflow with componentization and state management. Trigger: When building, refactoring, or scaling frontend apps. |
| license | Apache 2.0 |
| metadata | {"version":"1.0","type":"universal"} |
Frontend Development
Universal frontend workflow guiding componentization, state management, testing, and deployment. Technology-agnostic, orchestrates technical skills (react, typescript, a11y) without duplicating patterns.
When to Use
- Building, refactoring, or scaling frontend apps
- Managing state, side effects, or data flow
- Preparing for deployment or CI/CD
- Reviewing code quality
Don't use for:
- Technology-specific code (use react, typescript skills)
- Backend development (use backend-dev skill)
Critical Patterns
โ
REQUIRED: Componentization with Single Responsibility
Build small, reusable components that do one thing well.
Decision Tree:
- Component doing >1 thing? โ Split into focused components
- Logic mixed with presentation? โ Extract custom hooks
- Component >100 lines? โ Decompose into smaller units
Implementation: Delegate to react for component patterns
Example Decomposition:
Monolithic UserDashboard (200 lines)
โ
UserDashboard (layout coordinator, 20 lines)
โ UserList (renders list, 15 lines)
โ UserCard (single user, 25 lines)
โ Avatar (image display, 10 lines)
โ Button (action trigger, 8 lines)
โ LoadingSpinner (loading state, 5 lines)
When to Stop Decomposing:
- Component <30 lines AND single responsibility
- No reusable parts remain
- Further splitting hurts readability
โ
REQUIRED: State Management with Colocated State
Keep state as local as possible. Lift to global only when necessary.
Decision Tree:
Need state?
โ Used by 1 component? โ Local state (useState)
โ Used by 2-3 sibling components? โ Lift to parent
โ Used across component tree? โ Context API
โ Shared across entire app + complex updates? โ Redux/Zustand
Data from server?
โ Use React Query/SWR (NOT Redux for server state)
Derived state?
โ Compute during render (NOT useState)
โ Expensive computation? โ useMemo
Implementation: Delegate to react for state patterns
โ
REQUIRED: Testing with User-Centric Approach
Test behavior, not implementation. Simulate real user interactions.
Decision Tree:
What to test?
โ User flows (registration, checkout)? โ Integration tests (react-testing-library)
โ Edge cases + error states? โ Unit tests (jest)
โ Full app workflows? โ E2E tests (playwright)
How to query elements?
โ Prefer: getByRole, getByLabelText (accessible queries)
โ Avoid: getByTestId (implementation detail)
Implementation: Delegate to react-testing-library and unit-testing
Testing Priorities:
- Critical user flows (login, checkout, payment)
- Error states (network failure, validation errors)
- Edge cases (empty state, loading, no permissions)
- Accessibility (keyboard navigation, screen reader)
โ
REQUIRED: Environment-Based Configuration
Use environment variables for configuration. Never hardcode.
Decision Tree:
Need configuration?
โ API URL? โ VITE_API_URL / NEXT_PUBLIC_API_URL
โ Feature flags? โ VITE_ENABLE_FEATURE=true/false
โ Environment detection? โ import.meta.env.MODE / process.env.NODE_ENV
Sensitive data (API keys)?
โ NEVER in frontend code
โ Use backend proxy for API calls
Implementation: Delegate to framework-specific skills (next, vite)
Configuration Pattern:
config.ts
โ apiUrl (from env var, fallback to localhost)
โ environment (development | production)
โ features (object with boolean flags)
.env.example
โ Documents all required env vars
โ Committed to repo
.env.local
โ Actual values (NOT committed)
โ
REQUIRED: Component Hierarchy
When designing component tree:
- Identify data flow: Where does data originate? Where is it consumed?
- Find common ancestor: Lowest component that can own state
- Minimize prop drilling: If passing props >2 levels, consider context
- Separate concerns: Layout components (div, flex) vs logic components (data fetching, state)
Red Flags:
- Props passed through 3+ levels without being used
- Parent component knowing too much about child internals
- Component receiving >8 props (too many responsibilities)
โ
REQUIRED: Data Fetching Strategy
Decision Tree:
Fetching data?
โ Static content (marketing page)? โ SSG (Static Site Generation)
โ Dynamic content + SEO critical? โ SSR (Server-Side Rendering)
โ Dynamic content + NOT SEO critical? โ CSR (Client-Side Rendering)
Which library?
โ REST API? โ React Query / SWR
โ GraphQL? โ Apollo Client / urql
โ Real-time updates? โ WebSockets + React Query
Implementation: Delegate to framework skills (next, react)
โ
REQUIRED: Performance Optimization
When to optimize:
- Measure FIRST (React DevTools Profiler, Lighthouse)
- Identify bottlenecks (slow renders, large bundles)
- Apply targeted fixes (NOT premature optimization)
Common Optimizations:
- Lazy load routes โ React.lazy + Suspense
- Lazy load images โ Intersection Observer
- Memoize expensive calculations โ useMemo
- Prevent unnecessary re-renders โ React.memo, useCallback
- Code splitting โ Dynamic imports
Red Flags (Premature Optimization):
- Using React.memo everywhere "just in case"
- useCallback for simple functions
- Optimizing before measuring
Decision Tree
New feature?
โ Create isolated, testable component
State needed?
โ Local state first; global store only when shared across components
Deployment?
โ Automate with CI/CD (lint โ test โ build โ deploy)
Bug found?
โ Add/expand test coverage before fixing
Example
Building a product list page: component decomposition, state, data fetching, and testing.
function ProductListPage() {
const { data: products, isLoading, error } = useProducts();
const [search, setSearch] = useState("");
if (isLoading) return <LoadingSpinner />;
if (error) return <ErrorBanner message={error.message} />;
const filtered = products.filter(p => p.name.includes(search));
return (
<>
<SearchInput value={search} onChange={setSearch} />
<ProductGrid products={filtered} />
</>
);
}
function () {
({ : [], : api.() });
}
(, () => {
();
screen.();
userEvent.(screen.(), );
(screen.()).();
(screen.())..();
});
Patterns applied: component decomposition by responsibility, local state for UI, React Query for server state, derived state computed during render, getByRole accessible queries.
Edge Cases
-
State sync bugs: Race conditions occur when async operations complete out of order. Use cleanup functions in useEffect. Consider using state management libraries (Redux, Zustand) for complex async flows.
-
Build pipeline failures: Environment variables not set cause production builds to fail. Validate required env vars at build time. Use .env.example to document required variables.
-
Cross-browser or device-specific issues: Test on multiple browsers (Chrome, Firefox, Safari) and devices (mobile, tablet, desktop). Use feature detection instead of browser detection. Polyfill missing APIs.
-
Memory leaks: Event listeners, subscriptions, and timers not cleaned up cause memory leaks. Always return cleanup function from useEffect. Unsubscribe from observables.
-
Bundle size bloat: Importing entire libraries increases bundle size. Use tree-shaking compatible libraries. Import only what you need (import { Button } from 'library' not import * as Library).
Checklist
Workflow
E2E Development Workflow:
- brainstorming โ Evaluate alternatives, high-level planning
- writing-plans โ Break into executable tasks (2-5 min, file paths)
- frontend-dev (this skill) โ Apply Frontend Developer thinking and architecture
- plan-execution โ Execute in batches of 3 with checkpoints
- verification-protocol โ Verify each task (IDENTIFY โ RUN โ READ โ VERIFY โ CLAIM)
- code-review โ Two-stage review (spec compliance โ code quality)
Resources