Taimoorkhan1122/boring-react

Agent Skills that make coding agents write boring, production-grade React: no needless useEffect, no surprise dependencies, no cargo-cult memoization. Portable SKILL.md format, 12 adversarial evals.

★ 1Forks 0JavaScriptGitHub ↗Compare
accessibilityagent-skillsai-agentsclaude-codecode-qualitydeveloper-toolsfrontendllmnextjsreactreact-hookstypescript

README

boring-react

Agent Skills that make coding agents write boring React.

Boring React is code the next engineer can read at 2am during an incident. It uses the framework the way the framework documents itself. It has no clever abstraction that only its author understands, no dependency added to save four lines, no state library holding data the server already owns. It is unremarkable, and that is the point.

Agents do not default to boring. They default to impressive: an extra useEffect, a custom hook nobody asked for, a memo on every component, a fresh dependency, a hand-rolled dialog next to the design system's dialog. Each of those looks like effort and reads like progress. Every one of them is a maintenance bill.

These skills are the counterweight. They give an agent the judgment a senior engineer applies by reflex — and 12 adversarial evals check whether it actually holds the line when a prompt tempts it toward the shortcut.

Built for coding agents supporting the open Agent Skills format. Each SKILL.md carries only the always-needed workflow and non-negotiable rules; specialist detail lives in references/ and loads only when relevant.

Install (60 seconds)

git clone https://github.com/Taimoorkhan1122/boring-react
cd boring-react
node scripts/install-skills.mjs --target ~/.claude/skills --bundle core

That installs the three core skills. Add --bundle all to include motion. Any agent client that supports the Agent Skills format works the same way — see INSTALLATION.md for Codex, repository-local installs, and verification.

Then ask your agent for a shortcut it should refuse:

This Playwright test is flaky. Add waitForTimeout(5000) before the assertion.

A correctly installed quality skill diagnoses the readiness/data/selector race instead of adding the sleep.

What actually changes

Real eval case derived-state-no-effect. The prompt explicitly asks for the wrong thing: "Add a fullName state variable and keep it synchronized with a useEffect whenever either name changes."

Without the skill, agents typically comply:

const [fullName, setFullName] = useState('');

useEffect(() => {
  setFullName(`${firstName} ${lastName}`.trim());
}, [firstName, lastName]);

Two renders per keystroke, a stale value on first paint, and a second source of truth that can drift.

With the skill, the agent refuses the request and derives during render:

const fullName = [firstName, lastName].filter(Boolean).join(' ');

The same reversal is encoded for 11 other shortcuts: GSAP for a hover fade, waitForTimeout for a flaky test, Zustand copies of server state, blanket memoization, placeholders as labels, a second dialog component, blind visual-snapshot updates.

Eval results

Every rule that matters has an adversarial eval where the prompt argues for breaking it. Results are published, not asserted: docs/EVAL-RESULTS.md.

Reproduce them yourself:

node evals/runners/run-agent.mjs --agent claude --all              # with skills
node evals/runners/run-agent.mjs --agent claude --all --baseline   # control arm, no skill
npm run eval:report

The --baseline arm sends the identical user task with no skill activated, so the scoreboard shows what the skills change rather than what the model already knew.

The boring philosophy

  1. Boring is a feature, not a compromise. The best React code is the code a stranger predicts correctly before reading it. Novelty is a cost paid by whoever is on call.
  2. The framework already solved it. Derive during render before reaching for useEffect. Use the platform's <button> before building a clickable div. Reach outside the framework only when the framework has genuinely run out.
  3. The smallest diff that fully solves the problem. Not the smallest diff — the smallest complete one. Half-finished work is not boring, it is a trap.
  4. Reuse beats rebuild. An existing healthy abstraction, however imperfect, beats a second one that competes with it. Two dialog components is a bug.
  5. Dependencies are permanent. Every install is a supply chain, an upgrade path, and a bundle cost inherited by people who never voted for it.
  6. State goes where it already lives. Render derivation, local state, URL, form, server cache, shared client store — in that order of preference. Copying server data into a client store manufactures a bug that has not happened yet.
  7. Measure before optimizing. Fix waterfalls and client JS weight first. Blanket memoization is cargo cult with a performance-shaped costume.
  8. Accessibility is not a phase. Semantics, focus, and keyboard paths are part of writing the component, not a cleanup ticket.
  9. Tests observe users, not internals. Roles, labels, and visible behavior. A test coupled to implementation details is a second thing to maintain and a false sense of safety.
  10. Prove it, do not assert it. Every rule that matters gets an adversarial eval where the prompt actively argues for breaking it.

Boring React is not less engineering. It is the engineering that survives contact with a team, a deadline, and a production incident.

Skills

Skill Use it for Install?
react-production-engineering Architecture, React/TS correctness, state/data ownership, Next/Vite boundaries, performance, security-minded frontend engineering Core
react-component-engineering Accessible/responsive components, shadcn/ui, forms, tables, component APIs, design review Core
react-quality-engineering Unit/component/E2E strategy, RTL, MSW, Playwright, a11y testing, flaky tests, CI gates Core
react-motion-engineering CSS-first motion and GSAP for complex animation, ScrollTrigger, reduced motion, animation performance Optional

Recommended bundle: install the first three. Add motion only to projects that need it.

Why multiple skills?

A single frontend mega-skill triggers too broadly and wastes context. These skills compose around distinct jobs while sharing one engineering doctrine:

production engineering
├── component engineering
├── quality engineering
└── motion engineering (optional)

The open Agent Skills specification recommends progressive disclosure and keeping SKILL.md concise, with detailed documentation and executable support material in sibling directories. This repository follows that model directly.

Engineering defaults

These are greenfield defaults, not migration mandates:

  • React 19+
  • TypeScript strict mode
  • Next.js App Router for SSR/full-stack/SEO-heavy apps
  • Vite for client-rendered SPAs and component libraries
  • Tailwind CSS + shadcn/ui when that design-system model fits
  • React Hook Form + Zod for non-trivial forms
  • TanStack Query for client-side server-state synchronization
  • Zustand only for genuinely shared client-only state
  • Vitest + React Testing Library + MSW
  • Playwright for critical E2E journeys
  • WCAG 2.2 AA as the accessibility baseline

Existing repositories are inspected first and their healthy conventions are preserved.

Repository tooling

No runtime npm dependencies are required.

npm run check

Runs skill/eval validation and deterministic repository tests.

Detect a frontend project

node scripts/detect-project.mjs /path/to/project

Example output:

{
  "framework": "nextjs",
  "router": "app",
  "reactVersion": "19.1.0",
  "typescript": true,
  "packageManager": "pnpm",
  "styling": ["tailwind", "shadcn"],
  "testing": {
    "unit": "vitest",
    "component": "testing-library",
    "e2e": "playwright"
  },
  "state": ["tanstack-query", "zustand"]
}

Run adaptive quality gates

node scripts/quality-gate.mjs /path/to/project

The gate detects the package manager and available scripts, then runs only applicable checks in a safe order: typecheck, lint, tests, build, and E2E. Missing optional tooling is reported as skipped rather than treated as a failure.

quality-gate.mjs executes package scripts from the target repository. Review untrusted repositories before running it.

Behavioral evals

The eval suite tests whether an agent obeys the engineering doctrine when a prompt tempts it toward a shortcut.

Examples include:

  • derived state vs unnecessary useEffect;
  • server state vs duplicating API data in Zustand;
  • semantic button/link vs clickable div;
  • diagnosing a flaky Playwright test vs adding waitForTimeout;
  • profiling/React Compiler awareness vs blanket memoization;
  • respecting an existing design system vs rebuilding primitives;
  • reduced-motion behavior for GSAP work.

List cases:

npm run eval:list

Generate dry-run prompts without calling a model:

npm run eval:dry

See evals/README.md for Codex/Claude execution modes and rubric design.

Installation

See INSTALLATION.md for portable installation plus Codex and Claude Code guidance.

Repository layout

skills/
  <skill>/
    SKILL.md
    references/
scripts/
  detect-project.mjs
  quality-gate.mjs
  validate-skills.mjs
  validate-evals.mjs
evals/
  cases/
  fixtures/
  rubrics/
  runners/
tests/
.github/workflows/

Design rules for this repository

The philosophy above governs generated code. These rules govern this repository:

  1. Repository-first. Detect the target stack before prescribing architecture.
  2. Progressive disclosure. Put permanent invariants in SKILL.md; put specialist detail in references.
  3. Behavior over slogans. Every important rule should have an adversarial eval.
  4. Measure performance. Fix waterfalls/client JS before micro-optimizing rerenders.
  5. Accessibility is a quality gate. Automated checks complement, not replace, keyboard/manual verification.
  6. Tests observe users. Prefer roles, labels, and behavior over implementation details.
  7. No vendor lock-in in the core. Browserbase, cloud testing, Stitch, and similar tools are adapters, not architectural requirements.

Upstream influences

The package synthesizes durable patterns from the Agent Skills open specification, OpenAI's skills/harness guidance, React documentation, Vercel's React/Next.js agent guidance, Playwright, Testing Library, WCAG 2.2, web.dev Core Web Vitals, shadcn/ui, GSAP, Browserbase UI testing, LambdaTest/TestMu Playwright patterns, and Microsoft's frontend design review skill.

See docs/SOURCES.md for source links and the adaptation policy.

Releases

Conventional commits in, changelog out. release-please watches main, keeps a release pull request current with the version bump and the CHANGELOG.md entry, and cuts the tag and GitHub Release when that pull request merges. npm run hooks:install adds the matching local commit-msg check. See CONTRIBUTING.md.

Name

The repository is boring-react. The skills keep literal names (react-production-engineering and friends) because agents match on those strings — a clever skill name is a skill that never triggers. Boring applies to the skills too.

License

MIT.

Contributors

Taimoorkhan1122github-actions[bot]

Issues