react-ts-vite
AGENTS.md1 starsChanged 25 days agoMITView on GitHub
Generated from .agent/ by npm run agent:sync. Edit the files in .agent/, not this one. Active architecture: classic. This project was built from react-ts-vite, a React 19 + TypeScript + Vite 8 + Tailwind CSS 3 starter whose mindset is Design tool × Technology × Architecture × Cleanliness: Tailwind CSS (with Headless UI and Heroicons) for design, React for the UI, a selectable folder architecture for structure, and strict tooling for cleanliness. Keep those four in balance in every change.
- Reads credentials
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,774 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.
In this repository18 other files it gives its agents.
- docs/agents.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- .cursor/rules/rtv-architecture.mdcCursor rule
- .cursor/rules/rtv-code-style.mdcCursor rule
- .cursor/rules/rtv-design-system.mdcCursor rule
- .cursor/rules/rtv-git-workflow.mdcCursor rule
- .cursor/rules/rtv-testing.mdcCursor rule
- accessibility-auditSkill
- ci-cd-dockerSkill
- clean-code-reviewSkill
- dependency-upgradeSkill
- deployment-insightsSkill
- project-architectureSkill
- react-componentSkill
- scaffold-featureSkill
- tailwind-design-systemSkill
- testing-vitestSkill
The file
We split this AGENTS.md into the rules it gives an agent
11 rules. About 0 are common, 1 is distinctive, and 10 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
10
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 10
Read rtv.config.json: it declares the active architecture, the applied design templates and the path aliases.
- Very specific: line 21
Run
npm run check: before finishing: typecheck · lint · format · architecture rules · agent sync · tests. - Distinctive: line 28
Add a dependency without stating why in the commit or PR.
- Very specific: line 29
Commit secrets. ANTHROPIC_API_KEY lives in CI secrets or the developer's shell.
- Very specific: line 53
Place new code in the layer whose purpose matches it (see the table below).
- Very specific: line 54
Import through the path aliases listed below (@components/Button, @pages/Dashboard).
- Very specific: line 102
Every folder exposes an index.ts barrel when it has more than one public module.
- Very specific: line 117
Modules: import through aliases; order imports as external packages → aliases → relative, separated by blank lines.
- Very specific: line 133
Forms: use @tailwindcss/forms base styles plus ring-1 ring-inset borders and focus:ring-2 focus:ring-brand-600.
- Very specific: line 146
Changelog: add a line under ## [Unreleased] in CHANGELOG.md for every user-visible change (Keep a Changelog format).
- Very specific: line 159
Keep tests deterministic: no real timers or network.
≈ “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
<!-- rtv:generated -->AGENTS.md
Generated from
.agent/bynpm run agent:sync. Edit the files in.agent/, not this one. Active architecture: classic.
This project was built from react-ts-vite, a React 19 + TypeScript + Vite 8 + Tailwind CSS 3 starter whose mindset is Design tool × Technology × Architecture × Cleanliness: Tailwind CSS (with Headless UI and Heroicons) for design, React for the UI, a selectable folder architecture for structure, and strict tooling for cleanliness. Keep those four in balance in every change.
Before you start
- Read
rtv.config.json: it declares the active architecture, the applied design templates and the path aliases.npm run arch -- currentprints the layers, their purposes and the import rules thatnpm run arch:checkenforces. - Pick the matching skill in
.agent/skills/for the task at hand (component, page, feature, tests, review, accessibility, upgrade, CI, deployment report) and follow it. - Toolchain: Node ≥ 22.12, npm. Install with
npm install. Scripts are listed below.
How to work
- Place first. Decide which layer owns the change (see the architecture rule). New top-level folders under
src/are never created ad hoc. - Import through aliases (
@components/Button,@pages/Dashboard,@services/http). Parent-relative imports (../) are an ESLint error; inside a page or slice, import siblings with./or through the slice alias (@pages/Dashboard/data). - Type everything.
strictTypeScript, noany,import typefor types, explicit prop types for components. - Style with Tailwind utilities and the
brand-*tokens. Interactive patterns come from Headless UI, icons from Heroicons. Every screen must work in light and dark mode and be keyboard accessible. - Test behaviour. Vitest + Testing Library; every page has a smoke test in
__tests__/pages/. Add or update tests with the code they cover. - Run
npm run checkbefore finishing: typecheck · lint · format · architecture rules · agent sync · tests. Fix what it reports; never disable a rule, skip a test or addeslint-disableto get green. - Keep docs in sync. New script, template, architecture or skill ⇒ update
README.md/docs/and runnpm run agent:sync.
Never
- Move folders by hand to change the architecture; use
npm run arch -- apply <id>. - Edit generated files (
AGENTS.md,.agent/rules/architecture.md,.agent/agent.json,.claude/skills/*,.claude/commands/*,.cursor/rules/*,.github/copilot-instructions.md); edit the source in.agent/and runnpm run agent:sync. - Add a dependency without stating why in the commit or PR; prefer the platform and the libraries already present.
- Commit secrets.
ANTHROPIC_API_KEYlives in CI secrets or the developer's shell.
Scripts
| Script | Purpose |
npm run dev / build / preview | Vite dev server (port 3000) · production build · serve the build |
npm test / npm run test:run / coverage | Vitest watch · single run · coverage report |
npm run check | Quality gate: typecheck, lint, format:check, arch:check, agent:check, test:run |
npm run lint:fix / format | Auto-fix ESLint findings · format with Prettier (Tailwind class order included) |
npm run setup | Wizard: architecture, design templates, Claude deployment insights |
npm run arch -- <list|current|apply <id>|check|scaffold> | Architecture catalogue and switcher |
npm run templates -- <list|add <id…>|remove <id…>|apply> | Design-template pages |
npm run agent -- <sync|check|list> | AI-agent instructions |
npm run deploy:insights | Claude deployment report (--dry-run to preview the prompt) |
Rules (always apply)
Project architecture
<!-- source: .agent/rules/architecture.md -->This project uses the Classic architecture (classic): Folders by technical role: components, hooks, services, pages.
- Place new code in the layer whose purpose matches it (see the table below). Never create new top-level folders under
src/without updating the architecture catalogue (scripts/lib/architectures.mjs). - Import through the path aliases listed below (
@components/Button,@pages/Dashboard). Never use parent-relative imports (../); the ESLint ruleno-restricted-importsenforces this. - Respect the layer dependency direction. Run
npm run arch:checkbefore finishing a task; it fails on any forbidden import. - Applied design templates: none. Pages live in
src/pages/, each with a smoke test in__tests__/pages/. - To switch architecture run
npm run arch -- apply <id>(never move folders by hand). Project root:react-ts-vite.
Classic (classic) — layered by type
The simplest mental model. Code is grouped by what it is (a component, a hook, a service) rather than by what it does. Zero ceremony, instantly familiar to every React developer.
src/
├── assets/
├── components/
├── const/
├── hooks/
├── pages/
├── services/
├── types/
└── utils/| Layer | Path | Purpose | May import |
pages | src/pages | Route-level screens. Compose UI, read data through hooks and own page state. | pages, components, hooks, services, types, const, utils, assets |
components | src/components | Reusable, presentational UI. Receives data through props and never talks to services directly. | components, hooks, types, const, utils, assets |
hooks | src/hooks | Stateful logic and data access (useSomething). The bridge between UI and services. | hooks, services, types, const, utils |
services | src/services | Side effects: API clients, storage, analytics. Framework-agnostic — no React here. | services, types, const, utils |
utils | src/utils | Pure, framework-agnostic helpers. No side effects. | utils, types, const |
const | src/const | Constants and configuration: navigation, routes, feature flags, environment access. | const, types |
types | src/types | Shared TypeScript types and interfaces. | types |
assets | src/assets | Static assets imported by code: images, fonts, SVG. | — |
Aliases
@→src@assets→src/assets@components→src/components@const→src/const@hooks→src/hooks@pages→src/pages@services→src/services@types→src/types@utils→src/utils
Principles
- Dependencies flow downwards: pages → components → hooks → services → utils/const/types.
- Components never import services; data access lives in hooks.
- Every folder exposes an
index.tsbarrel when it has more than one public module.
Best for: Small and medium apps · Prototypes and MVPs · Teams new to front-end architecture
Trade-offs: Folders grow wide as features multiply · Code for one feature is spread across several folders
Code style and cleanliness
<!-- source: .agent/rules/code-style.md -->- Formatting is Prettier's job (
.prettierrc.json: no semicolons, single quotes, trailing commas, 100 columns, Tailwind class sorting). Never hand-format or discuss style in reviews. - TypeScript:
strictis on. Noany(useunknownand narrow), no non-null assertions unless the invariant is explained in a comment,import typefor type-only imports,satisfiesfor typed literals. Prefertypealiases for props and unions;interfaceonly for extensible object contracts. - Components: one component per file, named
PascalCase, folderComponentName/index.tsxfor anything with more than one file. Props are atype ComponentNameProps. Components are named exports; pages (route-level) andAppare default exports. Keep a component under ~150 lines: split by responsibility, not by line count. - Hooks are
useSomethingand own stateful or side-effectful logic. Components stay presentational; data access goes through hooks, hooks call services. Follow the React Compiler-era lint rules (react-hooks/*): nosetStateinside effects, no mutation of props or state, derive values during render. - Services are plain TypeScript modules (no React, no JSX) with explicit return types. Errors are thrown as
Errorsubclasses or returned as typed results; never swallow them silently. - Modules: import through aliases; order imports as external packages → aliases → relative, separated by blank lines. No default exports from barrels;
index.tsre-exports only. - Naming: files mirror their export (
useTheme.ts,Button/index.tsx,formatCurrency.ts); booleans read as predicates (isOpen,hasError); event handlers arehandleXinside andonXas props. - Comments explain why, never what. No commented-out code, no
console.login committed code, no TODO without an owner or issue link. - Dead code is deleted, not kept "just in case". Git remembers.
- Small, reversible changes: one concern per commit, generated files regenerated by their tool, not edited.
Design system (Tailwind CSS + Headless UI + Heroicons)
<!-- source: .agent/rules/design-system.md -->- Utilities first. Style with Tailwind utility classes in JSX. Custom CSS belongs only in
src/index.css(@layer base) for tokens and global resets. No inlinestyleexcept for truly dynamic values (e.g. a computed width). - Tokens. The brand colour scale is defined once as CSS variables in
src/index.cssand exposed asbrand-50 … brand-950(e.g.bg-brand-600,text-brand-400,ring-brand-600/20). Usebrand-*for primary actions and accents, Tailwind greys for surfaces and text. Re-theming means changing the variables, never find-and-replace in components. - Dark mode uses the
classstrategy (darkMode: 'class'): adddark:variants for every surface, text and border colour you set. TheuseThemehook (dashboard template) toggles thedarkclass on<html>and persists the choice. - Layout: mobile-first (
sm:→lg:→xl:), max-width containers (mx-auto max-w-7xl px-6 lg:px-8), the 4-pt spacing scale, consistent radii (rounded-mdcontrols,rounded-lg/rounded-2xlsurfaces) and shadows (shadow-smcontrols,shadowcards). - Interactive patterns come from Headless UI v2 (
Dialog,DialogPanel,Menu,MenuItems,Listbox,Switch,Disclosure,Popover,Transition). Use the named exports and state styling via data attributes (data-[focus]:bg-gray-50,data-[open]:…). Never re-implement focus traps, keyboard navigation or aria wiring by hand. - Icons are Heroicons:
@heroicons/react/24/outlinefor navigation and UI chrome,24/solidfor emphasis,20/solidfor dense/inline use. Alwaysaria-hidden="true"and give the surrounding control an accessible name (<span class="sr-only">). - Forms use
@tailwindcss/formsbase styles plusring-1 ring-insetborders andfocus:ring-2 focus:ring-brand-600. Every field has a visible<label>; errors are linked witharia-describedby. - Accessibility is part of the design: semantic landmarks (
header,nav,main,footer), oneh1per page, visiblefocus-visible:outlinestyles,aria-current="page"on active nav,role="status"/aria-livefor async feedback, WCAG AA contrast (the default brand scale passes on white and gray-900). - Conditional classes: compose with array
.join(' ')or a tinycnhelper in@utils; keep class strings static where possible so Tailwind can see them. - Class order is enforced by
prettier-plugin-tailwindcss; do not reorder by hand.
Git workflow and releases
<!-- source: .agent/rules/git-workflow.md -->- Conventional Commits:
feat:,fix:,docs:,refactor:,test:,chore:,ci:,build:,perf:, with an optional scope (feat(dashboard): add period filter). Subject in the imperative, ≤ 72 characters, body explains why. - Branches:
feat/<topic>,fix/<topic>,chore/<topic>frommaster. One concern per branch; keep PRs reviewable (< ~400 changed lines when possible). - Before pushing:
npm run checkmust pass locally; CI runs the same gate on Node 22 and 24 plus an architecture-switch smoke test. - Pull requests describe the change, how it was tested and any follow-ups. Link issues. Generated files (
AGENTS.md, mirrors, lockfile) are committed together with the change that produced them. - Changelog: add a line under
## [Unreleased]inCHANGELOG.mdfor every user-visible change (Keep a Changelog format). - Release: bump
versioninpackage.json(npm version <patch|minor|major> --no-git-tag-version), move Unreleased into a dated changelog section, commitchore(release): vX.Y.Zand merge it into thereleasebranch. TheReleaseworkflow (.github/workflows/release.yml) runs the quality gate, tagsvX.Y.Z, publishes the GitHub release from the changelog section, publishes to npm with provenance and, whenANTHROPIC_API_KEYis configured, appends a Claude deployment report. Never tag by hand. - Never rewrite shared history (
push --forceonmaster), commit.envfiles or credentials, or merge with a red CI.
Testing
<!-- source: .agent/rules/testing.md -->- Stack: Vitest 5 (
happy-domenvironment, URLhttp://localhost:3000/),@testing-library/react16,@testing-library/jest-dommatchers (loaded invitest.setup.ts).globals: trueis on, but importdescribe/test/expectfromvitestexplicitly for clarity. - Location:
__tests__/mirrorssrc/(__tests__/pages/Dashboard.test.tsx,__tests__/components/Button.test.tsx). Script and library tests live in__tests__/scripts/*.test.mjs. Design templates are tested from__tests__/templates/. - Every page has a smoke test that renders it and asserts its
h1.npm run templates -- add <id>generates it; keep it when you customise the page. - Test behaviour, not implementation: query by role and accessible name first (
getByRole('button', { name: /sign in/i })), then label/text; avoiddata-testidunless there is no accessible handle. Interact withfireEvent(or@testing-library/user-eventif you add it) and assert visible outcomes. - Isolate at the boundary: mock services (
vi.mock('@services/http')) orfetch, never React internals. Hooks are tested through the components that use them or withrenderHook. - Keep tests deterministic: no real timers or network; use
vi.useFakeTimers()when time matters; reset mocks inafterEach. - Coverage (
npm run coverage, v8 provider) is a signal, not a target. Cover branches that matter: validation, error states, empty states, permissions. - Run
npm run test:run(CI mode) before pushing;npm testwatches while developing.
Skills
Reusable know-how for specific tasks. Read the linked SKILL.md before starting a matching task.
| Skill | When to use |
accessibility-audit | Audit and fix the accessibility of pages and components built with Tailwind, Headless UI and Heroicons — semantics, headings, names, keyboard, focus, contrast, forms, live regions, motion — and verify with Testing Library queries. Use when asked about a11y, WCAG, screen readers, keyboard support or when reviewing UI changes. |
ci-cd-docker | Work with this project's delivery pipeline — the GitHub Actions quality gate and architecture smoke test, npm publishing with provenance, the Claude deployment-insights workflow, and the Docker images (Vite dev server with hot reload, nginx production image). Use when CI fails, when adding a workflow or deploy target, or when running the app in containers. |
clean-code-review | Review a diff or pull request against this project's rules — architecture placement, import direction, types, component design, design-system usage, accessibility, tests and docs — and report findings by severity with concrete fixes. Use when asked to review, audit or critique code, or before opening a PR. |
dependency-upgrade | Upgrade dependencies safely in this React + TypeScript + Vite + Tailwind + Vitest project — grouped bumps, changelog review, known breaking changes, verification with the full quality gate and documentation updates. Use when asked to update, bump or modernise dependencies or to fix a broken upgrade. |
deployment-insights | Produce or configure Claude deployment insights — a Markdown report with summary, release notes, risk assessment, bundle notes and a post-deploy checklist generated from commits, diff and build output. Use when asked for release notes, a deployment summary, a risk review before shipping, or to enable/configure "Claude on deployment". |
project-architecture | Decide where code lives and keep imports pointing the right way in the active folder architecture (classic, feature-based, Feature-Sliced Design, clean/hexagonal or atomic). Use when creating files, resolving npm run arch:check violations, choosing between layers, or switching architectures. |
react-component | Create or refactor a React component the way this project expects — typed props, named export, Tailwind tokens, accessibility, co-located test and the right layer. Use when asked to build, extract, split or clean up a component, hook or page. |
scaffold-feature | Plan and create all the files a new business feature needs in the active architecture (types/entities, service or use case, hook, UI, page, route, navigation, tests). Use when asked to "add a feature", "implement <capability>" or scaffold a vertical slice. Accepts the feature name as $ARGUMENTS. |
tailwind-design-system | Apply the project's Tailwind CSS design system — brand tokens, dark mode, spacing and typography scale, Headless UI v2 patterns and Heroicons — when styling or re-theming UI. Use when building screens, fixing visual inconsistencies, adding interactive components (dialogs, menus, listboxes) or changing the brand palette. |
testing-vitest | Write and run tests with Vitest 5, Testing Library and jest-dom in this project — page smoke tests, component behaviour tests, hook tests, service mocks and script tests. Use when adding tests, fixing failing tests, raising coverage or deciding what to test. |
Workflows
Step-by-step procedures for recurring jobs.
| Workflow | Purpose |
add-feature | Implement a business capability across layers in the active architecture, with tests and documentation. |
add-page | Add a route-level page from a design template or from scratch, wire its route and test it. |
new-project | Scaffold a project from react-ts-vite, choose its architecture and templates, and make the first commit. |
release | Cut a version from the release branch, publish it to npm and produce the Claude deployment report. |
review-pr | Review changes against the project rules and report findings in a consistent format. |
switch-architecture | Move the project to another folder architecture safely with the switcher, then verify. |
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.

