Vercel React Best Practices
sanity-io/sanity
React and Next.js performance optimization guidelines from Vercel Engineering.
A skill your agent uses when building, reviewing or debugging a SolidJS app — signals, stores, effects, memos and resources, and JSX that compiles to real DOM with no virtual DOM.
$ npx skills add ericrisco/rsc-harness --skill solid-js -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install ericrisco/rsc-harness solid-js --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/ericrisco/rsc-harness.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/solid-js .claude/skills/solid-js && 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 "solid-js" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/solid-js into .claude/skills/solid-js/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "solid-js", 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/ericrisco/rsc-harness/tree/main/skills/solid-jsType 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 ericrisco/rsc-harness --skill solid-js -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install ericrisco/rsc-harness solid-js --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/solid-js .agents/skills/solid-js && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "solid-js" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/solid-js into .agents/skills/solid-js/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "solid-js", 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 ericrisco/rsc-harness --skill solid-js -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install ericrisco/rsc-harness solid-js --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/solid-js .cursor/skills/solid-js && 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 "solid-js" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/solid-js into .cursor/skills/solid-js/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "solid-js", 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/ericrisco/rsc-harness.git --path skills/solid-js--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 ericrisco/rsc-harness --skill solid-js -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install ericrisco/rsc-harness solid-js --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/solid-js .gemini/skills/solid-js && 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 "solid-js" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/solid-js into .gemini/skills/solid-js/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "solid-js", 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 ericrisco/rsc-harness solid-jsInstalls 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 ericrisco/rsc-harness --skill solid-js -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/solid-js .github/skills/solid-js && 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 "solid-js" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/solid-js into .github/skills/solid-js/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "solid-js", 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 ericrisco/rsc-harness --skill solid-js -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install ericrisco/rsc-harness solid-js --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/solid-js .opencode/skills/solid-js && 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 "solid-js" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/solid-js into .opencode/skills/solid-js/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "solid-js", 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.
solid-jsA skill your agent uses when building, reviewing or debugging a SolidJS app — signals, stores, effects, memos and resources, and JSX that compiles to real DOM with no virtual DOM.
Solid JS is an agent skill from ericrisco/rsc-harness. Use when building, reviewing or debugging a SolidJS app — signals, stores, effects, memos and resources, and JSX that compiles to real DOM with no virtual DOM. Covers the classic traps: a signal that does not update the UI, For versus Index, effect loops, components that run once, and props losing reactivity when destructured. NOT React's re-render model (that is react).
Its SKILL.md is about 3.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 8 other files, including scripts and reference files (for example `evals/README.md`, `evals/cases.yaml` and `references/reactivity-deep-dive.md`).
It sits in Frontend & Design, covering React components. It works with React, Vercel and TypeScript. The repository describes itself as: Your agent invents things because it has no memory, and can't touch your database because it has no arms. rsc is the meta-harness that gives it both, plus the trade to know the… The licence is MIT.
Read from SKILL.md and the folder at commit 92fde8f. 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.
Ships 1 file in scripts/ (Shell), which the agent can run.
Shell commands in SKILL.md call:
npmbashtscFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npm, 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.
Solid JS loads about 3.1k tokens when it runs, and up to ~4.8k if it reads all its reference files. Until then it costs about 96 tokens; SKILL.md has 908 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); the scripts in this folder are not scanned.
The full file from ericrisco/rsc-harness at commit 92fde8f, republished under its MIT licence (© ericrisco). 908 words, ~3,119 tokens.
.claude/skills/solid-js/SKILL.md (or your agent's skills folder). This skill also uses 5 other files; get the full folder from GitHub.One rule governs everything else: the component function runs ONCE. Reactivity does not live in re-running the body — it lives in the reads. You read state by calling a getter (count()), and Solid re-runs only the exact DOM expression or effect that read it. There is no virtual DOM and no reconciliation; JSX compiles straight to DOM nodes. If you carry React habits here (destructuring props, expecting the body to re-run, deriving state in an effect), reactivity breaks silently — the code runs, it just stops updating.
Versions: stable is solid-js 1.9.x (1.9.11/1.9.13 line). Solid 2.0 is in beta on the next npm tag with a new reactive core (@solidjs/signals), createAsync, and automatic batching. Default to 1.9.x APIs unless the task says 2.0; flag the divergence where it matters.
| Situation | Skill |
|---|---|
Solid signals/stores/effects/memos/resources, JSX-to-DOM, <For>/<Index> | this skill |
React useState/hooks/re-render model (the body re-runs) | react |
| Next.js routing, server actions, RSC | nextjs |
Svelte 5 $state/$derived runes (similar look, different compiler) | svelte |
Vue/Nuxt ref/reactive/computed | vue-nuxt |
| Astro island architecture / what ships to the client (can host a Solid island) | astro |
| Plain TypeScript questions with no Solid surface | ../typescript/SKILL.md |
| Deploying the built app (Vercel/SolidStart adapter) | ../vercel/SKILL.md |
React re-runs the component body on every state change; Solid runs it once and re-runs only the tracked reads. So the value is the call, not the variable.
// Bad — React reflex: treats `count` as a value, body assumed to re-run.
function Counter() {
const [count, setCount] = createSignal(0);
console.log("body ran"); // prints ONCE, ever
return <button onClick={() => setCount(count + 1)}>{count}</button>;
// ^ NaN: count is the getter fn, not a number
}
// Good — read by calling the getter; the JSX read is what re-runs.
function Counter() {
const [count, setCount] = createSignal(0);
return <button onClick={() => setCount((c) => c + 1)}>{count()}</button>;
// ^ tracked read
}Why: the body is setup that runs once. Only getter reads inside JSX, effects, or memos are tracked and re-executed. count is the accessor function; count() is its current value.
createSignal(initial) returns [getter, setter]. Read with getter(), write with setter(next) or setter(prev => next).
const [name, setName] = createSignal("Ada");
setName("Grace"); // replace
setName((n) => n + "!"); // update from previousDerived state is just a function — no API needed:
const [first, setFirst] = createSignal("Ada");
const [last, setLast] = createSignal("Lovelace");
const fullName = () => `${first()} ${last()}`; // re-reads on access, always freshReach for createMemo only when the computation is expensive or shared by many readers — it caches and re-runs only when its dependencies change:
const sorted = createMemo(() => [...items()].sort(byName)); // expensive: memoizeRule: derive with a plain () => … by default; promote to createMemo for cost/sharing. Why: a memo adds a reactive node; a plain function is free and recomputes lazily on read.
Props are a reactive proxy. Destructuring or assigning .x reads the value once at run-once time, freezing it.
// Bad — both snapshot a dead value; updates from the parent never arrive.
function Hi(props) { const { name } = props; return <p>{name}</p>; }
function Hi(props) { const name = props.name; return <p>{name}</p>; }
// Good — read inline, or wrap in an accessor to pass reactivity along.
function Hi(props) { return <p>{props.name}</p>; }
function Hi(props) { const name = () => props.name; return <p>{name()}</p>; }To split or default props while keeping reactivity, use splitProps / mergeProps — never the spread/destructure idiom:
import { splitProps, mergeProps } from "solid-js";
function Button(props) {
const merged = mergeProps({ variant: "primary" }, props); // reactive defaults
const [local, rest] = splitProps(merged, ["variant", "children"]);
return <button class={local.variant} {...rest}>{local.children}</button>;
}Why: splitProps/mergeProps return proxies that preserve getter tracking; { ...props } and const { x } = props collapse it to a one-time copy.
createSignal is for one value. Use createStore for nested objects or arrays so updates are fine-grained per path (only the components reading the changed leaf re-run), with no cloning of the whole tree.
import { createStore, produce } from "solid-js/store";
const [state, setState] = createStore({ user: { name: "Ada" }, todos: [] });
setState("user", "name", "Grace"); // path update — only name readers re-run
setState("todos", (t) => [...t, { id: 1, done: false }]); // append
setState("todos", 0, "done", true); // update one item field by index
setState(produce((s) => { s.todos[0].done = true; })); // mutate-style, still fine-grained// Bad — replacing the whole object kills path-level reactivity and re-renders everything.
setState({ user: { name: "Grace" }, todos: state.todos });
// Good — target the path that changed.
setState("user", "name", "Grace");Why: stores diff at the path you touch; whole-object replacement is a single coarse change that defeats the entire point of a store.
createEffect runs after render and re-runs when any signal it reads changes. It is for side effects (DOM, logging, subscriptions, network) — not for computing state.
createEffect(() => {
document.title = `Count: ${count()}`; // side effect, tracks count()
});
onMount(() => { // runs once after first render
const id = setInterval(tick, 1000);
onCleanup(() => clearInterval(id)); // before re-run AND on disposal
});
batch(() => { setA(1); setB(2); }); // one update pass instead of two (1.x; auto in 2.0)
const snapshot = untrack(() => raw()); // read without subscribingThe signature anti-pattern — deriving state by writing a signal inside an effect — causes an infinite loop and is the most common "Solid is broken" report:
// Bad — effect reads total(), writes total → re-triggers itself forever.
const [total, setTotal] = createSignal(0);
createEffect(() => setTotal(price() * qty()));
// Good — derive, don't store.
const total = createMemo(() => price() * qty()); // or: const total = () => price() * qty();Why: an effect that writes one of its own dependencies is a feedback loop. Derived values are reads, not writes.
Early return, bare &&, and .map() defeat tracking or leak falsy values. Use the components, which Solid can track and dispose precisely.
<Show when={user()} fallback={<Login />}>{(u) => <Profile user={u()} />}</Show>
<Switch fallback={<NotFound />}>
<Match when={state() === "loading"}><Spinner /></Match>
<Match when={state() === "ready"}><Data /></Match>
</Switch>
<Dynamic component={tagFor(kind())} {...props} /><For> vs <Index> is a real decision:
| Your list is… | Use | Why |
|---|---|---|
| Keyed objects that reorder/insert/remove | <For each={items()}>{(item) => …}</For> | keys by reference; DOM nodes move, not rebuild |
| Fixed-position rows, primitives, or inputs bound to the index | <Index each={items()}>{(item) => … item() …}</Index> | keys by position; item is an accessor (item()) |
// Bad — <For> with index-bound inputs: nodes move on reorder, inputs desync.
<For each={fields()}>{(f, i) => <input value={f.value} onInput={(e) => setField(i(), e)} />}</For>
// Good — <Index> when the position is the identity.
<Index each={fields()}>{(f, i) => <input value={f().value} onInput={(e) => setField(i, e)} />}</Index>Why: <For> tracks which value lives where (great for keyed data); <Index> tracks what's at slot N (great for fixed slots). Picking wrong rebuilds or desyncs nodes.
In 1.x use createResource; in 2.0 the standard primitive is createAsync. Both surface loading/error through <Suspense> and <ErrorBoundary>.
// 1.x
const [user] = createResource(userId, (id) => fetchUser(id)); // refetches when userId() changes
<ErrorBoundary fallback={(err) => <p>Failed: {err.message}</p>}>
<Suspense fallback={<Spinner />}>
<p>{user()?.name}</p>
</Suspense>
</ErrorBoundary>The 1.9→2.0 async migration (createAsync, automatic batching, @solidjs/signals) lives in references/reactivity-deep-dive.md.
npm create vite@latest my-app -- --template solid-ts # Vite + vite-plugin-solid + TS
cd my-app && npm install && npm run devRouting with @solidjs/router:
import { Router, Route, A } from "@solidjs/router";
function App() {
return (
<Router>
<Route path="/" component={Home} />
<Route path="/users/:id" component={UserPage} />
</Router>
);
}
// inside UserPage: const params = useParams(); params.id (reactive)
// nav links use <A href="…"> (not raw <a>) for client-side routingFor SSR, file-based routing, and server functions ("use server", query/action), reach for SolidStart (1.x stable; 2.0.0-alpha tracks Solid 2.0). The full router + SolidStart map is in references/router-and-start.md. Deploying the build → ../vercel/SKILL.md.
| Anti-pattern | Why it breaks | Do instead |
|---|---|---|
const { x } = props / const x = props.x | snapshots a non-reactive value at run-once | read props.x inline or const x = () => props.x |
Reading count instead of count() | passes the accessor function, not the value | call it: count() |
| Expecting the component body to re-run | it runs once; only tracked reads re-run | move reactive work into JSX / effect / memo |
Deriving state via createEffect that sets a signal | feedback loop / stale order | createMemo or a plain () => … |
<For> for index-bound inputs | nodes move on reorder, inputs desync | <Index> (keyed by position, item()) |
setStore(wholeNewObject) | one coarse change defeats fine-grained paths | setStore("path", …, value) / produce |
Early return null / cond && <X/> for conditionals | leaks falsy values, escapes tracking | <Show when={…} fallback={…}> / <Switch> |
{...props} to forward reactively | spread copies once, drops getters | splitProps / mergeProps |
If the project emits Solid components/JSX/config, run the gate:
bash scripts/verify.shIt detects the package runner from the lockfile, then runs tsc --noEmit → ESLint → Vitest → vite build. Missing tools are SKIPPED (yellow), not failed; it exits non-zero only on a real failure.
createRoot/getOwner/runWithOwner, on() explicit deps, createComputed/createRenderEffect, createSelector, store reconcile/produce, and the 1.9→2.0 migration.@solidjs/router surface (params, data loading, navigation, nested layouts) and a concise SolidStart 1.x map.© ericrisco, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 5 other files (scripts, references) in skills/solid-js of ericrisco/rsc-harness.
Open the folder on GitHubat commit 92fde8f
Solid JS 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 |
|---|---|---|---|---|---|---|
| Solid JS this skillericrisco/rsc-harness | 156 | — | ~3.1k | Automated safety check: Pass | MIT | |
| Vercel React Best Practicessanity-io/sanity | 6.4k | 130 repos | ~1.6k | Automated safety check: Pass | MIT | |
| React Render Types CompositionHorusGoul/eslint-plugin-react-render-types | 111 | — | ~1.1k | Automated safety check: Pass | MIT | |
| Safe Element Comparisonseasonedcc/remix-forms | 514 | — | ~1.8k | Automated safety check: Pass | MIT | |
| React Best Practicesryokun6/ryos | 1.3k | — | ~2k | Automated safety check: Pass | MIT | |
| Frontend Typescript Rulesshinpr/ai-coding-project-boilerplate | 232 | — | ~1.7k | Automated safety check: Pass | MIT |
sanity-io/sanity
React and Next.js performance optimization guidelines from Vercel Engineering.
HorusGoul/eslint-plugin-react-render-types
Composition patterns for building React components with @renders type annotations from eslint-plugin-react-render-types.
seasonedcc/remix-forms
Maintain element type comparison safety in remix-forms. An agent skill from seasonedcc/remix-forms.
ryokun6/ryos
React performance optimization guidelines from Vercel Engineering (vercel-labs/agent-skills).
shinpr/ai-coding-project-boilerplate
Applies React/TypeScript type safety, component design, and state management rules.
gambitph/Stackable
React performance optimization guidelines from Vercel Engineering.
ericrisco/rsc-harness
A skill your agent uses when designing or analyzing a controlled experiment — falsifiable hypothesis, sample size from an MDE, reading significance/CI/power, CUPED, or rescuing tests that won't go…
ericrisco/rsc-harness
A skill your agent uses when making a web UI conform to WCAG 2.2 Level AA — axe-core or Lighthouse a11y violations, keyboard operability, focus management, ARIA roles/names/live regions, contrast…
ericrisco/rsc-harness
A skill your agent uses when running or fixing paid acquisition on Google or Meta — campaign structure (Performance Max, Demand Gen, Search, Advantage+), platform-fit creative, budget/scaling rules…
ericrisco/rsc-harness
A skill your agent uses when measuring whether an LLM or agent system actually got better and gating merges on it: golden sets, fixing an inflated LLM-as-judge, scoring RAG (faithfulness, contextual…
ericrisco/rsc-harness
A skill your agent uses when a creative goal must become a finished media file: pick and order generative-media models per modality — AI voiceover, image-to-video clips, score — then glue them with…
ericrisco/rsc-harness
A skill your agent uses when instrumenting product or web analytics — GA4/PostHog SDK wiring, event taxonomy, funnels, double-counted events, consent gating, PII scrubbing.
Works with
Categories
A skill your agent uses when building, reviewing or debugging a SolidJS app — signals, stores, effects, memos and resources, and JSX that compiles to real DOM with no virtual DOM. Solid JS is an agent skill from ericrisco/rsc-harness. Use when building, reviewing or debugging a SolidJS app — signals, stores, effects, memos and resources, and JSX that compiles to real DOM with no virtual DOM.
Solid JS fits situations like: debugging a SolidJS app — signals; memos and resources; JSX that compiles to real DOM with no virtual DOM.
Run `npx skills add ericrisco/rsc-harness --skill solid-js -a claude-code`. Or copy the skill folder (skills/solid-js in ericrisco/rsc-harness) into .claude/skills/solid-js in your project. Claude Code loads it when a task matches its description.
Run `npx skills add ericrisco/rsc-harness --skill solid-js -a codex`. Or copy the skill folder (skills/solid-js in ericrisco/rsc-harness) into .agents/skills/solid-js 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 ericrisco/rsc-harness --skill solid-js -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/solid-js, .gemini/skills/solid-js, .github/skills/solid-js and .opencode/skills/solid-js in your project.
Going by SKILL.md and its folder, Solid JS needs a shell for the scripts in its folder and the command-line tools its instructions call (npm, bash and tsc). Our summary lists: Node.js; A Bash shell.
SKILL.md contains no URLs. Its commands use npm, 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. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Solid JS is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.1k 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. Its references folder adds about 1.6k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Solid JS: Vercel React Best Practices (sanity-io/sanity, 6.4k stars), React Render Types Composition (HorusGoul/eslint-plugin-react-render-types, 111 stars), Safe Element Comparison (seasonedcc/remix-forms, 514 stars) and React Best Practices (ryokun6/ryos, 1.3k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
ericrisco (a GitHub user) maintains it in ericrisco/rsc-harness, which has 156 GitHub stars. The repository holds 229 skills in this directory. The repository was last updated on October 6, 2026.
Source: ericrisco/rsc-harness on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.