← All skills
senior-frontend
Use when building React/Next.js components, optimizing Next.js performance, analyzing bundle size, scaffolding a frontend project, or reviewing frontend code quality and accessibility.
About this skill
Use when building React/Next.js components, optimizing Next.js performance, analyzing bundle size, scaffolding a frontend project, or reviewing frontend code quality and accessibility.
SKILL.md
senior-frontend.SKILL.mdPlace it in your Syntic skills folder. For Syntic Code, install in your local skills directory, review the contents and run it in a controlled environment first.
---
name: senior-frontend
description: Use when building React/Next.js components, optimizing Next.js performance, analyzing bundle size, scaffolding a frontend project, or reviewing frontend code quality and accessibility.
category: Engineering
version: 1.0.0
tools: []
---
# Senior Frontend
Frontend development patterns, performance optimization, and stack guidance for React and Next.js applications.
## Project Structure Baseline
A well-scaffolded Next.js project separates `app/` (routes, layouts, API routes), `components/ui` and `components/layout`, `hooks/`, `lib/` (utilities), and `types/`. Offer to add auth (NextAuth.js), an API client (React Query), forms (React Hook Form + Zod), or testing (Vitest + Testing Library) depending on the project's needs.
## Component Conventions
Default to client components only when the component needs event handlers, state, effects, or browser APIs; otherwise keep it a server component. Co-locate a component with its test and Storybook story when the codebase already uses those conventions. Example client component shape:
```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>;
}
```
## Bundle Analysis
Evaluate a project's `package.json` and import patterns for optimization opportunities and score the result out of 100 as a **Bundle Health Score** — also referred to as the **Bundle Score**:
| 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 |
Flag known heavy dependencies and their lighter alternatives:
| 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 |
## React Patterns
**Compound components** share state via context (e.g., a `Tabs` component exposing `Tabs.List`/`Tabs.Panel` through a shared context provider).
**Custom hooks** extract reusable logic — e.g., `useDebounce<T>(value, delay)` returns a debounced value via a cleanup-guarded `setTimeout`.
**Render props** share rendering logic — e.g., a `DataFetcher` component that fetches a URL into state and calls a `render({ data, loading })` prop.
## Next.js Optimization
Use Server Components by default; add `'use client'` only for event handlers, state, effects, or browser APIs. Fetch data server-side and pass client-only interactivity (e.g. an "Add to Cart" button) down as a client component.
Use `next/image` with `priority` for above-the-fold hero images and `fill` + `sizes` for responsive images elsewhere. Fetch independent data in parallel with `Promise.all`; stream slower sections behind `<Suspense>` so the page shell renders immediately.
## Accessibility and Testing
Checklist: semantic HTML (`<button>`, `<nav>`, `<main>`); full keyboard navigation; ARIA labels on icons and complex widgets; minimum 4.5:1 color contrast for normal text; visible focus indicators (e.g. `focus-visible:ring-2`); a skip-to-content link for keyboard users.
Test with React Testing Library — assert on behavior (`getByRole`, user-event clicks) and accessibility attributes (`aria-labelledby`, role) rather than implementation details:
```tsx
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('dialog is accessible', async () => {
render(<Dialog open={true} title="Confirm" />);
expect(screen.getByRole('dialog')).toBeInTheDocument();
expect(screen.getByRole('dialog')).toHaveAttribute('aria-labelledby');
});
```
## Quick Reference
Common `next.config.js` needs: `images.remotePatterns` for external image hosts, AVIF/WebP formats, and `experimental.optimizePackageImports` for icon libraries. Use a `cn()` helper to compose conditional Tailwind classes. For reusable typed components, prefer a generic `ListProps<T>` shape over `any`.
## Forcing Questions Before Recommending
Before scaffolding a component, recommending a framework, or auditing a bundle, surface four assumptions:
1. **Primary user device + network** — mobile-4G, desktop-fiber, low-end-Android, or corporate network; drives every performance decision
2. **LCP target in milliseconds** — a single number, not "fast"; drives bundle budget and rendering choice
3. **SEO-dependent vs. auth-walled** — drives rendering choice (SSR/SSG/RSC vs. SPA)
4. **WCAG target + a named accessibility owner** — AA, AAA, or best-effort; drives investment and gates
Every recommendation must state verifiable success criteria: Core Web Vitals targets (LCP, INP, CLS) at p75 on the primary device, a per-route JS bundle budget in KB-gzip, and a Lighthouse accessibility and performance floor. If any of the three is missing, the recommendation is incomplete.
## Stack Profiles
Four reference profiles calibrate recommendations by primary device, LCP target, and bundle budget:
| Profile | When to pick | LCP target (mobile-4G p75) | Bundle budget |
|---|---|---|---|
| Next.js App Router | SaaS customer-facing, SEO + dynamic, RSC-first | 2000ms | 150 KB-gzip / route |
| Remix or SvelteKit | Mobile-4G primary, low-JS-first, progressive enhancement | 1500ms | 80 KB-gzip / route |
| Vite SPA | Auth-walled app, desktop/corporate primary | 2500ms | 200 KB init + 80 KB / route |
| Astro or static | Marketing / docs / blog, near-zero write, SEO-critical | 1200ms | 30 KB JS / page |
Pick the best-fit profile from the stated device, LCP target, SEO dependency, and auth-wall status; name the runner-up tradeoff when it's within 15%, and call out the anti-patterns to avoid on the chosen profile.
## When to Hand Off
Route to a specialist teammate for: WCAG audits and screen-reader testing; deep bundle/runtime performance profiling; cinematic or scroll-storytelling landing pages; Apple Human Interface Guidelines work (iOS/macOS/visionOS). @mention the relevant teammate rather than attempting deep specialist work here.
Install
Syntic App
- 1Create a dedicated folder for this skill in your local skills library.
- 2Place SKILL.md into that folder.
- 3Restart Syntic and invoke this skill on matching tasks.
Syntic Code (CLI)
- 1Save SKILL.md in your local Syntic Code skills directory.
- 2Keep related files in the same skill folder.
- 3Run in a safe environment and validate outputs.