# Stackship Circuit template A React 19 + Vite starting point for apps that Circuit builds and Stackship runs. Routing, light/dark theming, a typed API layer and the Stackship components are already wired, so an agent (or you) starts with product work instead of plumbing. It follows the same contract as Circuit's frontend template — dev server on `:5173`, mock API at `/api`, `.eventsourced/session.yaml` for the live preview — with the Stackship design system on top. ## Stack - **React 19** with the React Compiler enabled - **Vite 8** dev server, with a mock API served at `/api` - **Tailwind v4** — Stackship tokens defined as CSS variables in `src/index.css` - **Radix UI** (unified `radix-ui` package) for accessible primitives - **SWR** for data fetching, **react-router** for routing, **lucide-react** for icons - **Poppins + JetBrains Mono** bundled through Fontsource — no CDN calls, works air-gapped ## Structure ``` src/ api/ # typed API layer — one SWR hook per endpoint types.ts # response types client.ts # fetch wrapper (all network calls go through here) hooks.ts # useStats(), useResources(), … consumed by pages components/ ui/ # Stackship primitives: Button, Card, Badge, ServiceIcon, ProgressBar, Skeleton gallery/ # component-gallery demos, one primitive per file dashboard/ # dashboard sections (StatGrid, ResourcesTable, SentinelCard…) home/ # home page sections (Hero, EnvironmentCard, LoopSection, StackGrid) Layout.tsx # header + footer, wraps every route Logo.tsx # Stackship wordmark, light/dark aware ThemeProvider.tsx / ThemeToggle.tsx pages/ # one file per route, registered in App.tsx mock/server.mjs # zero-dependency mock API (started by the dev server) public/ # favicon and Stackship logos ``` ## Conventions (follow these when editing — applies to AI agents too) - **Colours and fonts come from tokens only.** Use Tailwind classes like `bg-card`, `text-muted-foreground`, `border-border`, `bg-primary`. Never hardcode hex values; both modes read from the variables at the top of `src/index.css`. The one exception is the always-dark hero surface, which uses `bg-night` and white text in both themes. - **Brand utilities:** `text-gradient` (blue→green headline words), `bg-brand` (gradient CTAs and meters), `glass`, `glow-primary` / `glow-accent` (blurred backdrops on dark sections). Use the gradient sparingly — one highlight per screen reads as deliberate. - **Resource types** get their accent from `ServiceIcon` (`app`, `database`, `storage`, …). Don't invent new hues for them. - **Sentinel** (the AI/ops assistant) uses the rose `sentinel` colour and nothing else does. - **New route** = one file in `src/pages/` + one line in `src/App.tsx` (+ nav entry in `Layout.tsx`). - **New data** = type in `src/api/types.ts`, route in `mock/server.mjs`, hook in `src/api/hooks.ts`. Pages never call `fetch` directly. - **Loading** with ``, **errors** inline with `` and a retry — see `src/pages/Dashboard.tsx`. - **Pages are compositions.** A page owns layout and data fetching, then renders sections from `src/components//`. If a page file grows past ~100 lines, extract sections. - **Copy:** sentence case for headings and buttons, no exclamation marks, no emoji. Calm and declarative — "You control where data lives", not "Unleash your data". - Radix provides behaviour, Tailwind provides looks. Copy styles from the gallery (`src/pages/Components.tsx`) rather than inventing new patterns. ## Commands ```bash npm run dev # app on :5173, mock API proxied at /api npm run build # type-check + production build npm run lint # oxlint ``` ## Theming Light and dark are two sets of CSS variables in `src/index.css` (`:root` and `.dark`). The header toggle offers light, dark and system, and persists to `localStorage`. To retheme, change the variable values — no component edits needed. ## Swapping in a real API Point `server.proxy['/api']` in `vite.config.ts` at your backend and remove the `mockApi()` plugin. Endpoint shapes stay in `src/api/types.ts`.