a11y-fixes
Resolve axe-core accessibility violations reported by Vitest (test/a11y.ts), Playwright (.playwright/a11y.ts), or the code-audit-frontend agent's a11y bucket.…
Patterns and conventions for writing and editing React code, including components and hooks. Use this skill whenever writing or reviewing React components, hooks (useEffect, useCallback, useState), event handlers, or component extraction decisions. Also trigger when debugging
$ npx -y skills add gaia-react/gaia --skill react-code --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/react-codeContext preview
The summary Claude sees to decide when to auto-load this skill.
Patterns and conventions for writing and editing React code, including components and hooks. Use this skill whenever writing or reviewing React components, hooks (useEffect, useCallback, useState), event handlers, or component extraction decisions. Also trigger when debugging
name: react-code description: Patterns and conventions for writing and editing React code, including components and hooks. Use this skill whenever writing or reviewing React components, hooks (useEffect, useCallback, useState), event handlers, or component extraction decisions. Also trigger when debugging stale closures, infinite re-renders, or unnecessary re-renders caused by memoization issues, or when deciding whether to add a dependency, reach for a web-platform API (Intl, URL, crypto.randomUUID), or hand-roll a primitive. Also trigger when choosing a React 19 idiom, deciding between forwardRef and ref-as-prop, useContext and use(), or Context.Provider and the Context shorthand; when conditional rendering risks the && numeric-0 leak; or when tempted to reach for React's form Actions (useActionState, useFormStatus, useOptimistic) instead of React Router's form handling.
Write and edit React components, pages, routes, hooks, and forms following project conventions.
Before installing a package or hand-rolling a primitive, walk this ladder and stop at the first hit:
1. **Existing GAIA code**, a component, hook, or util already covers it (form inputs → Gate 2). 2. **Web platform**, a browser API or native element does the job: `Intl` (dates, numbers, lists, plurals), `URL` / `URLSearchParams`, `crypto.randomUUID()`, `structuredClone()`, `AbortController`, native `Array` / `Object` methods, `<dialog>`, modern CSS (`:has()`, container queries). 3. **Already-installed dependency**, check `package.json` before adding a sibling that does the same job. For component/hook traps Claude often hand-rolls (client-only/useHydrated, sse, debounce-fetcher), see the remix-utils decision map at `wiki/dependencies/remix-utils.md` before reinventing. 4. **New dependency**, only when 1-3 genuinely fall short; the added weight has to earn its place. 5. **Custom code**, last resort, kept minimal.
The largest real savings come from `Intl` over date/number-formatting libraries and native collection methods over `lodash`/`underscore` (already enforced by `you-dont-need-lodash-underscore`). Reaching for the platform replaces a needless dependency or bespoke widget; it never overrides accessibility, input validation, or an existing GAIA component (a wrapper exists for a reason).
Most hook bugs come from misidentifying the type of problem being solved. Before writing or editing hooks, run through these gate, it only applies when the relevant pattern is present in your changes.
**Before writing `useEffect`:**
1. Can I calculate this during render? → Derive inline or `useMemo`, no Effect needed. 2. Does this respond to a user action? → Put it in the event handler, no Effect needed. 3. Am I syncing state to other state? → Derive it; remove the redundant state, no Effect needed. 4. Am I notifying a parent of a state change? → Call both setters in the handler, no Effect needed. 5. Do I need to reset child state when a prop changes? → Use `key`, no Effect needed. 6. Am I synchronizing with an external system (browser API, third-party widget, network)? → Effect is appropriate here. Add cleanup. For data fetching, include an `ignore` flag.
**Before writing `useCallback`:**
Only use when the function is:
1. Passed as a prop to a `memo`-wrapped component 2. A dependency of `useEffect`, `useMemo`, or another `useCallback` 3. Passed to a child that uses it in a hook dependency array
If none apply, skip `useCallback`, it adds indirection without benefit.
**`useState` type inference:** Omit explicit type when inferable from the default value. Add types for unions or complex objects. For an absent initial value, prefer `undefined` over `null` (GAIA never-null): `useState<T>()` is already typed `T | undefined`.
**Before writing `<input>`, `<select>`, `<textarea>`, or `<input type="checkbox">`:**
| Native element | Use instead | | -------------------------------------- | ------------------------------------------------------------------------------- | | `<input type="text">` | `InputText` (`~/components/Form/InputText`) | | `<input type="email">` | `InputEmail` (`~/components/Form/InputEmail`) | | `<input type="password">` | `InputPassword` (`~/components/Form/InputPassword`) | | `<input type="checkbox">` (single) | `Checkbox` (`~/components/Form/Checkbox`) | | `<input type="checkbox">` (group) | `Checkboxes` (`~/components/Form/Checkboxes`), needs `options: Option[]` | | `<input type="radio">` / radio group | `RadioButtons` (`~/components/Form/RadioButtons`), needs `options: Option[]` | | `<select>` | `Select` (`~/components/Form/Select`), needs `name` + `options: SelectOption[]` | | `<textarea>` | `TextArea` (`~/components/Form/TextArea`), needs `name`; auto-resizes | | Date (year/month/day) | `YearMonthDay` (`~/components/Form/YearMonthDay`) | | Field with label + error + description | `Field` (`~/components/Form/Field`) |
**Exceptions (native OK):** `<input type="hidden">`, `<input type="file">`, `<input type="range">`.
`Select` requires `options: SelectOption[]` (`{label, value}`). Build this array (with `useMemo` if derived from translations/data) rather than inline `<option>` elements.
**CRITICAL, `@conform-to/zod`:** Always import from `/v4` subpath. The default export targets Zod v3 and causes a runtime error that typecheck/lint/build do NOT catch.
// BAD, runtime error
import {parseWithZod} from '@conform-to/zod';
// GOOD
impoClaude is raw power. GAIA is order and focus. The foundation that keeps Claude-shipped code production-grade as your team scales. The React frontend is handled. You build the rest of your app on top. Every convention enforced in code.
Repo: gaia-react/gaia
Resolve axe-core accessibility violations reported by Vitest (test/a11y.ts), Playwright (.playwright/a11y.ts), or the code-audit-frontend agent's a11y bucket.…
Resolve specific ESLint errors and warnings that appear in this project. Use when fixing lint failures, ESLint reported issues, or autofix conflicts (e.g.…
File a new tech-debt GitHub issue for an out-of-scope code-review finding, building the dedup key, checking for an existing open or declined-closed match, and…
Generate a comprehensive GAIA session handoff document, accomplishments, decisions, current state, open questions, so context can be cleared or compacted…
Restore context from the most recent GAIA session handoff and suggest the next action. Trigger on `/gaia-pickup` or natural-language asks like "pick up where…
Diagnose React render performance by driving a micro-interaction, capturing real renders, and surfacing memo-defeating reference instability with a recommended…