.claude/skills/senior-frontend/SKILL.md
Provides senior-level React, Next.js, TypeScript, and Tailwind CSS frontend development including component architecture, performance optimization, and accessibility. Use when the user needs advanced frontend guidance or mentions React components, Next.js performance, or frontend architecture.
npx skillsauth add tranhieutt/software_development_department senior-frontendInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
return in server components before client boundary — mixing async server + client state without boundaries causes hydration mismatchespriority on LCP images only — adding priority everywhere defeats preload budgetsuse client at the leaf, not the root — push client boundary as deep as possible to maximize RSC treePromise.all([...]) at the page level, not sequential awaitsmoment (290KB) → dayjs (2KB); lodash → lodash-es with tree-shaking; axios → native fetch// Server Component (default) — fetch directly, no hooks
async function ProductPage({ params }: { params: { id: string } }) {
const [product, reviews] = await Promise.all([ // parallel fetch
getProduct(params.id),
getReviews(params.id),
]);
return (
<div>
<h1>{product.name}</h1>
<Suspense fallback={<ReviewsSkeleton />}>
<Reviews productId={params.id} /> {/* can defer slow queries */}
</Suspense>
<AddToCartButton productId={product.id} /> {/* client boundary at leaf */}
</div>
);
}
// Client Component — only where interactivity needed
"use client";
function AddToCartButton({ productId }: { productId: string }) {
const [adding, setAdding] = useState(false);
return <button onClick={() => addToCart(productId)}>Add to Cart</button>;
}
// next.config.js
const nextConfig = {
images: {
remotePatterns: [{ hostname: "cdn.example.com" }],
formats: ["image/avif", "image/webp"],
},
experimental: {
optimizePackageImports: ["lucide-react", "@heroicons/react"], // tree-shake icon libs
},
};
// Generic list component
function List<T extends { id: string }>({ items, renderItem }: {
items: T[];
renderItem: (item: T) => React.ReactNode;
}) {
return <ul>{items.map(item => <li key={item.id}>{renderItem(item)}</li>)}</ul>;
}
// Props extending HTML element
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: "primary" | "ghost" | "danger";
isLoading?: boolean;
}
export function Button({ variant = "primary", isLoading, children, ...props }: ButtonProps) {
return (
<button {...props} disabled={props.disabled || isLoading} aria-busy={isLoading}
className={cn("px-4 py-2 rounded font-medium focus-visible:ring-2",
variant === "primary" && "bg-blue-600 text-white hover:bg-blue-700",
variant === "danger" && "bg-red-600 text-white",
(props.disabled || isLoading) && "opacity-50 cursor-not-allowed"
)}>
{isLoading && <Spinner aria-hidden />}
{children}
</button>
);
}
Common heavy deps to replace:
| Package | Size | Alternative |
|---|---|---|
| moment | 290KB | dayjs (2KB) or date-fns (12KB) |
| lodash | 71KB | lodash-es (tree-shakeable) |
| axios | 14KB | native fetch or ky (3KB) |
| @mui/material | Large | shadcn/ui or Radix UI |
# Analyze bundle
npx @next/bundle-analyzer # or
npx vite-bundle-visualizer
// Skip link — place before main nav
<a href="#main-content" className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4">
Skip to main content
</a>
// Icon button — always label
<button type="button" aria-label="Close dialog" className="focus-visible:ring-2">
<XIcon aria-hidden="true" />
</button>
// Minimum contrast: 4.5:1 for text, 3:1 for UI components
app/
├── layout.tsx # Root layout: fonts, providers, metadata
├── page.tsx
├── (auth)/ # Route group — no URL segment
│ ├── login/page.tsx
│ └── register/page.tsx
└── api/
└── [route]/route.ts
components/
├── ui/ # Button, Input, Card (reusable primitives)
└── features/ # Domain-specific composites
hooks/ # useDebounce, useLocalStorage, useMediaQuery
lib/
├── utils.ts # cn(), formatDate()
└── api.ts # API client
types/ # Shared TypeScript types
testing
Generates high-fidelity architecture diagrams, sequence flows, and component maps for SDD projects. Use when finalizing a design phase, documenting system architecture, or visualizing agentic workflows. Default style: Style 6 (Claude Official).
data-ai
Provides vector database and semantic search patterns for Pinecone, Weaviate, Qdrant, Milvus, and pgvector in RAG and recommendation systems. Use when implementing vector search or when the user mentions vector database, semantic search, embeddings, or similarity search.
development
Updates docs/technical/CODEMAP.md by scanning the current codebase structure. Run after a significant feature merge, refactor, or when CODEMAP feels stale.
development
Unlocks the codebase after a release freeze or incident freeze period to resume normal development. Use when a freeze period ends or when the user mentions unfreezing or lifting the code freeze.