Migrate a Solid 1.x codebase, file, or component to SolidJS 2.0 (solid-js 2.x / next / RC). Use when converting code that imports solid-js/web, solid-js/store, createResource, Suspense, onMount, batch, or other 1.x APIs to the 2.0 equivalents. Not for writing new v2 code from scratch (see solidjs-v2).
Scanned 9/5/2026
Install to Claude Code
npx -y skills add khmm12/solidjs-v2-skills --skill solidjs-v2-migration --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Solidjs V2 Migration?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/khmm12-solidjs-v2-migration)More formats (shields.io, HTML) on the badges page.
---
name: solidjs-v2-migration
description: Migrate a Solid 1.x codebase, file, or component to SolidJS 2.0 (solid-js 2.x / next / RC). Use when converting code that imports solid-js/web, solid-js/store, createResource, Suspense, onMount, batch, or other 1.x APIs to the 2.0 equivalents. Not for writing new v2 code from scratch (see solidjs-v2).
---
# Migrate Solid 1.x → 2.0
Convert 1.x code to 2.0 in passes: mechanical first, then semantic, then
diagnostics-driven cleanup. The full rename/removal table with before/after
recipes is in `references/migration-map.md` — read it before starting; this
file is the workflow.
## Step 0 — establish the direction
- Source must be Solid 1.x (imports like `solid-js/web`, `solid-js/store`,
`createResource`, `Suspense`). Target version: whatever `solid-js@2.x` /
`@solidjs/web` prerelease the project declares (or the latest, if you're also
bumping `package.json`).
- Prereleases drift. The installed typings (`node_modules/solid-js/types`,
`@solidjs/web`) outrank docs and this skill's references when they disagree.
- Upgrade `solid-js`, `@solidjs/web`, and the Solid compiler integration
together. `babel-preset-solid` is replaced by `@solidjs/babel-plugin`; Vite
uses `@solidjs/vite-plugin` (native `@solidjs/compiler` by default).
## Pass 1 — mechanical (grep-and-replace, low judgement)
1. Dependencies: `solid-js@2.x`, add `@solidjs/web`, and replace
`babel-preset-solid` with matching `@solidjs/babel-plugin` (or use
`@solidjs/vite-plugin`).
2. `tsconfig.json`: `"jsxImportSource": "@solidjs/web"`.
3. Import paths and pure renames — tables at the top of
`references/migration-map.md`. Greppable: `solid-js/web`, `solid-js/store`,
`Suspense`, `SuspenseList`, `ErrorBoundary`, `mergeProps`, `splitProps`,
`unwrap`, `onMount`, `createSelector`, `Context.Provider`, `classList`,
`equalFn`, `getListener`.
Mind the non-1:1 renames: `Errored`'s fallback gets an error **accessor**
(`err()`), `splitProps` → `omit` inverts the result (rest-only), `merge` treats
`undefined` as an override, `onSettled` is a leaf owner.
## Pass 2 — semantic rewrites (per call site, by intent)
Work through `references/migration-map.md` sections in this order — each names
the decision to make:
1. **Effects**: single-callback `createEffect` → split `(compute, apply)`;
`on()` → compute phase; `initialValue` → default parameter; `onCleanup`
inside effects → returned cleanup.
2. **`createComputed`** → `createMemo` / split effect / `createSignal(fn)` —
pick by intent (derivation / side effect / writable derived).
3. **`batch`** → delete; add `flush()` only where code reads its own writes
synchronously.
4. **`createResource`** → async `createMemo` (or `createProjection` for keyed
collections) + `<Loading>`; `.loading`/`.error`/`refetch`/`mutate` each map
differently — see the table.
5. **Mutations**: ad-hoc flag flipping / `startTransition` → `action()` +
optimistic primitives + awaitable `refresh()` or `until()` live-source
acknowledgement.
6. **Stores**: `produce` wrappers → plain drafts; path setters → drafts (or
`storePath` compat); `reconcile` moves inside the draft; `createMutable` →
`createStore`.
7. **Lists**: `<Index>` → `<For keyed={false}>`; audit default `<For>`
callbacks — item is now raw, index is an accessor.
8. **DOM**: `use:` → ref factories; `on:`/`attr:`/`bool:`/`class:`/`style:`
namespaces → standard forms; `/*@once*/` → reactive or `defaultValue`;
camelCase attributes → lowercase.
9. **Context**: `.Provider` → context-as-component; delete `useX`-with-throw
wrappers (`useContext` now returns `T` and throws without Provider).
10. **Server functions**: old `.GET`/`.withOptions` call sites → declaration
wrappers, `prepareRequest`, or per-call `invoke`; audit module-level versus
function-level wrapper trust boundaries.
11. **`from`/`observable`** → async iterables / push-out effects.
## Pass 3 — run dev and fix diagnostics
2.0 ships structured dev diagnostics; the first dev run after migration is the
real review. Typical wave, in order of volume:
- `STRICT_READ_UNTRACKED` — top-level/destructured prop reads the old code
tolerated. Move reads into JSX/memos, or `untrack` deliberate one-shots.
- `REACTIVE_WRITE_IN_OWNED_SCOPE` (throws) — 1.x effects that write signals.
Rewrite as derivations or move writes to handlers/actions. `untrack()` is not
an exemption: it suppresses dependency tracking, not ownership.
- `ASYNC_OUTSIDE_LOADING_BOUNDARY` — async reads with no `<Loading>` ancestor;
add boundaries where fallback UI is wanted.
- `CLEANUP_IN_FORBIDDEN_SCOPE` — `onCleanup` inside `onSettled`; return the
cleanup instead.
Then run the test suite: assertions reading right after writes need `flush()`,
and reactive setups in tests need `createRoot`.
## Pass 4 — behavioral audit (no grep pattern)
The "Behavioral changes that need an audit" section of the map: synchronous
read-after-write assumptions, `undefined`-as-override in merges, forever-roots
needing `runWithOwner(null, ...)`.
## Failure modes
- **A 1.x API has no entry in the map** → check the installed typings before
inventing a replacement; some conveniences (e.g. `observable`,
`createDeferred`) intentionally have none — surface the gap rather than
papering over it.
- **App mounts blank after migration** → pending async outside `Loading`
defers the root mount (`ASYNC_OUTSIDE_LOADING_BOUNDARY` in console).
- **Migration of one file pulls in half the app** → migrate bottom-up (leaf
components first), keep passes 1–2 per-file but expect pass 3 diagnostics to
surface cross-file issues.
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!