No Use Effect
mattiacerutti/supernova
Enforce the no-useEffect rule when writing or reviewing React code.
Promote a duplicated React/JSX template-local component into the shared @asyncapi/generator-components package.
$ npx skills add asyncapi/generator --skill migrate-component -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install asyncapi/generator migrate-component --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/asyncapi/generator.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/migrate-component .claude/skills/migrate-component && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "migrate-component" agent skill from https://github.com/asyncapi/generator/tree/master/.claude/skills/migrate-component into .claude/skills/migrate-component/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate-component", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/asyncapi/generator/tree/master/.claude/skills/migrate-componentType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add asyncapi/generator --skill migrate-component -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install asyncapi/generator migrate-component --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/asyncapi/generator.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/migrate-component .agents/skills/migrate-component && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "migrate-component" agent skill from https://github.com/asyncapi/generator/tree/master/.claude/skills/migrate-component into .agents/skills/migrate-component/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate-component", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add asyncapi/generator --skill migrate-component -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install asyncapi/generator migrate-component --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/asyncapi/generator.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/migrate-component .cursor/skills/migrate-component && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "migrate-component" agent skill from https://github.com/asyncapi/generator/tree/master/.claude/skills/migrate-component into .cursor/skills/migrate-component/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate-component", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/asyncapi/generator.git --path .claude/skills/migrate-component--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add asyncapi/generator --skill migrate-component -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install asyncapi/generator migrate-component --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/asyncapi/generator.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/migrate-component .gemini/skills/migrate-component && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "migrate-component" agent skill from https://github.com/asyncapi/generator/tree/master/.claude/skills/migrate-component into .gemini/skills/migrate-component/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate-component", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install asyncapi/generator migrate-componentInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add asyncapi/generator --skill migrate-component -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/asyncapi/generator.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/migrate-component .github/skills/migrate-component && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "migrate-component" agent skill from https://github.com/asyncapi/generator/tree/master/.claude/skills/migrate-component into .github/skills/migrate-component/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate-component", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add asyncapi/generator --skill migrate-component -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install asyncapi/generator migrate-component --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/asyncapi/generator.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/migrate-component .opencode/skills/migrate-component && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "migrate-component" agent skill from https://github.com/asyncapi/generator/tree/master/.claude/skills/migrate-component into .opencode/skills/migrate-component/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate-component", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
migrate-componentPromote a duplicated React/JSX template-local component into the shared @asyncapi/generator-components package.
Migrate Component is an agent skill from asyncapi/generator. Promote a duplicated React/JSX template-local component into the shared @asyncapi/generator-components package. Use this skill whenever the user asks to "migrate", "move", "promote", "extract", "share", or "consolidate" a component into generator-components (or shared components / the components package). Also trigger for phrases like "it's used in multiple templates now, let's share it" or "avoid duplication across clients". Do not fire for unrelated React refactors or for moving code between apps/.
Its SKILL.md is about 3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Development, covering React components and Refactoring. It works with React and Node.js. The repository describes itself as: Use your AsyncAPI definition to generate literally anything. Markdown documentation, Node.js code, HTML documentation, anything! The licence is Apache-2.0.
12 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit ab1f79a. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
npmgitturboFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npm and git, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Migrate Component loads about 3k tokens when it runs. Until then it costs about 131 tokens; SKILL.md has 1,198 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from asyncapi/generator at commit ab1f79a, republished under its Apache-2.0 licence (© asyncapi). 1,198 words, ~2,950 tokens.
.claude/skills/migrate-component/SKILL.md (or your agent's skills folder).You are migrating a duplicated React/JSX template-local component out of packages/templates/clients/<protocol>/<lang>[/<framework>]/components/ (the <framework> segment is present for stack-specific templates like java/quarkus, omitted for single-stack languages like python) into the shared packages/components/src/components/ package.
Important: Always edit
src/files. Thelib/directory is generated at publish time by Babel — never edit files there.
The user has named the component to migrate, e.g. "migrate HandleError". If they did NOT name one, ask which component.
Use the Glob tool with pattern packages/templates/clients/**/components/<Component>.js to find all template-local copies of this component.
Decide based on the result count:
| Result count | Action |
|---|---|
| 0 | Stop and report "no template files found" — nothing to promote. |
| 1 | Report "only one template uses this component; CLAUDE.md section 4.5 recommends 2+ before promotion" and prompt the user via AskUserQuestion: continue anyway? |
| 2+ | Continue automatically — threshold satisfied. |
The 1-template case is the only judgment call — do not stop unilaterally; let the user make the call.
Use the Glob tool with pattern packages/components/src/components/<Component>.js — if it returns a result, stop and report that the component already exists in the shared package.
Before touching any files, work through these three steps in order. Each produces an artifact the execution steps consume directly:
The Glob results from precondition 1 are the canonical list — call it "the template files" in subsequent steps. Every later step (read sources, delete files, update imports) refers back to these exact paths. Echo the list back to the user as a fenced block so it stays visible; do not re-run Glob.
Read every path in the template files — one read per file, no skipping. For each, record one row in a markdown table:
| File | Props (with defaults) | Render shape | Indent | newLines |
|---|---|---|---|---|
…/javascript/.../<Component>.js | { methodName, methodParams = ['msg'] } | <Text>…</Text> | 2 | 1 |
…/python/.../<Component>.js | { methodName, methodParams = ['self','msg'], preExecutionCode } | <Text>…</Text> | 4 | 2 |
…/dart/.../<Component>.js | { methodName } | <MethodGenerator … /> | 2 | 1 |
This table is the source of truth for the next two research steps. Print it back to the user.
The shared component's props are the union of props across the template files:
Worked example (using the table above):
// Per-copy props:
// javascript → { methodName, methodParams = ['msg'] }
// python → { methodName, methodParams = ['self','msg'], preExecutionCode }
// dart → { methodName }
//
// Union → { methodName, methodParams, preExecutionCode }
// methodName → required (in every copy)
// methodParams → optional, ['msg'] (JS/Dart omit; Python overrides at the call site)
// preExecutionCode → optional, '' (only Python uses it; default is a no-op for JS/Dart)
export function <Component>({
methodName,
methodParams = ['msg'],
preExecutionCode = '',
}) { /* … */ }Python's consuming template then renders <<Component> methodName='onMessage' methodParams={['self','msg']} preExecutionCode='…' />; JS/Dart pass only what they need.
Choose the abstraction shape based on the table and signature:
MethodGenerator with a websocket<X>Config map. Use when per-language differences are mostly method-body strings (the config object holds the language-specific logic; the component itself is thin). See packages/components/src/components/RegisterErrorHandler.js.Text code blocks. Use when the rendering structure itself varies across languages (different indentation, different block shapes, framework sub-keys). See packages/components/src/components/QueryParamsVariables.js.Execute strictly in this order; each step must succeed before the next.
Create packages/components/src/components/<Component>.js using the signature and abstraction shape from research step 3.
Two things to enforce (everything else — named export, body code, imports, EOF newline — copy from the canonical example for your chosen shape):
@typedef for the Language union, @param for every prop in the research step 3 union (matching required/optional/defaults exactly), @returns {JSX.Element}, and a @example block. This is what jsdoc2md publishes to apps/generator/docs/api_components.md in step 9; missing or malformed tags produce an empty diff there.language/framework (or any prop with a supported set), throw using helpers from packages/components/src/utils/ErrorHandling.js. Use unsupportedLanguage(language, supportedList) for the language prop; use unsupportedFramework(language, framework, supportedList) when the component also accepts a framework prop (e.g. java/quarkus). See QueryParamsVariables.js for the full pattern.Edit packages/components/src/index.js: append one line export { <Component> } from './components/<Component>';.
Create packages/components/test/components/<Component>.test.js. Test cases come directly from the artifacts of research steps 2 and 3:
(language, framework?) pair). Pass the per-language props from that row.undefined leaks in the snapshot.npm run components:test -- -uOutput: packages/components/test/components/__snapshots__/<Component>.test.js.snap. Open it and sanity-check that the rendered output looks like what each language template emits today. The real correctness check happens in step 8 — git diff on the regenerated per-client integration snapshots.
For each path in "the template files" (research step 1):
git rm <path>packages/templates/clients/<protocol>/<lang>[/<framework>]/test/components/<Component>.test.js (same <lang>[/<framework>] segments as the source file — e.g. java/quarkus/test/components/…): git rm it and its .snap.Do not re-run Glob — the list from research step 1 is canonical.
For each path in "the template files" (research step 1), find the file that imported it. Use the Grep tool with pattern from './<Component>' scoped to that file's template root — the directory immediately above components/, which is <lang>/ for single-stack languages or <lang>/<framework>/ for stack-specific ones (e.g. packages/templates/clients/websocket/python/ or packages/templates/clients/websocket/java/quarkus/).
In each match:
<Component> to the existing @asyncapi/generator-components import (match the file's existing order convention; alphabetical not required).<<Component> /> JSX usage, pass the props from that language's row in research step 2's table plus language='<lang>'. The rendered output must be identical to what the deleted local file emitted — that's what keeps the integration snapshot churn minimal in step 7.Example (using the worked example from research step 3):
// JS template — methodParams default matches the table, so only pass required props.
<<Component> language='javascript' methodName='onMessage' />
// Python template — override per-language values from the table.
<<Component>
language='python'
methodName='on_message'
methodParams={['self', 'msg']}
preExecutionCode={'...'}
/>
// Dart template — only methodName per the table.
<<Component> language='dart' methodName='onMessage' />Run from the integration-test package — much faster than repo root since it skips the rest of the pipeline:
cd packages/templates/clients/<protocol>/test/integration-test && npm run test:updateOr to update a single client: cd packages/templates/clients/<protocol>/test/integration-test && npm run test:<lang>:update
Rebuilds __snapshots__/integration.test.js.<lang>.snap (one per client).
git diff is the migration's correctness check — the new snapshots vs. the committed ones tell you whether the migration changed any rendered output:
git diff packages/templates/clients/<protocol>/test/integration-test/__snapshots__/Expect modest whitespace/indent churn. Large semantic diffs (different method names, missing lines, body content changes) mean step 1 (component implementation) or step 6 (consumer props) is wrong → fix the offending step, then re-run step 4 (component snapshot) and steps 7–8 (integration snapshots + diff). Skip steps 2/3/5/6 unless they're what you're fixing.
apps/generator/docs/api_components.md is a committed jsdoc2md artifact and CLAUDE.md section 2.4 requires it be regenerated in the same PR as any public-signature change:
turbo run docs --filter=@asyncapi/generator-componentsThen git diff apps/generator/docs/api_components.md and commit alongside the source changes. Empty diff = JSDoc tags in step 1 are missing or malformed → fix and rerun.
From repo root:
npm run components:test — passes.npm run templates:test — passes (the integration snapshot is now in sync).npm run lint — passes.packages/components/src/components/RegisterErrorHandler.js.packages/components/src/components/QueryParamsVariables.js.packages/components/test/components/RegisterErrorHandler.test.js.packages/components/src/utils/ErrorHandling.js.© asyncapi, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .claude/skills/migrate-component of asyncapi/generator.
Open the folder on GitHubat commit ab1f79a
Migrate Component next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Migrate Component this skillasyncapi/generator | 1.1k | — | ~3k | Automated safety check: Pass | Apache-2.0 | |
| No Use Effectmattiacerutti/supernova | 187 | 2 repos | ~1.7k | Automated safety check: Pass | MIT | |
| React Best Practicesshapeshift/web | 206 | 1 repos | ~2k | Automated safety check: Pass | MIT | |
| Project Form PatternsAkaraChen/aghub | 272 | — | ~1.1k | Automated safety check: Pass | MIT | |
| React Performanceaffaan-m/ECC | 274k | 1 repos | ~4.5k | Automated safety check: Pass | MIT | |
| Feature Archpproenca/dot-skills | 214 | — | ~2k | Automated safety check: Pass | MIT |
mattiacerutti/supernova
Enforce the no-useEffect rule when writing or reviewing React code.
shapeshift/web
Comprehensive React and Next.js performance optimization guide with 40+ rules for eliminating waterfalls, optimizing bundles, and improving rendering.
AkaraChen/aghub
Form implementation guidance for the aghub desktop app. An agent skill from AkaraChen/aghub.
affaan-m/ECC
React and Next.js performance optimization patterns adapted from Vercel Engineering's React Best Practices (https://github.com/vercel-labs/agent-skills).
pproenca/dot-skills
React feature-based architecture guidelines for scalable applications.
pproenca/dot-skills
React 19/19.2 modern patterns for concurrent rendering, Server Components, actions, ref-as-prop, document metadata, resource hints, hooks, and memoization — plus a category-major review/refactor…
asyncapi/generator
A skill your agent uses when editing, adding, or reviewing any file under .github/workflows/, or when a CI step installs a CLI tool (npm i -g, npx, pipx, uses: /setup-).
asyncapi/generator
Port a component or feature that already exists in one protocol client template to sibling clients under packages/templates/clients/<protocol/ that are missing it.
Categories
Promote a duplicated React/JSX template-local component into the shared @asyncapi/generator-components package. Migrate Component is an agent skill from asyncapi/generator. Promote a duplicated React/JSX template-local component into the shared @asyncapi/generator-components package.
Migrate Component fits situations like: the user asks to migrate; consolidate a component into generator-components (or shared components / the components package); phrases like its used in multiple templates now; avoid duplication across clients.
Run `npx skills add asyncapi/generator --skill migrate-component -a claude-code`. Or copy the skill folder (.claude/skills/migrate-component in asyncapi/generator) into .claude/skills/migrate-component in your project. Claude Code loads it when a task matches its description.
Run `npx skills add asyncapi/generator --skill migrate-component -a codex`. Or copy the skill folder (.claude/skills/migrate-component in asyncapi/generator) into .agents/skills/migrate-component in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add asyncapi/generator --skill migrate-component -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/migrate-component, .gemini/skills/migrate-component, .github/skills/migrate-component and .opencode/skills/migrate-component in your project.
Going by SKILL.md and its folder, Migrate Component needs the command-line tools its instructions call (npm, git and turbo). Our summary lists: Python 3.
SKILL.md contains no URLs. Its commands use npm and git, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Migrate Component is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Migrate Component: No Use Effect (mattiacerutti/supernova, 187 stars), React Best Practices (shapeshift/web, 206 stars), Project Form Patterns (AkaraChen/aghub, 272 stars) and React Performance (affaan-m/ECC, 274k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
asyncapi (a GitHub organization) maintains it in asyncapi/generator, which has 1,080 GitHub stars. The repository holds 3 skills in this directory. The repository was last updated on October 5, 2026.
Source: asyncapi/generator on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.