Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Frontend development skill for React, Next.js, TypeScript, and Tailwind CSS applications. Use when building React components, optimizing Next.js performance, analyzing bundle sizes, scaffolding frontend projects, implementing accessibility, or reviewing frontend code quality.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 132% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 48% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 47% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 94% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 289% | 0% |
Frontend development patterns, performance optimization, and automation tools for React/Next.js applications.
Generate a new Next.js or React project with TypeScript, Tailwind CSS, and best practice configurations.
bash python scripts/frontend_scaffolder.py my-app --template nextjs
bash python scripts/frontend_scaffolder.py dashboard --template nextjs --features auth,api
bash cd my-app && npm install
bash npm run dev
| Option | Description | | -------------------- | ------------------------------------------------- | | --template nextjs | Next.js 14+ with App Router and Server Components | | --template react | React + Vite with TypeScript | | --features auth | Add NextAuth.js authentication | | --features api | Add React Query + API client | | --features forms | Add React Hook Form + Zod validation | | --features testing | Add Vitest + Testing Library | | --dry-run | Preview files without creating them |
my-app/
├── app/
│ ├── layout.tsx # Root layout with fonts
│ ├── page.tsx # Home page
│ ├── globals.css # Tailwind + CSS variables
│ └── api/health/route.ts
├── components/
│ ├── ui/ # Button, Input, Card
│ └── layout/ # Header, Footer, Sidebar
├── hooks/ # useDebounce, useLocalStorage
├── lib/ # utils (cn), constants
├── types/ # TypeScript interfaces
├── tailwind.config.ts
├── next.config.js
└── package.jsonGenerate React components with TypeScript, tests, and Storybook stories.
bash python scripts/component_generator.py Button --dir src/components/ui
bash python scripts/component_generator.py ProductCard --type server
bash python scripts/component_generator.py UserProfile --with-test --with-story
bash python scripts/component_generator.py FormValidation --type hook
| Option | Description | | --------------- | -------------------------------------------- | | --type client | Client component with 'use client' (default) | | --type server | Async server component | | --type hook | Custom React hook | | --with-test | Include test file | | --with-story | Include Storybook story | | --flat | Create in output dir without subdirectory | | --dry-run | Preview without creating files |
tsx"use client"; import { useState } from "react"; import { cn } from "@/lib/utils"; interface ButtonProps { className?: string; children?: React.ReactNode; } export function Button({ className, children }: ButtonProps) { return <div className={cn("", className)}>{children}</div>; }
Analyze package.json and project structure for bundle optimization opportunities.
bash python scripts/bundle_analyzer.py /path/to/project
Bundle Health Score: 75/100 (C)
HEAVY DEPENDENCIES: moment (290KB) Alternative: date-fns (12KB) or dayjs (2KB)
lodash (71KB) Alternative: lodash-es with tree-shaking
bash python scripts/bundle_analyzer.py . --verbose
| Score | Grade | Action | | ------ | ----- | ------------------------------ | | 90-100 | A | Bundle is well-optimized | | 80-89 | B | Minor optimizations available | | 70-79 | C | Replace heavy dependencies | | 60-69 | D | Multiple issues need attention | | 0-59 | F | Critical bundle size problems |
The analyzer identifies these common heavy packages:
| Package | Size | Alternative | | ------------- | ----- | ------------------------------ | | moment | 290KB | date-fns (12KB) or dayjs (2KB) | | lodash | 71KB | lodash-es with tree-shaking | | axios | 14KB | Native fetch or ky (3KB) | | jquery | 87KB | Native DOM APIs | | @mui/material | Large | shadcn/ui or Radix UI |
Reference: references/react_patterns.md
Share state between related components:
tsxconst Tabs = ({ children }) => { const [active, setActive] = useState(0); return ( <TabsContext.Provider value={{ active, setActive }}> {children} </TabsContext.Provider> ); }; Tabs.List = TabList; Tabs.Panel = TabPanel; // Usage <Tabs> <Tabs.List> <Tabs.Tab>One</Tabs.Tab> <Tabs.Tab>Two</Tabs.Tab> </Tabs.List> <Tabs.Panel>Content 1</Tabs.Panel> <Tabs.Panel>Content 2</Tabs.Panel> </Tabs>;
Extract reusable logic:
tsxfunction useDebounce<T>(value: T, delay = 500): T { const [debouncedValue, setDebouncedValue] = useState(value); useEffect(() => { const timer = setTimeout(() => setDebouncedValue(value), delay); return () => clearTimeout(timer); }, [value, delay]); return debouncedValue; } // Usage const debouncedSearch = useDebounce(searchTerm, 300);
Share rendering logic:
tsxfunction DataFetcher({ url, render }) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { fetch(url) .then((r) => r.json()) .then(setData) .finally(() => setLoading(false)); }, [url]); return render({ data, loading }); } // Usage <DataFetcher url="/api/users" render={({ data, loading }) => loading ? <Spinner /> : <UserList users={data} /> } />;
Reference: references/nextjs_optimization_guide.md
Use Server Components by default. Add 'use client' only when you need:
tsx// Server Component (default) - no 'use client' async function ProductPage({ params }) { const product = await getProduct(params.id); // Server-side fetch return ( <div> <h1>{product.name}</h1> <AddToCartButton productId={product.id} /> {/* Client component */} </div> ); } // Client Component ("use client"); function AddToCartButton({ productId }) { const [adding, setAdding] = useState(false); return <button onClick={() => addToCart(productId)}>Add</button>; }
tsximport Image from 'next/image'; // Above the fold - load immediately <Image src="/hero.jpg" alt="Hero" width={1200} height={600} priority /> // Responsive image with fill <div className="relative aspect-video"> <Image src="/product.jpg" alt="Product" fill sizes="(max-width: 768px) 100vw, 50vw" className="object-cover" /> </div>
tsx// Parallel fetching async function Dashboard() { const [user, stats] = await Promise.all([getUser(), getStats()]); return <div>...</div>; } // Streaming with Suspense async function ProductPage({ params }) { return ( <div> <ProductDetails id={params.id} /> <Suspense fallback={<ReviewsSkeleton />}> <Reviews productId={params.id} /> </Suspense> </div> ); }
Reference: references/frontend_best_practices.md
<button>, <nav>, <main>)tsx// Accessible button <button type="button" aria-label="Close dialog" onClick={onClose} className="focus-visible:ring-2 focus-visible:ring-blue-500" > <XIcon aria-hidden="true" /> </button> // Skip link for keyboard users <a href="#main-content" className="sr-only focus:not-sr-only"> Skip to main content </a>
tsx// Component test with React Testing Library import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; test("button triggers action on click", async () => { const onClick = vi.fn(); render(<Button onClick={onClick}>Click me</Button>); await userEvent.click(screen.getByRole("button")); expect(onClick).toHaveBeenCalledTimes(1); }); // Test accessibility test("dialog is accessible", async () => { render(<Dialog open={true} title="Confirm" />); expect(screen.getByRole("dialog")).toBeInTheDocument(); expect(screen.getByRole("dialog")).toHaveAttribute("aria-labelledby"); });
js// next.config.js const nextConfig = { images: { remotePatterns: [{ hostname: "cdn.example.com" }], formats: ["image/avif", "image/webp"], }, experimental: { optimizePackageImports: ["lucide-react", "@heroicons/react"], }, };
tsx// Conditional classes with cn() import { cn } from "@/lib/utils"; <button className={cn( "px-4 py-2 rounded", variant === "primary" && "bg-blue-500 text-white", disabled && "opacity-50 cursor-not-allowed", )} />;
tsx// Props with children interface CardProps { className?: string; children: React.ReactNode; } // Generic component interface ListProps<T> { items: T[]; renderItem: (item: T) => React.ReactNode; } function List<T>({ items, renderItem }: ListProps<T>) { return <ul>{items.map(renderItem)}</ul>; }
references/react_patterns.mdreferences/nextjs_optimization_guide.mdreferences/frontend_best_practices.mdOther measured skills in the registry, with their headline benchmark lift.