<!-- skill: React Website | version: 1.0.0 | description: Build React + Vite websites — structure, routing, data, build | category: Web -->

## Instructions
- Scaffold with Vite (`npm create vite@latest name -- --template react`), never create-react-app.
- Structure: `src/components/` (UI), `src/pages/` (routes), `src/hooks/`, `src/api.js` (all fetch calls in one place).
- One component per file, props typed informally via JSDoc or PropTypes; keep components under ~150 lines.
- Data fetching: small `useEffect` + state helper per resource; show loading and error states, never a blank screen.
- Routing: `react-router-dom` with a layout route (header/footer) and page routes.
- Style with plain CSS modules or a single stylesheet; avoid adding a UI framework until the design demands it.
- Build with `npm run build`, preview with `npm run preview`, deploy the `dist/` folder statically.

## Examples
- Todo app: `App.jsx` + `components/TodoList.jsx` + `localStorage` persistence in a `useTodos` hook.
- Blog: `pages/Home.jsx`, `pages/Post.jsx`, posts as Markdown files fetched at runtime.

## Workflows
1. `npm create vite`, install router, set up folder structure + `api.js`.
2. Build static shell (layout, routes, placeholder pages) before any logic.
3. Implement one page at a time: UI → state → API → loading/error states.
4. `npm run build` early and often; fix warnings.
5. Deploy `dist/` to any static host (or serve from SARAH's backend static dir).

## Templates
```jsx
// src/api.js — all backend calls in one place
export async function api(path, opts = {}) {
  const res = await fetch(path, {
    headers: { 'Content-Type': 'application/json' },
    ...opts,
    body: opts.body ? JSON.stringify(opts.body) : undefined,
  });
  const data = await res.json().catch(() => ({}));
  if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`);
  return data;
}
```

## Tools
- SARAH `shell_run`: `npm run build` to verify; `npm run dev` for the dev server.
- SARAH preview: folders with `index.html` render in the preview pane after build.

## Advanced
- Performance: `React.memo` for pure list rows, `lazy()` + `Suspense` per route, `useMemo` only for genuinely expensive computes — profile in React DevTools before optimizing.
- Forms: controlled inputs for small forms; `FormData` + uncontrolled for big ones. Validate on submit, show inline errors, disable submit while pending.
- Resilience: error boundaries per route (never one for the whole app), `Error`, empty, and loading states are three separate UIs — design all three.
- Env config: `import.meta.env.VITE_*` for API URLs/keys (public only — secrets stay server-side).
- Testing: Vitest + Testing Library for hooks/utils; Playwright for 2-3 critical user flows.
- Deploy caching: hashed filenames cache forever; `index.html` never cached. 404 fallback to `index.html` for SPA routes on static hosts.

## Documentation
- React: https://react.dev
- Vite: https://vite.dev/guide
- Router: https://reactrouter.com
