KiroCrewWebsite
August 23, 2026 · View on GitHub
This file is a ROUTER, not a manual. It carries only the rules whose violation
causes damage before a pointer could be read. Everything else is a link you MUST
open before touching that area. The backend router is ../AGENTS.md.
React + TypeScript + Vite SPA for the Kiro Crew dashboard. Built assets go to
dist/ and are staged into ../src/kiro_crew/static/dist/ so the gateway serves
them.
Read before you touch
| If you are touching… | Read first |
|---|---|
| layout of a page, panels, headers | page-layout |
| themes, colors, CSS vars, stable class hooks | theming-contract |
| shared components, a11y, URL sanitization, data fetching | frontend-conventions |
| any user-facing string, date, number, or sort order | i18n-catalog + i18n gates |
src/extensions.ts, edition composition, registries | extension-seams |
| tests (vitest, MSW, Playwright, Electron), or a test that fails only in CI | testing |
| the Electron desktop shell | electron/README.md |
| anything backend, or a whole-system question | ../AGENTS.md |
Everything under website/docs/ is indexed by its README.
Stack
React 18, Redux Toolkit, React Query (@tanstack/react-query), React Router v7,
Framer Motion, Tailwind CSS 3, Lucide React, DOMPurify, highlight.js, Monaco,
TypeScript, Vite 5. Prefer the library already here over a new dependency.
Build and test: a gotcha that produces a silent false green
- The
localStoragetest polyfill must stay onStorage.prototype. Assigning it elsewhere makes the mock silently miss.
npm run test runs the website vitest suite AND the Electron node:test suite, and
a pretest jscpd duplication check runs first, so npm test can fail on
copy-paste before a single test executes. Commands and layers:
testing.
This is a public OSS fork: don't reintroduce internal couplings
- Build/infra: no
npm-pretty-much, Brazil, AIM, or CodeArtifact registries. The public build is plain npm + Vite;.npmrcdeliberately does not pin a registry -- the system-configured registry applies (seedocs/build/desktop-app.md). - Identity/telemetry: no live Cognito pools or RUM app ids (
src/rum.tsis an inert no-op stub, keep it inert), noaws-rum-web. - Removed product surfaces: internal feature-app pages, tabs, API-client methods, and the credential-TTL card were deleted with their backend. A downstream edition re-adds them additively through the extension seams, never by editing core.
- The Channels app is hidden from the App Store and the Board app is removed. An upstream sync must not restore either.
AUTOSDE.yamlin this directory is live and authoritative. The frontend review rules it declares are read by theclaude-review,codex-review,code-review,fork-gpt-review, andfork-opus-reviewworkflows, and ablocking: truerule there outranks a reviewer's own prompt. Read it before changing frontend code; never treat it as historical.
Browser support
Chrome, Firefox, Safari, Edge. Use standard Web APIs only; guard browser-specific
ones (e.g. typeof Notification !== 'undefined').
Rules that must not wait for a pointer
- Settings primitives: pass
configKeyon every newSettingsToggle/SettingsFieldthat writes a config path. It flows into the generated settings registry and makes<SettingRef configKey="...">chips deep-link to the control; omit it and the chip silently degrades to a CLI popover even though a toggle exists. Backend drift guards catch bad keys, not missing ones — this rule is the only gate for the missing case. - Icons:
lucide-reactonly, withclassName="lucide-inline". Never an emoji, never a hand-rolled SVG, neversize={N}. Enforced byAUTOSDE.yaml(use-lucide-icons,no-emoji-as-icons). - Security: every
dangerouslySetInnerHTMLgoes through DOMPurify viamd()/sanitize()/esc()insrc/api/helpers.ts. A bypass is an XSS bug, so there is no acceptable pointer for this one. - Never format a date, number, or sort order without naming a locale. Route
through the
src/i18n/format.tsseam; naming a locale explicitly IS the opt-out. CI-gated, and the failure (a Chinese UI rendering7/30/2026) ships silently. - Never hardcode a user-facing English string. The dashboard ships in 12 languages; add a catalog key. CI-gated.
- Data fetching is React Query, never
useState+useEffect. Follow the existing query-key convention. - Animation is Framer Motion. Do not add new CSS
@keyframes. - Styling uses design tokens (
var(--bg),var(--text), …), never a literal color. - Typography: no
text-xs, and no text below 10px. - Accessibility: use
<Clickable>rather than<div onClick>; give every icon-only button anaria-label; use<Btn>/<SendBtn>rather than a raw<button>; announce streaming regions witharia-live; honor the modal focus-trap contract. - Compose from
src/components/ui.tsx. Never hand-roll a panel section header; usePanelSectionHeader. src/extensions.tsis core-owned and must register nothing. Core registrations belong in the seed maps.- Edition composition is fail-closed: it needs
KIROCREW_EDITION_DIRandKIROCREW_ALLOW_EDITION=1. Never set the latter in a release or publish job. A contaminated public wheel cannot be unpublished.