react
Operate React applications as a named tool: inspect and diagnose React/Vite projects, design component boundaries and state flow, implement accessible responsive UI, and verify behavior with the project's tests. Use when a task explicitly involves React, JSX/TSX, React hooks, Rea
Install
npx skills add https://github.com/magnus919/agent-skills/tree/main/react
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install magnus919-agent-skills@llmmart
git clone https://github.com/magnus919/agent-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole magnus919/agent-skills collection as a plugin from our marketplace. Git is the plain clone.
README
react — Build and diagnose React applications
Why Install This Skill
React projects accumulate framework-specific failure modes: hooks that resynchronize unnecessarily, stale requests that overwrite newer data, routes that break under a subpath, and Vite environment values accidentally shipped to browsers. This skill gives your agent a focused operating loop for those problems.
After installation, your agent can inspect a React/Vite project safely, make component and state changes that fit its existing conventions, protect accessible interaction states, and verify the result with the project's own checks. It also includes a read-only doctor for quick diagnostics without installing dependencies or exposing environment values.
What You Get
| Directory | Purpose |
|---|---|
SKILL.md |
React-specific implementation workflow, guardrails, handoffs, and verification steps |
references/component-and-state.md |
Component boundaries, hooks, effects, async state, and forms |
references/vite-diagnostics.md |
Vite environment, build, asset-base, and deployment diagnostics |
scripts/react-doctor.py |
Bounded Python diagnostic with human-readable or JSON output |
scripts/test_react_doctor.py |
Offline tests for diagnostic behavior and safety guarantees |
evals/evals.json |
Six substantive output-quality cases for React and Vite work |
Quick Start
python3 scripts/react-doctor.py --json .
python3 scripts/react-doctor.py .
The doctor reads project files only. It does not install packages, run scripts, contact the network, or print environment values.
Triggers
Load this skill when working with React, JSX/TSX, hooks, React Router, Vite React configuration, React component/state implementation, or React build failures. Use it for a focused project diagnosis before editing.
Requirements
- Python 3.8+ for the bundled diagnostic and tests.
- Node.js and the project's package manager for application builds and tests.
- Existing React/Vite project files; no API key is required.
- Use
frontend-engineeringfor framework-agnostic frontend architecture,playwrightfor browser automation, andweb-accessibilityfor dedicated accessibility audits.
Skill manifest
React Application Engineering
Use this skill for the React-specific implementation layer. Preserve the project's existing React version, package manager, build scripts, styling conventions, and routing model unless the user asks for a migration.
Operating loop
- Diagnose before editing. Run
scripts/react-doctor.py --json [PROJECT]and inspectpackage.json, source entry points, Vite config, TypeScript config, routes, and test scripts. The diagnostic is bounded and read-only. - Define the component contract. Identify the page/feature boundary, inputs and outputs, owned state, server state, loading/empty/error/success states, and side effects. Keep reusable components independent of route globals and avoid passing state through unrelated layers.
- Implement with explicit data flow. Prefer local state for local behavior, context only for genuinely cross-cutting concerns, and the existing server state/cache solution for remote data. Keep effects for synchronization with external systems; derive values during render rather than storing duplicates.
- Keep UI resilient. Render a useful loading, empty, error, and success experience. Cancel or ignore stale async work, handle aborts, and avoid setting state after an obsolete request. Preserve stable keys and avoid mutating props or state.
- Build for the browser. Use semantic HTML, keyboard-operable controls, visible focus, responsive layout, and stable accessible names. For detailed accessibility requirements, load web-accessibility.
- Verify in layers. Run the narrowest existing unit/component test, then lint/typecheck, then the production build. For browser-level flows use playwright, not ad hoc browser automation. Report the exact commands and any environment-dependent checks that were skipped.
React-specific rules
- Hooks run unconditionally and in the same order on every render; never call them in branches, loops, event handlers, or nested functions.
- Effects synchronize with external systems. Do not use an effect to calculate a value that can be derived from props/state, or to mirror props into state without a clear user-editing requirement.
- Use functional updates when the next state depends on the previous state. Give list items stable keys from domain identity, not array indexes when the list can reorder, insert, or delete.
- Treat event handlers as user intent and keep them separate from render-time computation. Disable or guard duplicate submissions and expose pending state.
- Keep API response validation and transformation at the integration boundary; components should consume a typed, predictable view model.
- Do not add a state library or router solely because it is popular. First map ownership and use the project's existing choices.
- In Vite, expose only intentionally public variables using the project's
documented prefix (normally
VITE_); never put secrets in client bundles. Read references/vite-diagnostics.md for environment, build, and deployment checks.
Routing and handoffs
- Component architecture, responsive implementation, performance budgets, and general frontend testing: frontend-engineering.
- Browser E2E authoring, locator choice, network interception, and Playwright runs: playwright.
- Semantic structure, keyboard/focus behavior, WCAG acceptance evidence, and accessibility audits: web-accessibility.
- React Native, Expo, Android, or iOS implementation: mobile-development.
Reference routing
| Load when | Reference |
|---|---|
| Choosing component boundaries, state ownership, effects, or async UI behavior | references/component-and-state.md |
| Diagnosing Vite env exposure, dependency versions, build output, or deployment paths | references/vite-diagnostics.md |
Included script
scripts/react-doctor.py is a read-only, dependency-free diagnostic. Run
scripts/react-doctor.py --help for options. It accepts a project directory,
checks common React/Vite signals, and emits human-readable or bounded JSON
output. It does not install packages, execute project scripts, access the
network, or print environment values.
Completion boundary
Stop when the requested React change is implemented, the project's relevant checks have run, and remaining failures are reported with their command and root-cause evidence. Do not broaden a component task into a framework migration or an accessibility audit without explicit scope.
Files (agent-skills)
-
evals
-
evals.json 3.1 KB
{ "schema_version": 1, "skill_name": "react", "evals": [ { "id": "component-state-boundary", "prompt": "Design a React dashboard filter component that fetches results and has loading, empty, error, and success states.", "expected_output": "A component/state plan that assigns ownership, avoids duplicated derived state, and describes each async UI state.", "assertions": ["Identifies local, URL, and server state separately", "Includes loading, empty, error, and success behavior", "Avoids an unnecessary effect for derived values"] }, { "id": "stale-request-protection", "prompt": "Fix a React search hook where a slower response for the previous query overwrites the current query results.", "expected_output": "A hook implementation or patch using abort or an active-request guard, with cleanup and intentional cancellation handling.", "assertions": ["Prevents stale responses from committing state", "Cleans up the obsolete request", "Does not present abort cancellation as a user error"] }, { "id": "vite-secret-boundary", "prompt": "Diagnose why a Vite app exposes an API token in its browser bundle and propose a safe fix.", "expected_output": "A diagnosis that treats client env values as public, removes the secret from client code, and routes privileged access through a server boundary.", "assertions": ["Explains compile-time Vite env substitution", "Never recommends shipping a secret under a public prefix", "Includes a way to rotate the exposed credential"] }, { "id": "subpath-routing-build", "prompt": "A React Router app works at localhost root but its JS and CSS 404 when deployed under /portal/. Debug the Vite deployment.", "expected_output": "A bounded diagnostic covering Vite base, generated asset URLs, and host-side SPA history fallback, followed by a preview verification.", "assertions": ["Checks the Vite base setting", "Checks SPA fallback for deep links", "Verifies the built output at the deployed subpath"] }, { "id": "accessible-react-control", "prompt": "Implement an expandable React disclosure with keyboard support and a focus-safe error message.", "expected_output": "A semantic button/disclosure implementation with an accessible name, aria-expanded linkage, visible focus, and an announced error path.", "assertions": ["Uses native button semantics", "Keeps aria-expanded and controlled-region linkage synchronized", "Routes detailed WCAG review to web-accessibility"] }, { "id": "verification-handoff", "prompt": "Add a React form feature and verify it without installing new dependencies or using browser automation unnecessarily.", "expected_output": "A verification sequence using existing project scripts, then build, with Playwright reserved for browser-level flows and failures reported exactly.", "assertions": ["Inspects package scripts and existing conventions first", "Runs focused checks before the production build", "Routes browser E2E work to playwright rather than inventing ad hoc automation"] } ] }
-
-
references
-
component-and-state.md 2.7 KB
# React Component And State Patterns ## Start with ownership Describe each value as one of local UI state, server/cache state, URL state, or cross-cutting application state. Keep state at the lowest common owner. If a value is derived from other values, compute it during render or in a memoized calculation when measurement proves the calculation costly; do not create a second source of truth. A practical component boundary usually owns one interaction or visual contract. Split when a component has unrelated state machines, repeated markup, or an API that requires consumers to understand implementation details. Keep domain transformations outside presentational components when they can be tested without a browser. ## Effects and asynchronous work Before adding `useEffect`, name the external system it synchronizes with: network, subscription, timer, browser API, or imperative widget. If none exists, prefer render derivation or an event handler. Every effect should have a cleanup when it creates a subscription, timer, listener, or request that can outlive the render. For a request keyed by an input, use an abort signal or an active-request guard, handle abort as non-error cancellation, and ensure a late response cannot replace newer data. Model `status` explicitly (`idle`, `pending`, `success`, `error`) and render all meaningful states. Avoid catching an error only to log it and leave a permanently pending screen. ## Interaction contracts Use controlled inputs when validation, submission, or external reset is part of the feature; otherwise an uncontrolled input with a ref may be simpler. Keep submit handlers idempotent, disable or guard while pending, and preserve the user's entered data on recoverable errors. Announce validation and server errors through the accessible structure, not only a color or toast. For lists, key rows with stable domain identity. If a row has local state, an index key can transfer that state to another record after sorting or deletion. Use functional updates for transitions based on prior state, especially when multiple events may batch. ## Verification checklist - Hooks are unconditional and dependencies reflect values read from the effect. - No derived state or duplicated server state is introduced without a reason. - Loading, empty, error, retry, and success states are represented where relevant. - Async cleanup prevents stale writes and treats cancellation intentionally. - Buttons and links use native semantics; keyboard and focus behavior is tested. - Component tests cover user-visible behavior; browser flows are delegated to [playwright](../../playwright/SKILL.md). - Dedicated semantic and WCAG review is delegated to [web-accessibility](../../web-accessibility/SKILL.md). -
vite-diagnostics.md 2.6 KB
# Vite Diagnostics And Release Checks ## Environment values Vite substitutes client-exposed variables at build time. Only variables with the configured public prefix (commonly `VITE_`) should be read by browser code. Treat every such value as public: it is not a secret merely because it lives in `.env`. Keep credentials and server-only configuration outside the client bundle. Check `.env.example`, Vite config, deployment configuration, and the actual built assets for accidental exposure. Vite loads mode-specific files with a defined precedence. Confirm the intended mode (`development`, `production`, or a custom mode) and do not assume a local `.env` matches CI. When diagnosing a value, inspect its name and source without printing its value. Re-run the build after changing env configuration because substitution is compile-time. ## Build and asset paths Inspect `base` in `vite.config.*` when the app is served below `/`. A wrong base usually appears as 404s for module, CSS, or asset URLs after deployment even though the root-local dev server works. Validate the generated HTML and asset references against the real deployment path. For SPA history fallback, confirm the host serves the app entry point for non-root routes; Vite does not configure that server rule for every deployment target. ## Dependency and output checks Use the project's package manager lockfile and scripts. Check that `react` and `react-dom` versions are compatible and that duplicate React copies are not being pulled into the bundle, which can produce invalid hook call errors. Do not blindly delete lockfiles or upgrade dependencies while diagnosing. For release verification, run the existing typecheck/lint/test commands before `vite build`, inspect warnings, and use a preview server for a smoke check at the deployed base path. Keep source maps and reports out of user-facing output unless the project intentionally publishes them. ## Safe diagnostic sequence 1. Record the package manager and available scripts from `package.json`. 2. Identify the active mode and public-prefix configuration without exposing values. 3. Inspect `base`, route fallback, and generated asset URLs. 4. Check lockfile consistency and React package version alignment. 5. Run the narrowest reproducible check, then the production build. 6. Confirm the browser flow with [playwright](../../playwright/SKILL.md) when route, asset, or navigation behavior is involved. 7. Ask [frontend-engineering](../../frontend-engineering/SKILL.md) for broader performance/component strategy and [web-accessibility](../../web-accessibility/SKILL.md) for a dedicated accessibility audit.
-
-
scripts
-
react-doctor.py 3.6 KB
#!/usr/bin/env python3 """Bounded, read-only diagnostics for React/Vite projects.""" import argparse import json import re import sys from pathlib import Path MAX_BYTES = 512 * 1024 TEXT_FILES = ("package.json", "vite.config.js", "vite.config.ts", "vite.config.mjs", "vite.config.cjs", "tsconfig.json") def read_text(root, name): path = root / name try: if not path.is_file() or path.stat().st_size > MAX_BYTES: return None return path.read_text(encoding="utf-8") except (OSError, UnicodeError): return None def diagnose(root): result = {"project": str(root), "checks": [], "warnings": []} package_text = read_text(root, "package.json") package = None if package_text is None: result["warnings"].append("package.json is missing or exceeds the read limit") else: try: package = json.loads(package_text) if not isinstance(package, dict): raise ValueError("not an object") deps = {**package.get("dependencies", {}), **package.get("devDependencies", {})} result["checks"].append({"name": "package-json", "status": "ok"}) result["checks"].append({"name": "react-dependencies", "status": "ok" if "react" in deps and "react-dom" in deps else "warning"}) except (ValueError, TypeError, json.JSONDecodeError): result["warnings"].append("package.json is not valid JSON") config_name = next((name for name in TEXT_FILES[1:5] if read_text(root, name) is not None), None) result["checks"].append({"name": "vite-config", "status": "ok" if config_name else "info", "file": config_name}) source_files = [] for directory in (root / "src", root / "app"): if directory.is_dir(): source_files.extend(p for p in directory.rglob("*") if p.is_file() and p.suffix in {".jsx", ".tsx", ".js", ".ts"}) result["checks"].append({"name": "source-entry", "status": "ok" if source_files else "warning", "file_count": len(source_files)}) env_names = set() for path in root.glob(".env*"): text = read_text(root, path.name) or "" env_names.update(re.findall(r"^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=", text, re.MULTILINE)) result["checks"].append({"name": "public-env-names", "status": "ok", "names": sorted(n for n in env_names if n.startswith("VITE_"))}) if any(not n.startswith("VITE_") for n in env_names): result["warnings"].append(".env files contain non-public names; keep them server-side and never import secrets into client code") lockfiles = [name for name in ("package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb", "bun.lock") if (root / name).is_file()] result["checks"].append({"name": "lockfile", "status": "ok" if lockfiles else "warning", "files": lockfiles}) return result def main(argv=None): parser = argparse.ArgumentParser(description="Read-only React/Vite project diagnostics") parser.add_argument("project", nargs="?", default=".") parser.add_argument("--json", action="store_true", dest="as_json") args = parser.parse_args(argv) root = Path(args.project).expanduser().resolve() if not root.is_dir(): print("ERROR: project directory does not exist", file=sys.stderr) return 2 result = diagnose(root) if args.as_json: print(json.dumps(result, sort_keys=True)) else: print("React/Vite doctor: " + result["project"]) for check in result["checks"]: print("- {name}: {status}".format(**check)) for warning in result["warnings"]: print("WARNING: " + warning) return 0 if __name__ == "__main__": sys.exit(main()) -
test_react_doctor.py 2.4 KB
#!/usr/bin/env python3 """Offline tests for the read-only React doctor.""" import json import os import subprocess import sys import tempfile import unittest from pathlib import Path SCRIPT = Path(__file__).with_name("react-doctor.py") class DoctorTests(unittest.TestCase): def run_doctor(self, root, *args): return subprocess.run([sys.executable, str(SCRIPT), *args, str(root)], capture_output=True, text=True) def test_json_reports_react_vite_signals_without_values(self): with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) (root / "package.json").write_text(json.dumps({"dependencies": {"react": "18", "react-dom": "18"}}), encoding="utf-8") (root / "vite.config.ts").write_text("export default {}", encoding="utf-8") (root / "src").mkdir() (root / "src/App.tsx").write_text("export default function App() {}", encoding="utf-8") (root / ".env.local").write_text("VITE_PUBLIC=visible\nSECRET=do-not-print\n", encoding="utf-8") output = self.run_doctor(root, "--json") self.assertEqual(output.returncode, 0) report = json.loads(output.stdout) self.assertEqual(report["checks"][0]["status"], "ok") env_check = next(check for check in report["checks"] if check["name"] == "public-env-names") self.assertIn("VITE_PUBLIC", env_check["names"]) self.assertNotIn("do-not-print", output.stdout) def test_missing_project_is_usage_error(self): output = self.run_doctor(Path("/definitely/not/a/project")) self.assertEqual(output.returncode, 2) self.assertIn("does not exist", output.stderr) def test_malformed_package_is_reported(self): with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) (root / "package.json").write_text("{broken", encoding="utf-8") output = self.run_doctor(root, "--json") self.assertEqual(output.returncode, 0) self.assertTrue(any("not valid JSON" in warning for warning in json.loads(output.stdout)["warnings"])) def test_help_is_available(self): output = subprocess.run([sys.executable, str(SCRIPT), "--help"], capture_output=True, text=True) self.assertEqual(output.returncode, 0) self.assertIn("read-only", output.stdout.lower()) if __name__ == "__main__": unittest.main()
-
-
README.md 2.2 KB
# react — Build and diagnose React applications ## Why Install This Skill React projects accumulate framework-specific failure modes: hooks that resynchronize unnecessarily, stale requests that overwrite newer data, routes that break under a subpath, and Vite environment values accidentally shipped to browsers. This skill gives your agent a focused operating loop for those problems. After installation, your agent can inspect a React/Vite project safely, make component and state changes that fit its existing conventions, protect accessible interaction states, and verify the result with the project's own checks. It also includes a read-only doctor for quick diagnostics without installing dependencies or exposing environment values. ## What You Get | Directory | Purpose | |---|---| | `SKILL.md` | React-specific implementation workflow, guardrails, handoffs, and verification steps | | `references/component-and-state.md` | Component boundaries, hooks, effects, async state, and forms | | `references/vite-diagnostics.md` | Vite environment, build, asset-base, and deployment diagnostics | | `scripts/react-doctor.py` | Bounded Python diagnostic with human-readable or JSON output | | `scripts/test_react_doctor.py` | Offline tests for diagnostic behavior and safety guarantees | | `evals/evals.json` | Six substantive output-quality cases for React and Vite work | ## Quick Start ```bash python3 scripts/react-doctor.py --json . python3 scripts/react-doctor.py . ``` The doctor reads project files only. It does not install packages, run scripts, contact the network, or print environment values. ## Triggers Load this skill when working with React, JSX/TSX, hooks, React Router, Vite React configuration, React component/state implementation, or React build failures. Use it for a focused project diagnosis before editing. ## Requirements - Python 3.8+ for the bundled diagnostic and tests. - Node.js and the project's package manager for application builds and tests. - Existing React/Vite project files; no API key is required. - Use `frontend-engineering` for framework-agnostic frontend architecture, `playwright` for browser automation, and `web-accessibility` for dedicated accessibility audits. -
SKILL.md 5.5 KB
--- name: react description: >- Operate React applications as a named tool: inspect and diagnose React/Vite projects, design component boundaries and state flow, implement accessible responsive UI, and verify behavior with the project's tests. Use when a task explicitly involves React, JSX/TSX, React hooks, React Router, Vite React configuration, or React build failures. Do not use for framework-agnostic frontend strategy (route to frontend-engineering), browser automation (route to playwright), accessibility policy or audits (route to web-accessibility), or non-React mobile apps (route to mobile-development). license: MIT compatibility: >- The bundled diagnostic script uses Python 3.8+ standard library only. Running or building an application requires its repository package manager and Node.js. metadata: tags: react, jsx, tsx, vite, hooks, components, router, frontend source: https://react.dev/ --- # React Application Engineering Use this skill for the React-specific implementation layer. Preserve the project's existing React version, package manager, build scripts, styling conventions, and routing model unless the user asks for a migration. ## Operating loop 1. **Diagnose before editing.** Run `scripts/react-doctor.py --json [PROJECT]` and inspect `package.json`, source entry points, Vite config, TypeScript config, routes, and test scripts. The diagnostic is bounded and read-only. 2. **Define the component contract.** Identify the page/feature boundary, inputs and outputs, owned state, server state, loading/empty/error/success states, and side effects. Keep reusable components independent of route globals and avoid passing state through unrelated layers. 3. **Implement with explicit data flow.** Prefer local state for local behavior, context only for genuinely cross-cutting concerns, and the existing server state/cache solution for remote data. Keep effects for synchronization with external systems; derive values during render rather than storing duplicates. 4. **Keep UI resilient.** Render a useful loading, empty, error, and success experience. Cancel or ignore stale async work, handle aborts, and avoid setting state after an obsolete request. Preserve stable keys and avoid mutating props or state. 5. **Build for the browser.** Use semantic HTML, keyboard-operable controls, visible focus, responsive layout, and stable accessible names. For detailed accessibility requirements, load [web-accessibility](../web-accessibility/SKILL.md). 6. **Verify in layers.** Run the narrowest existing unit/component test, then lint/typecheck, then the production build. For browser-level flows use [playwright](../playwright/SKILL.md), not ad hoc browser automation. Report the exact commands and any environment-dependent checks that were skipped. ## React-specific rules - Hooks run unconditionally and in the same order on every render; never call them in branches, loops, event handlers, or nested functions. - Effects synchronize with external systems. Do not use an effect to calculate a value that can be derived from props/state, or to mirror props into state without a clear user-editing requirement. - Use functional updates when the next state depends on the previous state. Give list items stable keys from domain identity, not array indexes when the list can reorder, insert, or delete. - Treat event handlers as user intent and keep them separate from render-time computation. Disable or guard duplicate submissions and expose pending state. - Keep API response validation and transformation at the integration boundary; components should consume a typed, predictable view model. - Do not add a state library or router solely because it is popular. First map ownership and use the project's existing choices. - In Vite, expose only intentionally public variables using the project's documented prefix (normally `VITE_`); never put secrets in client bundles. Read [references/vite-diagnostics.md](references/vite-diagnostics.md) for environment, build, and deployment checks. ## Routing and handoffs - Component architecture, responsive implementation, performance budgets, and general frontend testing: [frontend-engineering](../frontend-engineering/SKILL.md). - Browser E2E authoring, locator choice, network interception, and Playwright runs: [playwright](../playwright/SKILL.md). - Semantic structure, keyboard/focus behavior, WCAG acceptance evidence, and accessibility audits: [web-accessibility](../web-accessibility/SKILL.md). - React Native, Expo, Android, or iOS implementation: [mobile-development](../mobile-development/SKILL.md). ## Reference routing | Load when | Reference | |---|---| | Choosing component boundaries, state ownership, effects, or async UI behavior | `references/component-and-state.md` | | Diagnosing Vite env exposure, dependency versions, build output, or deployment paths | `references/vite-diagnostics.md` | ## Included script `scripts/react-doctor.py` is a read-only, dependency-free diagnostic. Run `scripts/react-doctor.py --help` for options. It accepts a project directory, checks common React/Vite signals, and emits human-readable or bounded JSON output. It does not install packages, execute project scripts, access the network, or print environment values. ## Completion boundary Stop when the requested React change is implemented, the project's relevant checks have run, and remaining failures are reported with their command and root-cause evidence. Do not broaden a component task into a framework migration or an accessibility audit without explicit scope.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.