Syntic
← All skills
EngineeringFreeCommunityv1.0.0

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.md

Place 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.

SKILL.md
---
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

  1. 1Create a dedicated folder for this skill in your local skills library.
  2. 2Place SKILL.md into that folder.
  3. 3Restart Syntic and invoke this skill on matching tasks.

Syntic Code (CLI)

  1. 1Save SKILL.md in your local Syntic Code skills directory.
  2. 2Keep related files in the same skill folder.
  3. 3Run in a safe environment and validate outputs.