
Frontend Builder
- 197 installs
- 33 repo stars
- Updated December 25, 2025
- daffy0208/ai-dev-standards
Scaffold and implement UI pages, components, state management, routing, and responsive layouts using modern frontend frameworks for web and hybrid mobile product surfaces.
About
Builds production frontend surfaces: scaffolds components and routes, applies responsive layouts and design systems, wires client state and API consumption, and follows framework conventions so SaaS and content apps ship polished interactive UIs.
- Component and page scaffolding
- Responsive layout and design tokens
- Client routing and state management
- Framework-specific best practices
Frontend Builder by the numbers
- 197 all-time installs (skills.sh)
- Ranked #862 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Data as of Jul 30, 2026 (Skillselion catalog sync)
npx skills add https://github.com/daffy0208/ai-dev-standards --skill frontend-builderAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 197 |
|---|---|
| repo stars | ★ 33 |
| Last updated | December 25, 2025 |
| Repository | daffy0208/ai-dev-standards ↗ |
What it does
Scaffold and implement UI pages, components, state management, routing, and responsive layouts using modern frontend frameworks for web and hybrid mobile product surfaces.
Files
Frontend Builder
Build maintainable, performant React and Next.js frontends.
Core Principles
1. Component Composition
Break UI into small, reusable, single-purpose components
2. State Proximity
Keep state as close to where it's used as possible
3. Performance by Default
Optimize rendering, code splitting, and asset loading
4. Developer Experience
Clear naming, consistent patterns, helpful errors
Framework Selection
React (Vite) vs. Next.js
Use React + Vite when:
- Client-side only application
- No SEO requirements
- Simple deployment (static hosting)
- Faster initial setup
Use Next.js when:
- SEO important (marketing sites, blogs, e-commerce)
- Server-side rendering needed
- API routes required
- File-based routing preferred
- Image optimization critical
Recommended for most projects: Next.js (App Router)
---
Component Architecture
Component Types
1. Page Components (Route entry points):
// app/users/page.tsx (Next.js App Router)
export default function UsersPage() {
return (
<div>
<Header />
<UserList />
<Footer />
</div>
)
}2. Feature Components (Business logic):
// components/features/UserList.tsx
export function UserList() {
const { data, isLoading } = useUsers()
if (isLoading) return <LoadingSpinner />
return (
<div>
{data.map(user => <UserCard key={user.id} user={user} />)}
</div>
)
}3. UI Components (Reusable, no business logic):
// components/ui/button.tsx
export function Button({ children, variant = 'primary', ...props }) {
return (
<button
className={cn(buttonVariants[variant])}
{...props}
>
{children}
</button>
)
}Component Best Practices
// ✅ Good: Small, focused, typed
interface UserProfileProps {
user: User
onEdit?: () => void
}
export function UserProfile({ user, onEdit }: UserProfileProps) {
return (
<div className="flex gap-4">
<Avatar src={user.avatar} alt={user.name} />
<UserDetails user={user} />
{onEdit && <Button onClick={onEdit}>Edit</Button>}
</div>
)
}
// ❌ Bad: Giant, untyped, unclear
export function UserProfile(props) {
// 500 lines of JSX, multiple responsibilities
return <div>...</div>
}---
State Management
Decision Tree
How many components need this state?
│
├─ One component → useState
├─ Parent + children → Props or useState + props
├─ Siblings → Lift to common parent
├─ Widely used (theme, auth) → Context API
└─ Complex app state → Zustand or ReduxLocal State (useState)
// For component-level state
function Counter() {
const [count, setCount] = useState(0)
const [isOpen, setIsOpen] = useState(false)
return (
<div>
<button onClick={() => setCount(count + 1)}>{count}</button>
</div>
)
}Context API
// For app-wide state (theme, auth, user)
const UserContext = createContext<UserContextType | undefined>(undefined)
export function UserProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User | null>(null)
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
)
}
export function useUser() {
const context = useContext(UserContext)
if (!context) throw new Error('useUser must be within UserProvider')
return context
}Zustand (Recommended for Complex State)
import { create } from 'zustand'
interface CounterStore {
count: number
increment: () => void
decrement: () => void
reset: () => void
}
export const useCounterStore = create<CounterStore>((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
reset: () => set({ count: 0 })
}))
// Usage
function Counter() {
const { count, increment } = useCounterStore()
return <button onClick={increment}>{count}</button>
}---
Data Fetching
React Query (Recommended)
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
// Query (GET)
function Users() {
const { data, isLoading, error } = useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
staleTime: 5 * 60 * 1000 // 5 minutes
})
if (isLoading) return <LoadingSpinner />
if (error) return <ErrorMessage error={error} />
return <UserList users={data} />
}
// Mutation (POST, PUT, DELETE)
function CreateUser() {
const queryClient = useQueryClient()
const mutation = useMutation({
mutationFn: createUser,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['users'] })
}
})
return (
<button onClick={() => mutation.mutate({ name: 'John' })}>
Create User
</button>
)
}Next.js Server Components (App Router)
// app/users/page.tsx
// Server Component - fetches on server
export default async function UsersPage() {
const users = await fetchUsers() // Runs on server
return <UserList users={users} />
}
// Client Component - for interactivity
'use client'
export function UserList({ users }: { users: User[] }) {
const [selected, setSelected] = useState<string | null>(null)
return (
<div>
{users.map(user => (
<UserCard
key={user.id}
user={user}
onClick={() => setSelected(user.id)}
/>
))}
</div>
)
}---
Form Handling
React Hook Form (Recommended)
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
const loginSchema = z.object({
email: z.string().email('Invalid email address'),
password: z.string().min(8, 'Password must be at least 8 characters')
})
type LoginForm = z.infer<typeof loginSchema>
function LoginForm() {
const {
register,
handleSubmit,
formState: { errors, isSubmitting }
} = useForm<LoginForm>({
resolver: zodResolver(loginSchema)
})
const onSubmit = async (data: LoginForm) => {
await login(data)
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<input
{...register('email')}
type="email"
placeholder="Email"
className="border p-2"
/>
{errors.email && (
<span className="text-red-500">{errors.email.message}</span>
)}
</div>
<div>
<input
{...register('password')}
type="password"
placeholder="Password"
className="border p-2"
/>
{errors.password && (
<span className="text-red-500">{errors.password.message}</span>
)}
</div>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'Logging in...' : 'Login'}
</button>
</form>
)
}---
Styling
Tailwind CSS (Recommended)
// Install: @shadcn/ui for component library
function Button({ variant = 'primary', children, ...props }) {
return (
<button
className={cn(
'px-4 py-2 rounded font-medium transition-colors',
{
'bg-blue-500 text-white hover:bg-blue-600': variant === 'primary',
'bg-gray-200 text-gray-900 hover:bg-gray-300': variant === 'secondary',
'bg-red-500 text-white hover:bg-red-600': variant === 'danger'
}
)}
{...props}
>
{children}
</button>
)
}CSS Modules (Alternative)
// Button.module.css
.button {
padding: 0.5rem 1rem;
border-radius: 0.25rem;
}
.primary {
background-color: blue;
color: white;
}
// Button.tsx
import styles from './Button.module.css'
export function Button({ variant = 'primary', children }) {
return (
<button className={`${styles.button} ${styles[variant]}`}>
{children}
</button>
)
}---
Performance Optimization
React Optimization
import { memo, useMemo, useCallback } from 'react'
// 1. Memoize expensive calculations
function DataTable({ data }) {
const sortedData = useMemo(
() => data.sort((a, b) => a.name.localeCompare(b.name)),
[data]
)
return <Table data={sortedData} />
}
// 2. Memoize callbacks
function Parent() {
const handleClick = useCallback(() => {
console.log('Clicked')
}, [])
return <ExpensiveChild onClick={handleClick} />
}
// 3. Memoize components
const ExpensiveChild = memo(function ExpensiveChild({ onClick }) {
return <button onClick={onClick}>Click</button>
})Next.js Optimization
// 1. Image optimization
import Image from 'next/image'
<Image
src="/photo.jpg"
alt="Photo"
width={500}
height={300}
priority // Above the fold
/>
// 2. Font optimization
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
export default function RootLayout({ children }) {
return (
<html className={inter.className}>
<body>{children}</body>
</html>
)
}
// 3. Dynamic imports (code splitting)
import dynamic from 'next/dynamic'
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
loading: () => <LoadingSpinner />
})---
Error Handling
Error Boundary
'use client'
import { Component, ReactNode } from 'react'
interface Props {
children: ReactNode
fallback?: ReactNode
}
interface State {
hasError: boolean
error?: Error
}
export class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props)
this.state = { hasError: false }
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error }
}
render() {
if (this.state.hasError) {
return this.props.fallback || (
<div className="p-4 bg-red-50 border border-red-200">
<h2 className="text-red-800">Something went wrong</h2>
<p className="text-red-600">{this.state.error?.message}</p>
</div>
)
}
return this.props.children
}
}Next.js Error Handling
// app/error.tsx
'use client'
export default function Error({
error,
reset
}: {
error: Error
reset: () => void
}) {
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={reset}>Try again</button>
</div>
)
}---
Folder Structure
Next.js App Router
app/
├── (auth)/ # Route group (auth pages)
│ ├── login/
│ └── signup/
├── (dashboard)/ # Route group (dashboard)
│ ├── layout.tsx
│ ├── page.tsx
│ └── settings/
├── api/ # API routes
│ └── users/
│ └── route.ts
└── layout.tsx # Root layout
components/
├── ui/ # shadcn/ui components
│ ├── button.tsx
│ ├── input.tsx
│ └── dialog.tsx
├── features/ # Feature components
│ ├── UserList.tsx
│ └── UserProfile.tsx
└── layouts/ # Layout components
├── Header.tsx
└── Footer.tsx
lib/
├── utils.ts # Utility functions
├── api.ts # API client
└── validation.ts # Zod schemas
hooks/
├── useUser.ts
└── useDebounce.ts
stores/
└── userStore.ts # Zustand stores---
TypeScript Best Practices
// 1. Type component props
interface ButtonProps {
variant?: 'primary' | 'secondary' | 'danger'
children: ReactNode
onClick?: () => void
}
export function Button({ variant = 'primary', children, onClick }: ButtonProps) {
return <button onClick={onClick}>{children}</button>
}
// 2. Type API responses
interface User {
id: string
name: string
email: string
}
async function fetchUsers(): Promise<User[]> {
const res = await fetch('/api/users')
return res.json()
}
// 3. Type state
const [user, setUser] = useState<User | null>(null)
const [isLoading, setIsLoading] = useState<boolean>(false)---
Summary
Great frontends:
- ✅ Use Next.js for most projects (SEO, performance, DX)
- ✅ Break UI into small, typed components
- ✅ Choose appropriate state management (useState → Context → Zustand)
- ✅ Use React Query for server state
- ✅ Style with Tailwind CSS + shadcn/ui
- ✅ Optimize with memoization and code splitting
- ✅ Handle errors gracefully with Error Boundaries
- ✅ Follow consistent folder structure
---
Related Resources
Related Skills:
api-designer- For designing backend APIs to consumeux-designer- For creating UX designs to implementdeployment-advisor- For hosting Next.js/React apps
Related Patterns:
META/DECISION-FRAMEWORK.md- Frontend framework selectionSTANDARDS/architecture-patterns/component-patterns.md- Component design patterns (when created)
Related Playbooks:
PLAYBOOKS/setup-nextjs-project.md- Next.js project setup (when created)PLAYBOOKS/optimize-frontend-performance.md- Performance optimization (when created)
name: frontend-builder
kind: skill
description: Build modern React/Next.js frontends with proper component architecture, state management, and performance optimization
preconditions:
- check: file_exists('package.json')
description: Node.js project initialized
required: true
- check: not file_exists('app/') and not file_exists('src/')
description: No existing frontend structure
required: false
- check: has_dependency('react') or ready_to_install('react')
description: React framework available
required: true
effects:
- creates_component_architecture
- configures_nextjs_app_router
- implements_state_management
- adds_form_validation
- configures_tailwind_css
- implements_data_fetching
- adds_error_boundaries
- optimizes_performance
- configures_typescript
domains:
- frontend
- react
- nextjs
- ui
- component-architecture
- state-management
- typescript
- tailwindcss
cost: low
latency: fast
risk_level: low
side_effects:
- modifies_files
- installs_dependencies
- creates_folder_structure
- configures_build_tools
idempotent: false
success_signal: "Next.js/React app builds successfully, components render correctly, tests pass, TypeScript compiles without errors"
failure_signals:
- "Build fails with TypeScript errors"
- "Components fail to render"
- "State management issues"
- "Performance issues (slow rendering)"
- "Dependency conflicts"
compatibility:
requires:
- node-js
- npm-or-yarn
conflicts_with:
- vue-frontend
- angular-frontend
composes_with:
- api-designer
- design-system-architect
- ux-designer
- testing-strategist
- performance-optimizer
enables:
- interactive-ui
- client-side-routing
- server-side-rendering
- static-site-generation
observability:
logs:
- "Building Next.js app..."
- "Creating component: {component_name}"
- "Configuring state management with {library}"
- "Installing dependencies: {packages}"
metrics:
- build_time_ms
- bundle_size_kb
- component_count
- render_performance_ms
- lighthouse_score
metadata:
version: "1.0.0"
created_at: "2025-10-28"
tags:
- frontend
- react
- nextjs
- components
- ui
- typescript
- tailwind
examples:
- "Build Next.js app with App Router"
- "Create component library with TypeScript"
- "Implement state management with Zustand"
- "Build responsive UI with Tailwind CSS"
Frontend Builder - Quick Start
Version: 1.0.0 Category: Technical Development Difficulty: Intermediate
What This Skill Does
Guides development of modern React and Next.js frontends with best practices for component architecture, state management, data fetching, forms, styling, and performance.
When to Use
Use this skill when you need to:
- Build a new web application (React or Next.js)
- Choose frontend stack and architecture
- Structure components and folders
- Implement UI/UX designs
- Optimize frontend performance
- Set up state management
Quick Start
Fastest path to a production-ready frontend:
1. Choose framework
- Next.js: SEO, SSR, file routing (recommended for most)
- React + Vite: Client-side only, simpler setup
2. Initialize project
npx create-next-app@latest my-app --typescript --tailwind --app
# or
npm create vite@latest my-app -- --template react-ts3. Install core dependencies
npm install @tanstack/react-query zustand react-hook-form zod
npm install -D @shadcn/ui4. Set up folder structure
app/ or src/
├── components/ui/ # shadcn components
├── components/features/ # Business logic
├── lib/ # Utils, API client
├── hooks/ # Custom hooks
└── stores/ # Zustand stores5. Build components
- Start with UI components (Button, Input, etc.)
- Build feature components (UserList, Dashboard, etc.)
- Compose pages from components
6. Add data fetching (React Query)
- Queries for GET requests
- Mutations for POST/PUT/DELETE
- Automatic caching and revalidation
7. Optimize
- Memoize expensive calculations (
useMemo) - Memoize components (
memo) - Code split heavy components (
dynamic)
Time to first page: 1-2 days for setup + basic pages
File Structure
frontend-builder/
├── SKILL.md # Main skill instructions (start here)
└── README.md # This filePrerequisites
Knowledge:
- JavaScript/TypeScript basics
- React fundamentals (components, props, state, hooks)
- HTML and CSS
Tools:
- Node.js 18+ and npm/pnpm/yarn
- Code editor (VS Code recommended)
- Browser dev tools
Related Skills:
api-designerhelps design APIs to consumeux-designerprovides designs to implement
Success Criteria
You've successfully used this skill when:
- ✅ Next.js or React + Vite project set up with TypeScript
- ✅ Components organized in clear folder structure
- ✅ State management strategy chosen (useState → Context → Zustand)
- ✅ Data fetching implemented with React Query
- ✅ Forms handled with React Hook Form + Zod validation
- ✅ Styled with Tailwind CSS + shadcn/ui components
- ✅ Error boundaries implemented
- ✅ Performance optimizations applied (memoization, code splitting)
- ✅ TypeScript types defined for props and API responses
Common Workflows
Workflow 1: New Next.js App
1. Use frontend-builder to initialize Next.js with App Router 2. Set up shadcn/ui for component library 3. Install React Query for data fetching 4. Build page layouts and components 5. Use api-designer for backend API 6. Use deployment-advisor for hosting (Vercel recommended)
Workflow 2: Complex State Management
1. Start with useState for local state 2. Lift state to parent when siblings need it 3. Use Context API for widely-used state (theme, auth) 4. Use Zustand for complex app state (shopping cart, filters) 5. Use React Query for server state (users, posts, products)
Workflow 3: Performance Optimization
1. Use frontend-builder performance section 2. Identify slow renders with React DevTools Profiler 3. Apply useMemo for expensive calculations 4. Apply memo for frequently re-rendering components 5. Use Next.js dynamic imports for code splitting 6. Optimize images with Next.js Image component 7. Use performance-optimizer skill for advanced techniques
Key Concepts
Component Types:
- Page: Route entry points (
app/users/page.tsx) - Feature: Business logic (
components/features/UserList.tsx) - UI: Reusable, no logic (
components/ui/button.tsx)
State Management Decision:
One component → useState
Parent + children → Props
Siblings → Lift to parent
Widely used → Context API
Complex app state → Zustand
Server state → React QueryNext.js vs React:
- Next.js: SEO, SSR, file routing, image optimization, API routes
- React + Vite: Client-side, simpler, faster dev server, custom routing
Styling Options:
- Tailwind CSS: Utility-first, fast, no CSS files (recommended)
- CSS Modules: Scoped, traditional CSS
- CSS-in-JS: Styled-components, Emotion (less common now)
Data Fetching:
- React Query: Caching, revalidation, mutations (recommended)
- SWR: Similar to React Query, by Vercel
- useEffect + fetch: Manual, not recommended for production
Troubleshooting
Skill not activating?
- Try explicitly requesting: "Use the frontend-builder skill to..."
- Mention keywords: "frontend", "React", "Next.js", "components", "UI"
Choosing between Next.js and React?
- Next.js: SEO needed, blog, marketing site, e-commerce, full-stack app
- React + Vite: Internal tool, admin panel, single-page app, no SEO
- Default recommendation: Next.js (more features, better DX)
State management confusion?
- Start simple: useState for component state
- Lift state up when siblings need it
- Context for app-wide state (theme, auth)
- Zustand for complex state (shopping cart, filters)
- React Query for server data (users, posts) - NOT Zustand
- Don't over-engineer: most apps only need useState + React Query
Component re-rendering too much?
- Use React DevTools Profiler to identify slow components
- Apply
memoto expensive components - Use
useMemofor expensive calculations - Use
useCallbackfor functions passed as props - Check dependencies arrays in useEffect, useMemo, useCallback
Forms not validating?
- Use React Hook Form + Zod for validation
- Define Zod schema before form
- Use zodResolver in useForm
- Access errors via formState.errors
- Show error messages below inputs
Tailwind classes not working?
- Check tailwind.config.js includes content paths
- Restart dev server after config changes
- Use VS Code Tailwind CSS IntelliSense extension
- Check for typos in class names
- Use
cn()helper from shadcn for conditional classes
Build errors with TypeScript?
- Define interfaces for all component props
- Type useState:
useState<User | null>(null) - Type API responses with interfaces
- Use
ReactNodefor children prop - Enable strict mode in tsconfig.json
Version History
- 1.0.0 (2025-10-21): Initial release, enhanced from frontend-builder skill with comprehensive Next.js and React Query coverage
License
Part of ai-dev-standards repository.