Answer SolidJS 2.0 API and prerelease-behavior questions, and write or edit SolidJS 2.0 code (solid-js 2.x / next / RC). Use for questions or implementation involving components, signals/effects/batching, async data/generators/actions and Loading, stores and nested store views, lazy SSR/hydration, server functions ("use server"), experimental server components/frames, or DOM code for solid-js 2.x or @solidjs/web. Not for Solid 1.x projects and not for migrating 1.x code (see solidjs-v2-migrat...
Scanned 9/5/2026
Install to Claude Code
npx -y skills add khmm12/solidjs-v2-skills --skill solidjs-v2 --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Solidjs V2?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/khmm12-solidjs-v2)More formats (shields.io, HTML) on the badges page.
---
name: solidjs-v2
description: Answer SolidJS 2.0 API and prerelease-behavior questions, and write or edit SolidJS 2.0 code (solid-js 2.x / next / RC). Use for questions or implementation involving components, signals/effects/batching, async data/generators/actions and Loading, stores and nested store views, lazy SSR/hydration, server functions ("use server"), experimental server components/frames, or DOM code for solid-js 2.x or @solidjs/web. Not for Solid 1.x projects and not for migrating 1.x code (see solidjs-v2-migration).
---
# SolidJS 2.0
Solid 2.0 is **not React** and **not Solid 1.x**. Both priors are the dominant
bug sources in generated code. When in doubt, distrust pattern-matching and
check `references/cheatsheet.md` (official, ships with the package) or the
installed typings in `node_modules`.
## Step 0 — confirm this is actually a v2 project
Check before applying anything below:
- `package.json`: `solid-js` major is `2` (e.g. `2.0.0-rc.x`), and/or
`@solidjs/web` is a dependency.
- `tsconfig.json`: `"jsxImportSource": "@solidjs/web"`.
If `solid-js` is `1.x` (imports like `solid-js/web`, `solid-js/store`), **stop —
these rules do not apply**; that's a Solid 1.x project. If the task is to
convert it, use the `solidjs-v2-migration` skill instead.
Prereleases drift: when docs and the installed package disagree, trust the typings in
`node_modules` (`solid-js`, `@solidjs/web`, `@solidjs/signals`).
## The ten rules that prevent most bugs
1. **Reads lag writes.** Updates apply on the next microtask:
`setCount(1); count()` still returns `0`. Synchronous point: `flush()`.
`batch()` does not exist.
2. **`createEffect` takes two functions** — `(compute, apply, options?)`.
Compute tracks and returns a value; apply does side effects (untracked) and
may return a cleanup. The 1.x single-callback form throws. `on()`,
`createComputed`, initial-value args: all gone.
3. **Never write signals/stores or invoke an action inside a reactive scope**
(memo, compute, component body) — throws in dev. Define actions there if
useful, but invoke/write from event handlers, effect callbacks, actions, or
`onSettled`. `untrack()` suppresses read tracking but does not exempt writes.
Derive instead of writing back.
4. **No top-level reactive reads in component bodies** and no destructured
props — warns, value goes stale. Read via `props.x` inside JSX / memos /
effect computes; `untrack(() => ...)` for deliberate one-shots.
5. **Props are values, not accessors.** Call site: `<X v={count()} />`, never
`<X v={count} />`. Child: `props.v`, never `function X({ v })`. This stays
reactive — the compiler turns `v={count()}` into `{ get v() { return count() } }`,
so reading `props.v` in the child re-runs `count()` in the child's tracking
scope. Passing the accessor (`v={count}` + `props.v()`) to "keep reactivity" is
a misconception: props have **always** been getters in Solid (1.x and 2.0
alike — value-passing didn't change), so it's unnecessary and just forces
every consumer to call a function.
6. **Async is just a computation**: `const user = createMemo(() => fetchUser(id()))`
— no `createResource`. Wrap consumers in `<Loading fallback={...}>`;
errors go to `<Errored>`. In-flight-change indicators: `isPending(() => user())`
— fires for changed inputs and `affects()` declarations; a bare `refresh()`
is normally quiet. `await refresh(source)` waits for the settled re-ask;
`until(predicate)` waits for a truthy live-source acknowledgement.
7. **Store setters take a draft**: `setStore(s => { s.a.b = 1; })` (produce is
the default). Store APIs (`createStore`, `reconcile`, `snapshot`…) are
exported from `solid-js` — `solid-js/store` does not exist.
8. **List rendering is `For` with keying modes** — `<Index>` is gone. Callback
shapes differ per mode (see references); `keyed={false}` gives
`(itemAccessor, plainIndex)`. Fixed-count rendering: `<Repeat>`.
9. **Lifecycle**: `onSettled(() => { ...; return cleanup; })` replaces
`onMount`/`onCleanup` for component-level setup-and-teardown. It's a leaf
owner — no primitives or `onCleanup` inside.
10. **Imports moved**: `@solidjs/web` for `render`/`hydrate`/`Portal`/`Dynamic`
(not `solid-js/web`); `jsxImportSource: "@solidjs/web"`; DOM attributes are
lowercase (`tabindex`); `class` takes object/array forms (`classList` is
gone); directives are `ref={factory(opts)}` (`use:` is gone).
## Reference routing
Read the file matching the task before writing code in that area:
| Task touches | Read |
|---|---|
| Quick API lookup, import list, full 1.x→2.0 footgun list | `references/cheatsheet.md` (official) |
| Signals, memos, split/render effects and paint timing, `createReaction`, batching/flush, lifecycle, ownership, dev diagnostics | `references/reactivity.md` |
| Data fetching, loading values, async iterator completion, Loading/Errored, isPending/latest/resolve/awaitable refresh/until, action call scope/errors, optimistic UI | `references/async-and-actions.md` |
| createStore, reconcile, projections, nested store-view structural tracking, compiler patch-driver boundary, snapshot/deep, merge/omit, storePath | `references/stores.md` |
| For/Repeat/Show/Switch/Reveal, dynamic/lazy components, lazy SSR/hydration identity, class/attributes/events/refs/directives, render entries | `references/control-flow-and-dom.md` |
| tsconfig, JSX types, import paths, Context typing, test setup | `references/typescript-setup.md` |
| Composed patterns: SWR query, optimistic mutations, selection projections, global state, demand-driven resources | `references/patterns.md` |
| Naming a primitive/composable (`create*` vs `use*`), cross-cutting conventions | `references/conventions.md` |
| `"use server"` directive, module/function wrappers, server-function addressing/invoke/live, respond/redirect/reload, GET/withMeta, fetch/prepareRequest, named single-flight, no-JS, getRequestEvent | `references/server-functions.md` |
| Experimental server components, frames, client slots/state preservation, `installServerComponents`, `serverFunctions: { components: true }` | `references/server-components.md` |
## Failure modes
- **App renders nothing / mount seems stuck** → pending async outside a
`Loading` boundary defers the root mount; check the console for
`ASYNC_OUTSIDE_LOADING_BOUNDARY`.
- **Dev throws/warns with a diagnostic code** (`REACTIVE_WRITE_IN_OWNED_SCOPE`,
`STRICT_READ_UNTRACKED`, …) → table of codes and fixes at the bottom of
`references/reactivity.md`. Fix the cause; never silence with `ownedWrite`
for app state.
- **Test asserts stale values** → missing `flush()` after writes, or reactive
code created without an owner (`createRoot` in tests).
- **An API from docs/examples doesn't exist** → prereleases drift; verify against
installed typings and prefer them over any doc, including these references.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!