fleet / web
AGENTS.md7 starsChanged 37 days agoMITView on GitHub
Read the repo-root AGENTS.md first: its invariants and the Elcano frontend standard apply here. This file covers only what is specific to web/. A Tier B single-page app: React 19 + TypeScript 7, built by Vite into ../internal/webui/bundle/dist, which the fleet binary embeds with go:embed and serves itself (ADR-0091). There is no Node server in production and no server-side rendering; nothing in web/ runs on the server. - Go owns the server side (internal/webui): the auth gate, sessions, CSRF, OIDC,…
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,439 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
The file
We split this AGENTS.md into the rules it gives an agent
3 rules. About 0 are common, 0 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 3
Read the repo-root AGENTS.md first: its invariants and the Elcano frontend standard apply here.
- Very specific: line 72
Never edit them: scripts/flag-sync.sh check (part of make stack-check) fails on any change.
- Very specific: line 75
Every icon comes from Flag's sprite — use Flag's ids (book, alert-triangle, tools, …).
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
web/ — the fleet web UI (agent notes)
Read the repo-root AGENTS.md first: its invariants and the
Elcano frontend standard apply here. This file covers only what is specific to
web/.
What this is
A Tier B single-page app: React 19 + TypeScript 7, built by Vite into
../internal/webui/bundle/dist, which the fleet binary embeds with
go:embed and serves itself (ADR-0091).
There is no Node server in production and no server-side rendering; nothing
in web/ runs on the server.
- Go owns the server side (
internal/webui): the auth gate, sessions, CSRF, OIDC, CSP and security headers,X-App-Version, theme/brand/manifest, and every/api/*route (called in-process into the chat and orchestrator handlers). A new/api/*route is added there, not here. - Go renders
index.htmlper request: the page<title>and share metadata, and a JSON bootstrap (<script type="application/json" id="fleet-bootstrap">: branding, session email, flags) read bysrc/app/lib/bootstrap.ts. The CSP isscript-src 'self'— never add an inline script;public/theme-init.jsis the one pre-paint script and is a file for that reason. - Routing is in-house:
src/App.tsxis the route table (lazy pages),src/app/lib/navigation.tsxprovidesusePathname/useRouter/navigate,src/app/lib/Link.tsxthe link component. Paths that need a server-side decision (/→/chat,/admin, the/chatmembership gate, a missing/shared/{token}) are redirected by Go before the page is served. Keep URLs stable:/chat,/orchestrator,/settings/...,/admin,/help/...,/shared/{token},/login,/no-access.
Commands (run from web/; verified)
npm ci # lockfile-exact install
npm run lint # oxlint --deny-warnings --report-unused-disable-directives
npm run typecheck # tsc --noEmit — the ONLY type check (vite build strips types)
npm run test # vitest
npm run build # vite build → ../internal/webui/bundle/dist
npm run test:e2e:mocked # Playwright, mocked: builds the bundle + cmd/web-e2e-server, then drives themFrom the repo root: make ci-web (the CI job verbatim, ending with a binary
that must embed the bundle), make ci-e2e-mocked, and make dev — fleet
serve with FLEET_WEB_DEV_SERVER=http://127.0.0.1:5173 so the real Go gate
and API sit in front of the Vite dev server (hot reload; open
http://127.0.0.1:3000).
Runtime dependencies (each justified, per the standard)
| Package | Why |
react, react-dom | the Tier B framework |
react-markdown, remark-gfm | assistant and guide Markdown (GFM tables, task lists) without dangerouslySetInnerHTML |
@tanstack/react-virtual | virtualised long chat transcripts (ChatTranscript.tsx) |
Code highlighting is in-housed (src/app/chat/ui/highlight/, see the root
AGENTS.md). Add a runtime dependency only with a row here and a reason.
UI components and design
- New or replaced base components come from Flag's shadcn/ui registry
(
npx shadcn add <registry-url>/r/<item>.json; the registry URL is in Flag's README). The existing components are fleet's own and are not being migrated wholesale; build one by hand only when the registry lacks it, then upstream it to Flag. - Design rules (tokens, contrast, typefaces):
src/app/DESIGN.md. - Vendored Flag files —
src/app/fonts/(whole dir),public/icons/core-icons.svg,public/logos/fleet-mark.svgandsrc/app/FLAG-LICENSE— are listed with hashes in the rootflag.lock. Never edit them:scripts/flag-sync.sh check(part ofmake stack-check) fails on any change. Update withscripts/flag-sync.sh sync ../flagfrom a clean sibling Flag checkout, then commit the files andflag.locktogether. Every icon comes from Flag's sprite — use Flag's ids (book,alert-triangle,tools, …).src/app/shared/ui/iconHref.tskeeps a few aliases (book-open,warning,wrench) only for names that arrive as client-bundle data;spriteCoverage.test.tsrejects them in fleet's source. A glyph Flag lacks is requested from Flag, not drawn here.
Tests
- vitest beside the code (
*.test.ts(x)), jsdom. Mocks of@/app/lib/navigationstub only the hooks;Linklives in its own module. - Playwright (
e2e/):mocked(deterministic, the Go gateway alone with route-intercepted backends — includes the axe accessibility spec),live(real stack + sandbox, fake LLM),canary,screenshots. Seee2e/README.md. Never runplaywright installin a sandboxed agent session; use the browsers the environment provides.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

