Modern Web Front-End Development
Owns modern web front-end work — framework and rendering-mode selection,
React/TypeScript component architecture, Core Web Vitals as build-time budgets,
and front-end debugging — and the enterprise-SPA track (Angular, NgRx,
RxJS, Nx monorepos, OAuth2/OIDC-with-PKCE) carried over intact from
java-frontend, which was promoted to this skill. Companion to java-backend
for the API tier.
Seams (route, do not duplicate):
- Headless data contracts live in
wordpress-developer (§ Headless / Hybrid
Boundary) and woocommerce-developer (§ Headless Storefront) — this skill
builds the consuming app; those own the server-side contract.
- Core Web Vitals measurement lives in
performance — this skill owns the
build-side budgets that keep those metrics in range.
- Trading-application surfaces (order tickets, blotters) live in
trading-dashboard-ux.
- What to build and for whom — audience, journey, information architecture, and
token semantics — is decided upstream in
audience-experience-design; this
skill implements that brief, it does not originate it.
Depth lives in the dedicated skills. This file decides which framework and which rendering
mode, and owns the cross-cutting concerns. For React itself — Server vs Client Components, Actions,
the React Compiler, hooks and render behaviour — use react-developer. For the Next.js
framework — App Router, Cache Components and the use cache model, Route Handlers, Turbopack,
deployment targets — use nextjs-developer. Angular and enterprise SPA patterns stay here.
Two currency notes that invalidate older advice: the React Compiler is stable and makes manual
memoisation mostly unnecessary, and Next.js 16 inverted caching to opt-in ('use cache').
Check the version before applying any remembered guidance on either.
Framework & Rendering-Mode Selection
The first decision is the rendering mode, not the framework. Choose by how
the content behaves, then pick the tool that serves it.
| Mode |
Best for |
SEO |
Update cadence |
Hosting need |
| SPA (Vite + React/Angular) |
Authenticated app shells, dashboards, internal tools |
Weak (client-rendered) |
Live/interactive |
Static host + API |
| SSG (Next static export, Astro) |
Marketing, docs, blogs, mostly-static content |
Strong |
Rebuild on change |
Static host / CDN |
| ISR (Next incremental) |
Large catalogs, content that changes but not per-request |
Strong |
Background revalidate |
Node runtime |
| SSR (Next request-time) |
Per-request personalization, auth-gated pages, fresh data |
Strong |
Per request |
Node runtime |
- Static-first is the DEFAULT. Ship SSG/SPA unless a concrete requirement
(per-request personalization, auth-gated first paint, real-time freshness)
demands a server. SSR trades a CDN edge hit for a server round-trip on every
request — pay it only when the content genuinely varies per request.
- Shared-hosting plan gate (verify before recommending SSR). On Hostinger,
the managed Node.js runtime (needed for SSR/ISR/API routes) exists on
Business Web Hosting and the Cloud tiers (managed Node launched 2025-11;
runtimes 18/20/22/24.x). The entry Web Single / Web Premium tiers have
no managed Node runtime — Next.js must be statically exported there
and SSR/server-ISR/API routes will not run. Before recommending SSR on
shared hosting, confirm the plan tier provides a Node runtime AND run an SSR
load test — a server-rendered app on a plan that cannot serve it fails in
production, not at build time. (Older "Node is VPS-only on Hostinger"
guidance predates the 2025-11 launch and is stale.)
Next.js Working Knowledge (App Router)
Current stable is Next.js 16.x (major 16 stable 2025-10); the App Router
is the default for new projects and React Server Components are the default
component model inside it.
- Server-first is the primary performance lever. App-Router pages and
layouts are Server Components by default — they render on the server and do
not ship or hydrate client JS.
"use client" marks a Client Component
boundary; hydration cost applies only to that client subset. Maximize the
server portion; push "use client" down to the leaves that truly need
interactivity — the client/server split IS the main performance decision,
not a detail.
- Data fetching & revalidation. Fetch directly in async Server Components
(or via an ORM). In Next 16,
fetch is not cached by default — opt in
with explicit cache options or Cache Components / "use cache".
revalidatePath() invalidates a route's data; revalidateTag(tag, "max")
marks tagged data stale with SWR semantics (the one-argument revalidateTag
form is deprecated).
- Images & fonts.
next/image (built-in optimization) and next/font
(self-hosted, layout-shift-safe) remain the standard. In Next 16 the Image
priority prop is deprecated in favor of preload.
- Hydration failure modes (the usual production culprits): invalid HTML
nesting; branching on
window / typeof window; touching browser APIs
during render; nondeterministic output (Date.now(), Math.random(),
locale/timezone formatting); server-vs-client data-snapshot drift; CSS-in-JS
misconfiguration; browser extensions or iOS auto-linking mutating the DOM;
and CDN/Edge HTML rewriting. A hydration mismatch means the server HTML and
the first client render disagreed — the fix is to make the first client
render deterministic and identical to the server's.
Never assume a headless toolkit is App-Router-current — verify per tool
(see Headless Consumption below).
Core Web Vitals as Build-Time Budgets
Core Web Vitals are LCP, INP, and CLS. Measurement of the shipped site lives
in performance (route there for profiling / CrUX / Lighthouse). This section
owns what the build can actually control — enforce these as CI gates:
- Bundle-size budget per route — cap the first-load JS per route (e.g. fail
CI when a route's compressed first-load JS exceeds its budget); route-based
code splitting and lazy boundaries keep it there.
- Script-execution / TBT budget — Total Blocking Time is the lab proxy
for interaction responsiveness. Budget main-thread script work; defer or
offload heavy work (web workers,
requestIdleCallback).
- Long Animation Frames (LoAF) mitigation — use LoAF attribution to find
the blocking/rendering work behind slow interactions and break it up; LoAF
works in both lab/CI and field.
- Image budget — enforce modern formats (AVIF/WebP), correct
srcset,
explicit dimensions (prevents CLS), and lazy-loading below the fold.
- Third-party script policy — every third-party tag is a TBT and privacy
cost; load behind consent, defer, or facade-load (e.g. lite embeds).
Lab gates (build-time): LCP ≤ 2.5 s and CLS ≤ 0.1 are measurable in the lab
and belong in CI. INP (≤ 200 ms good) is a FIELD metric — it depends on
real user interactions over the page lifetime and cannot be measured at build
time; track it post-release via RUM / CrUX, and use TBT as the lab proxy
during the build. Do not claim a build "passes INP" — a build can only reduce
the risk of poor INP.
Debugging Modern Front-Ends
Front-end defects are largely invisible without the right traces — treat
debugging as a first-class workflow, not an afterthought.
- Source maps in production — ship hidden source maps (
sourcemap: 'hidden' — emitted but not referenced by a //# sourceMappingURL comment)
so stack traces symbolicate in your error reporter without exposing maps to
the public. Upload them to the error-reporting service at deploy time.
- Browser devtools traces — use the Performance panel to see hydration
cost, long tasks, and layout shifts on a real interaction; the Network panel
(with throttling) to catch waterfalls, oversized payloads, and blocking
requests. Record a trace against the actual slow interaction, not a cold load.
- Framework devtools — React DevTools (Profiler for re-render storms and
wasted renders) and the Next.js overlay / build output (which routes are
server vs client, bundle composition).
- Error boundaries + reporting — wrap client subtrees in error boundaries
with a graceful fallback, and report caught errors (with symbolicated stacks)
to a monitoring service. A blank screen with no report is the worst outcome.
Headless Consumption
A Next/Vite front-end consuming WordPress/WooCommerce owns the UI and
rendering, never the server-side contract:
- The data contract lives server-side. How WordPress exposes content (REST
vs WPGraphQL, auth for previews, cache-invalidation webhooks) is owned by
wordpress-developer (§ Headless / Hybrid Boundary). What WooCommerce keeps
authoritative (cart/session, checkout, price/stock, payment/tax/inventory) is
owned by woocommerce-developer (§ Headless Storefront). Build against those
boundaries; do not re-implement them here.
- WooCommerce cart is same-origin by default. Reverse-proxy/rewrite the
storefront's Store-API calls to the WordPress origin so session cookies stay
first-party — a cross-domain decoupled front-end breaks cart persistence
under CORS credential rules and Safari ITP. (Full rationale in
woocommerce-developer.)
- Verify toolkit App-Router status per tool. WPGraphQL can be queried
directly from Server Components / route handlers (no special adapter).
Faust.js's App Router package (
@faustwp/experimental-app-router) was
deprecated in 2025 — its supported path is the Pages Router; do not adopt
it for a new App-Router build. For a new App Router project, fetch REST or
WPGraphQL directly rather than adding a data-client framework you must then
keep current.
Next.js Server-Side Surface — and where a Node service begins
Next ships server code, and this skill owns the part co-deployed with one
Next app — but only that part. The boundary matters because the headless-WP
glue above (a secret-holding preview/auth endpoint, a save_post →
revalidateTag webhook receiver) IS Next server code with no other owner, while
a standalone backend service is explicitly out of scope (no dedicated skill —
route it away).
modern-frontend OWNS (co-deployed with the app):
- Route Handlers (
app/api/*/route.ts) — app-local BFF, webhook/revalidation
receivers, preview-auth endpoints holding server-side secrets (never in client
JS).
- Server Actions — UI-originated mutations; NOT public APIs or third-party
webhook receivers.
- Server-Component data fetching + revalidation (
revalidateTag/revalidatePath).
middleware.ts — auth gating, redirects, rewrites, cookies/headers.
A Node backend SERVICE begins (route away — no dedicated skill; use
profiling.md + database.md) at ANY of:
- independent deployment, or a versioned API consumed by clients other than this
app;
- separate data/domain ownership, or independent scaling/SLOs;
- durable queues, workers, schedulers, or cron independent of the HTTP request
lifecycle;
- long-running processing or persistent connections (WebSocket/streaming beyond
RSC).
If a task drifts across that line, it is no longer a modern-frontend task —
do not grow this section to cover it (Node/TypeScript MCP servers go to
mcp-server-creator).
Reference Files
Detailed code examples, patterns, and configuration for each topic area are in
the reference files below. Read the relevant file when working on that area.
The Angular/NgRx/OIDC material is the enterprise-SPA track; the React /
Vite / testing material serves both modern and enterprise builds.
| Topic |
File |
Covers |
| Angular 17+ patterns (enterprise-SPA track) |
angular-patterns.md |
Standalone components, services with inject(), routing (lazy loading, guards, resolvers), interceptors (auth token, error handling), change detection (OnPush, signals) |
| React 18+/19 patterns |
react-patterns.md |
Function components with hooks, custom hooks (useApi, useDebounce, useLocalStorage), error boundaries, React Router 6 with loaders |
| State management |
state-management.md |
NgRx (store, effects, selectors) for Angular, Redux Toolkit for React, guidance on global vs local vs server-cache state |
| API, auth, and forms |
api-auth-forms.md |
HttpClient typed responses, Axios with TanStack Query, GraphQL/Apollo Client, OpenAPI code generation, OAuth2 PKCE flows (Angular and React), role-based UI rendering, Angular reactive forms, React Hook Form with Zod validation |
| Components and styling |
component-styling.md |
Smart/container vs presentational components, compound component pattern, Storybook documentation, Tailwind CSS configuration, responsive Grid/Flexbox layouts, CSS custom properties theming |
| Testing, build, and a11y |
testing-build-a11y.md |
Jest + Testing Library (React), Jasmine + Angular testing, Playwright E2E, Mock Service Worker (MSW), Vite 8 (Rolldown) build config, Nx monorepo, GitHub Actions CI/CD, environment variables, WCAG 2.1 |
Decision Guide
Choosing a rendering mode: see Framework & Rendering-Mode Selection above —
decide the mode from content behavior first, static-first by default.
Choosing a framework:
- Next.js (App Router, RSC) — content sites, marketing, commerce
storefronts, and anything needing SSR/SSG/ISR and strong SEO. Server-first by
default.
- Vite + React — authenticated SPA shells, dashboards, and internal tools
where SEO is irrelevant and you want the fastest dev loop and a static deploy.
- Angular — large enterprise apps wanting opinionated structure (DI, RxJS,
NgRx); the enterprise-SPA track. Best for admin portals and data-heavy SPAs.
Choosing state management:
- Local state first (useState / signals) — component-scoped data.
- Server-cache libraries (TanStack Query, RTK Query) — for server state
(caching, pagination, optimistic updates). Most "global state" is really
server state; reach for a cache before a store.
- NgRx / Redux Toolkit — only for genuinely shared client state with complex
flows or time-travel debugging needs.
Choosing API integration:
- REST with HttpClient/Axios — default for most APIs.
- TanStack Query — caching, pagination, optimistic updates.
- GraphQL/Apollo — when the backend exposes a GraphQL schema (e.g. WPGraphQL)
and field-precise queries pay off.
Anti-Patterns
| Anti-Pattern |
Why It Fails |
Correct Approach |
| Reaching for SSR by default |
Pays a server round-trip on every request and needs a Node runtime the host may not have |
Static-first (SSG/SPA); adopt SSR only for per-request personalization, and verify the hosting plan first |
Marking everything "use client" |
Ships and hydrates JS that could have stayed on the server; defeats RSC |
Keep components server by default; push "use client" to the interactive leaves |
| Treating INP as a build-time gate |
INP is a field metric; a green Lighthouse run does not mean good INP in the wild |
Gate LCP/CLS + TBT in the lab; track INP via RUM/CrUX post-release |
| Fetching data in every component instead of a server-cache |
Duplicate requests, inconsistent data, excessive re-renders |
Use TanStack Query (React) or NgRx/signals (Angular) for server state |
| Not typing API responses in TypeScript |
Runtime errors when the API shape changes; bugs found in production |
Define types for all responses; validate at the boundary with zod/io-ts |
| Importing entire UI libraries for a few components |
Bundle balloons; unused code shipped to users |
Tree-shakeable imports; analyze the bundle; enforce a per-route budget |
| No error boundaries or reporting |
One failed call white-screens the app with no trace |
Error boundaries with fallback UI + symbolicated error reporting |
Related Skills
| Domain |
Skill |
| Headless WordPress data boundary |
wordpress-developer (§ Headless / Hybrid Boundary) |
| Headless WooCommerce storefront boundary |
woocommerce-developer (§ Headless Storefront) |
| Core Web Vitals measurement / profiling |
performance |
| Trading-application UI surfaces |
trading-dashboard-ux |
| Experience / UX design (pre-build brief) |
audience-experience-design |
| An LLM feature in the app (retrieval, agents, API cost) |
rag-architecture, agentic-architecture, llm-api-optimization |
| Java backend (Spring Boot, REST APIs) |
java-backend, java-spring-boot |
| SaaS architecture / implementation |
saas-architecture, saas-developer |
| Docker containers and CI/CD |
docker-admin, docker-cicd |
| Auth and security patterns |
python-auth-security |
| SEO and content optimization |
seo-structure-architect, seo-meta-optimizer |
1---2name: modern-frontend3description: Use when building or debugging modern web front-ends — framework and rendering-mode selection (Vite SPA, Next.js SSR/SSG/ISR, hydration strategies), React/TypeScript component architecture, enterprise SPA patterns (Angular, NgRx, OIDC/PKCE, Nx monorepos), state and server-cache management, responsive layouts, Core Web Vitals as build-time budgets, source-map and browser-devtools debugging, bundle analysis and code splitting, testing (Playwright, MSW, axe/WCAG), and deployment-mode selection (static-first default, SSR only with platform validation). Trigger on - Vite, Next.js, SSR, SSG, hydration, React app, frontend build, web app performance budget, bundle size, frontend debugging, headless frontend. Headless WordPress/WooCommerce data boundaries live in wordpress-developer / woocommerce-developer; CWV measurement lives in performance; trading dashboards live in trading-dashboard-ux; UI/UX design decisions live in audience-experience-design.4---56# Modern Web Front-End Development78Owns modern web front-end work — framework and rendering-mode selection,9React/TypeScript component architecture, Core Web Vitals as build-time budgets,10and front-end debugging — **and** the **enterprise-SPA track** (Angular, NgRx,11RxJS, Nx monorepos, OAuth2/OIDC-with-PKCE) carried over intact from12`java-frontend`, which was promoted to this skill. Companion to `java-backend`13for the API tier.1415**Seams (route, do not duplicate):**16- Headless data contracts live in `wordpress-developer` (§ Headless / Hybrid17 Boundary) and `woocommerce-developer` (§ Headless Storefront) — this skill18 builds the *consuming* app; those own the server-side contract.19- Core Web Vitals *measurement* lives in `performance` — this skill owns the20 *build-side budgets* that keep those metrics in range.21- Trading-application surfaces (order tickets, blotters) live in22 `trading-dashboard-ux`.23- What to build and for whom — audience, journey, information architecture, and24 token *semantics* — is decided upstream in `audience-experience-design`; this25 skill implements that brief, it does not originate it.2627<HARD-RULE>28Never store JWT tokens in localStorage — use httpOnly cookies or in-memory storage to prevent XSS token theft. localStorage is readable by any script on the page, including injected XSS payloads. A single XSS vulnerability means every stored token is exfiltrated.29</HARD-RULE>3031<HARD-RULE>32Always implement loading and error states for every async operation — unhandled states cause blank screens and confused users. Every fetch, mutation, and navigation that touches the network must have explicit pending, success, and error UI paths.33</HARD-RULE>3435<HARD-RULE>36Never subscribe to observables without unsubscribing (Angular) — memory leaks accumulate and crash the browser tab in long-running SPAs. Use takeUntilDestroyed(), async pipe, or DestroyRef to guarantee cleanup. In React, always return cleanup functions from useEffect.37</HARD-RULE>3839<HARD-RULE>40Always use semantic HTML elements before adding ARIA attributes — div with role="button" is never better than a real button element. Native elements provide keyboard handling, focus management, and screen reader announcements for free. ARIA is a repair tool, not a replacement.41</HARD-RULE>4243---4445> **Depth lives in the dedicated skills.** This file decides *which* framework and *which* rendering46> mode, and owns the cross-cutting concerns. For React itself — Server vs Client Components, Actions,47> the React Compiler, hooks and render behaviour — use **`react-developer`**. For the Next.js48> framework — App Router, Cache Components and the `use cache` model, Route Handlers, Turbopack,49> deployment targets — use **`nextjs-developer`**. Angular and enterprise SPA patterns stay here.50>51> **Two currency notes that invalidate older advice:** the React Compiler is stable and makes manual52> memoisation mostly unnecessary, and Next.js 16 **inverted caching to opt-in** (`'use cache'`).53> Check the version before applying any remembered guidance on either.5455## Framework & Rendering-Mode Selection5657The first decision is the **rendering mode**, not the framework. Choose by how58the content behaves, then pick the tool that serves it.5960| Mode | Best for | SEO | Update cadence | Hosting need |61|---|---|---|---|---|62| **SPA** (Vite + React/Angular) | Authenticated app shells, dashboards, internal tools | Weak (client-rendered) | Live/interactive | Static host + API |63| **SSG** (Next static export, Astro) | Marketing, docs, blogs, mostly-static content | Strong | Rebuild on change | Static host / CDN |64| **ISR** (Next incremental) | Large catalogs, content that changes but not per-request | Strong | Background revalidate | Node runtime |65| **SSR** (Next request-time) | Per-request personalization, auth-gated pages, fresh data | Strong | Per request | Node runtime |6667- **Static-first is the DEFAULT.** Ship SSG/SPA unless a concrete requirement68 (per-request personalization, auth-gated first paint, real-time freshness)69 demands a server. SSR trades a CDN edge hit for a server round-trip on every70 request — pay it only when the content genuinely varies per request.71- **Shared-hosting plan gate (verify before recommending SSR).** On Hostinger,72 the managed Node.js runtime (needed for SSR/ISR/API routes) exists on73 **Business Web Hosting and the Cloud tiers** (managed Node launched 2025-11;74 runtimes 18/20/22/24.x). The entry **Web Single / Web Premium** tiers have75 **no managed Node runtime** — Next.js must be **statically exported** there76 and SSR/server-ISR/API routes will not run. **Before recommending SSR on77 shared hosting, confirm the plan tier provides a Node runtime AND run an SSR78 load test** — a server-rendered app on a plan that cannot serve it fails in79 production, not at build time. (Older "Node is VPS-only on Hostinger"80 guidance predates the 2025-11 launch and is stale.)8182## Next.js Working Knowledge (App Router)8384Current stable is **Next.js 16.x** (major 16 stable 2025-10); the **App Router85is the default** for new projects and **React Server Components are the default86component model** inside it.8788- **Server-first is the primary performance lever.** App-Router pages and89 layouts are Server Components by default — they render on the server and **do90 not ship or hydrate** client JS. `"use client"` marks a Client Component91 boundary; hydration cost applies only to that client subset. **Maximize the92 server portion; push `"use client"` down to the leaves that truly need93 interactivity** — the client/server split IS the main performance decision,94 not a detail.95- **Data fetching & revalidation.** Fetch directly in async Server Components96 (or via an ORM). In Next 16, `fetch` is **not cached by default** — opt in97 with explicit cache options or Cache Components / `"use cache"`.98 `revalidatePath()` invalidates a route's data; `revalidateTag(tag, "max")`99 marks tagged data stale with SWR semantics (the one-argument `revalidateTag`100 form is deprecated).101- **Images & fonts.** `next/image` (built-in optimization) and `next/font`102 (self-hosted, layout-shift-safe) remain the standard. In Next 16 the Image103 `priority` prop is deprecated in favor of `preload`.104- **Hydration failure modes** (the usual production culprits): invalid HTML105 nesting; branching on `window` / `typeof window`; touching browser APIs106 during render; nondeterministic output (`Date.now()`, `Math.random()`,107 locale/timezone formatting); server-vs-client data-snapshot drift; CSS-in-JS108 misconfiguration; browser extensions or iOS auto-linking mutating the DOM;109 and CDN/Edge HTML rewriting. A hydration mismatch means the server HTML and110 the first client render disagreed — the fix is to make the first client111 render deterministic and identical to the server's.112113**Never assume a headless toolkit is App-Router-current** — verify per tool114(see Headless Consumption below).115116## Core Web Vitals as Build-Time Budgets117118Core Web Vitals are LCP, INP, and CLS. *Measurement* of the shipped site lives119in `performance` (route there for profiling / CrUX / Lighthouse). This section120owns what the **build can actually control** — enforce these as CI gates:121122- **Bundle-size budget per route** — cap the first-load JS per route (e.g. fail123 CI when a route's compressed first-load JS exceeds its budget); route-based124 code splitting and lazy boundaries keep it there.125- **Script-execution / TBT budget** — Total Blocking Time is the **lab proxy**126 for interaction responsiveness. Budget main-thread script work; defer or127 offload heavy work (web workers, `requestIdleCallback`).128- **Long Animation Frames (LoAF) mitigation** — use LoAF attribution to find129 the blocking/rendering work behind slow interactions and break it up; LoAF130 works in both lab/CI and field.131- **Image budget** — enforce modern formats (AVIF/WebP), correct `srcset`,132 explicit dimensions (prevents CLS), and lazy-loading below the fold.133- **Third-party script policy** — every third-party tag is a TBT and privacy134 cost; load behind consent, defer, or facade-load (e.g. lite embeds).135136**Lab gates (build-time):** LCP ≤ 2.5 s and CLS ≤ 0.1 are measurable in the lab137and belong in CI. **INP (≤ 200 ms good) is a FIELD metric** — it depends on138real user interactions over the page lifetime and **cannot be measured at build139time**; track it post-release via RUM / CrUX, and use **TBT as the lab proxy**140during the build. Do not claim a build "passes INP" — a build can only reduce141the *risk* of poor INP.142143## Debugging Modern Front-Ends144145Front-end defects are largely invisible without the right traces — treat146debugging as a first-class workflow, not an afterthought.147148- **Source maps in production** — ship **hidden** source maps (`sourcemap:149 'hidden'` — emitted but not referenced by a `//# sourceMappingURL` comment)150 so stack traces symbolicate in your error reporter without exposing maps to151 the public. Upload them to the error-reporting service at deploy time.152- **Browser devtools traces** — use the Performance panel to see hydration153 cost, long tasks, and layout shifts on a real interaction; the Network panel154 (with throttling) to catch waterfalls, oversized payloads, and blocking155 requests. Record a trace against the actual slow interaction, not a cold load.156- **Framework devtools** — React DevTools (Profiler for re-render storms and157 wasted renders) and the Next.js overlay / build output (which routes are158 server vs client, bundle composition).159- **Error boundaries + reporting** — wrap client subtrees in error boundaries160 with a graceful fallback, and report caught errors (with symbolicated stacks)161 to a monitoring service. A blank screen with no report is the worst outcome.162163## Headless Consumption164165A Next/Vite front-end consuming WordPress/WooCommerce owns the **UI and166rendering**, never the server-side contract:167168- **The data contract lives server-side.** How WordPress exposes content (REST169 vs WPGraphQL, auth for previews, cache-invalidation webhooks) is owned by170 `wordpress-developer` (§ Headless / Hybrid Boundary). What WooCommerce keeps171 authoritative (cart/session, checkout, price/stock, payment/tax/inventory) is172 owned by `woocommerce-developer` (§ Headless Storefront). Build against those173 boundaries; do not re-implement them here.174- **WooCommerce cart is same-origin by default.** Reverse-proxy/rewrite the175 storefront's Store-API calls to the WordPress origin so session cookies stay176 first-party — a cross-domain decoupled front-end breaks cart persistence177 under CORS credential rules and Safari ITP. (Full rationale in178 `woocommerce-developer`.)179- **Verify toolkit App-Router status per tool.** WPGraphQL can be queried180 directly from Server Components / route handlers (no special adapter).181 Faust.js's App Router package (`@faustwp/experimental-app-router`) was182 **deprecated in 2025** — its supported path is the Pages Router; do not adopt183 it for a new App-Router build. For a new App Router project, fetch REST or184 WPGraphQL directly rather than adding a data-client framework you must then185 keep current.186187## Next.js Server-Side Surface — and where a Node service begins188189Next ships server code, and this skill owns the part **co-deployed with one190Next app** — but only that part. The boundary matters because the headless-WP191glue above (a secret-holding preview/auth endpoint, a `save_post` →192`revalidateTag` webhook receiver) IS Next server code with no other owner, while193a standalone backend service is explicitly out of scope (no dedicated skill —194route it away).195196**modern-frontend OWNS (co-deployed with the app):**197- **Route Handlers** (`app/api/*/route.ts`) — app-local BFF, webhook/revalidation198 receivers, preview-auth endpoints holding server-side secrets (never in client199 JS).200- **Server Actions** — UI-originated mutations; NOT public APIs or third-party201 webhook receivers.202- **Server-Component data fetching + revalidation** (`revalidateTag`/`revalidatePath`).203- **`middleware.ts`** — auth gating, redirects, rewrites, cookies/headers.204205**A Node backend SERVICE begins (route away — no dedicated skill; use206profiling.md + database.md) at ANY of:**207- independent deployment, or a versioned API consumed by clients other than this208 app;209- separate data/domain ownership, or independent scaling/SLOs;210- durable queues, workers, schedulers, or cron independent of the HTTP request211 lifecycle;212- long-running processing or persistent connections (WebSocket/streaming beyond213 RSC).214215If a task drifts across that line, it is no longer a modern-frontend task —216do not grow this section to cover it (Node/TypeScript MCP servers go to217`mcp-server-creator`).218219---220221## Reference Files222223Detailed code examples, patterns, and configuration for each topic area are in224the reference files below. Read the relevant file when working on that area.225The Angular/NgRx/OIDC material is the **enterprise-SPA track**; the React /226Vite / testing material serves both modern and enterprise builds.227228| Topic | File | Covers |229|---|---|---|230| Angular 17+ patterns (enterprise-SPA track) | [angular-patterns.md](angular-patterns.md) | Standalone components, services with inject(), routing (lazy loading, guards, resolvers), interceptors (auth token, error handling), change detection (OnPush, signals) |231| React 18+/19 patterns | [react-patterns.md](react-patterns.md) | Function components with hooks, custom hooks (useApi, useDebounce, useLocalStorage), error boundaries, React Router 6 with loaders |232| State management | [state-management.md](state-management.md) | NgRx (store, effects, selectors) for Angular, Redux Toolkit for React, guidance on global vs local vs server-cache state |233| API, auth, and forms | [api-auth-forms.md](api-auth-forms.md) | HttpClient typed responses, Axios with TanStack Query, GraphQL/Apollo Client, OpenAPI code generation, OAuth2 PKCE flows (Angular and React), role-based UI rendering, Angular reactive forms, React Hook Form with Zod validation |234| Components and styling | [component-styling.md](component-styling.md) | Smart/container vs presentational components, compound component pattern, Storybook documentation, Tailwind CSS configuration, responsive Grid/Flexbox layouts, CSS custom properties theming |235| Testing, build, and a11y | [testing-build-a11y.md](testing-build-a11y.md) | Jest + Testing Library (React), Jasmine + Angular testing, Playwright E2E, Mock Service Worker (MSW), Vite 8 (Rolldown) build config, Nx monorepo, GitHub Actions CI/CD, environment variables, WCAG 2.1 |236237---238239## Decision Guide240241**Choosing a rendering mode:** see Framework & Rendering-Mode Selection above —242decide the mode from content behavior first, static-first by default.243244**Choosing a framework:**245- **Next.js (App Router, RSC)** — content sites, marketing, commerce246 storefronts, and anything needing SSR/SSG/ISR and strong SEO. Server-first by247 default.248- **Vite + React** — authenticated SPA shells, dashboards, and internal tools249 where SEO is irrelevant and you want the fastest dev loop and a static deploy.250- **Angular** — large enterprise apps wanting opinionated structure (DI, RxJS,251 NgRx); the enterprise-SPA track. Best for admin portals and data-heavy SPAs.252253**Choosing state management:**254- Local state first (useState / signals) — component-scoped data.255- Server-cache libraries (TanStack Query, RTK Query) — for *server* state256 (caching, pagination, optimistic updates). Most "global state" is really257 server state; reach for a cache before a store.258- NgRx / Redux Toolkit — only for genuinely shared client state with complex259 flows or time-travel debugging needs.260261**Choosing API integration:**262- REST with HttpClient/Axios — default for most APIs.263- TanStack Query — caching, pagination, optimistic updates.264- GraphQL/Apollo — when the backend exposes a GraphQL schema (e.g. WPGraphQL)265 and field-precise queries pay off.266267---268269## Anti-Patterns270271| Anti-Pattern | Why It Fails | Correct Approach |272|---|---|---|273| Reaching for SSR by default | Pays a server round-trip on every request and needs a Node runtime the host may not have | Static-first (SSG/SPA); adopt SSR only for per-request personalization, and verify the hosting plan first |274| Marking everything `"use client"` | Ships and hydrates JS that could have stayed on the server; defeats RSC | Keep components server by default; push `"use client"` to the interactive leaves |275| Treating INP as a build-time gate | INP is a field metric; a green Lighthouse run does not mean good INP in the wild | Gate LCP/CLS + TBT in the lab; track INP via RUM/CrUX post-release |276| Fetching data in every component instead of a server-cache | Duplicate requests, inconsistent data, excessive re-renders | Use TanStack Query (React) or NgRx/signals (Angular) for server state |277| Not typing API responses in TypeScript | Runtime errors when the API shape changes; bugs found in production | Define types for all responses; validate at the boundary with zod/io-ts |278| Importing entire UI libraries for a few components | Bundle balloons; unused code shipped to users | Tree-shakeable imports; analyze the bundle; enforce a per-route budget |279| No error boundaries or reporting | One failed call white-screens the app with no trace | Error boundaries with fallback UI + symbolicated error reporting |280281---282283## Related Skills284285| Domain | Skill |286|---|---|287| Headless WordPress data boundary | `wordpress-developer` (§ Headless / Hybrid Boundary) |288| Headless WooCommerce storefront boundary | `woocommerce-developer` (§ Headless Storefront) |289| Core Web Vitals measurement / profiling | `performance` |290| Trading-application UI surfaces | `trading-dashboard-ux` |291| Experience / UX design (pre-build brief) | `audience-experience-design` |292| An LLM feature in the app (retrieval, agents, API cost) | `rag-architecture`, `agentic-architecture`, `llm-api-optimization` |293| Java backend (Spring Boot, REST APIs) | `java-backend`, `java-spring-boot` |294| SaaS architecture / implementation | `saas-architecture`, `saas-developer` |295| Docker containers and CI/CD | `docker-admin`, `docker-cicd` |296| Auth and security patterns | `python-auth-security` |297| SEO and content optimization | `seo-structure-architect`, `seo-meta-optimizer` |