Skip to content
Skillv1.0.0

solid-js

SolidJS — fine-grained reactive UI library without a virtual DOM. Use when building high-performance UIs, choosing a React alternative with better reactivity primitives, or using SolidStart for full-s

by terminalskills(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from terminalskills/skills (skills/solid-js/SKILL.md). Install upstream with npx skills add terminalskills/skills --skill solid-js. Copyright stays with the author (Apache-2.0).

SolidJS

Overview

SolidJS is a declarative UI library that compiles JSX to real DOM operations — no virtual DOM, no diffing. Reactivity is fine-grained: only the exact DOM nodes that depend on changed data update. The result is near-native performance with a React-like authoring experience.

Installation

# New SolidJS project
npx degit solidjs/templates/ts my-app
cd my-app
npm install
npm run dev

# Or with Vite
npm create vite@latest my-app -- --template solid-ts

Reactivity Primitives

createSignal — Reactive State

import { createSignal } from "solid-js";

// Signals are getter/setter pairs
const [count, setCount] = createSignal(0);

// Read: call as function
console.log(count()); // 0

// Write: call setter
setCount(1);
setCount((prev) => prev + 1); // Updater function

// Signals with objects
const [user, setUser] = createSignal({ name: "Alice", age: 30 });
setUser((prev) => ({ ...prev, age: 31 }));

createEffect — Side Effects

import { createSignal, createEffect } from "solid-js";

const [name, setName] = createSignal("Alice");

// Runs immediately, then reruns whenever dependencies change
createEffect(() => {
  console.log("Name changed:", name());
  document.title = `Hello, ${name()}!`;
});

// Cleanup function
createEffect(() => {
  const id = setInterval(() => console.log(name()), 1000);
  return () => clearInterval(id); // Runs before next effect or on dispose
});

createMemo — Derived State

import { createSignal, createMemo } from "solid-js";

const [price, setPrice] = createSignal(100);
const [quantity, setQuantity] = createSignal(3);

// Computed value — only recalculates when dependencies change
const total = createMemo(() => price() * quantity());

console.log(total()); // 300
setPrice(120);
console.log(total()); // 360 — recalculated

Control Flow

import { Show, For, Switch, Match, Index } from "solid-js";

// Show — conditional rendering
<Show when={isLoggedIn()} fallback={<LoginForm />}>
  <Dashboard />
</Show>

// For — list rendering (efficient keyed updates)
<For each={items()}>
  {(item, index) => <div>{index()} - {item.name}</div>}
</For>

// Index — list rendering when items change in place (not reorder)
<Index each={items()}>
  {(item, index) => <div>{index} - {item().name}</div>}
</Index>

// Switch/Match — multi-branch conditional
<Switch fallback={<p>Unknown status</p>}>
  <Match when={status() === "loading"}><Spinner /></Match>
  <Match when={status() === "error"}><ErrorView /></Match>
  <Match when={status() === "success"}><DataView /></Match>
</Switch>

Stores — Complex State

import { createStore, produce } from "solid-js/store";

const [state, setState] = createStore({
  users: [] as { id: number; name: string; active: boolean }[],
  loading: false,
});

// Update nested properties
setState("loading", true);
setState("users", 0, "active", false);

// Immer-like mutations with produce
setState(
  produce((s) => {
    s.users.push({ id: 4, name: "Diana", active: true });
    s.loading = false;
  })
);

Resources — Async Data Fetching

import { createSignal, createResource, Suspense } from "solid-js";

// createResource — wraps async data fetching
async function fetchUser(id: number) {
  const res = await fetch(`/api/users/${id}`);
  if (!res.ok) throw new Error("User not found");
  return res.json();
}

function UserProfile() {
  const [userId, setUserId] = createSignal(1);

  // Refetches automatically when userId() changes
  const [user, { refetch, mutate }] = createResource(userId, fetchUser);

  return (
    <Suspense fallback={<p>Loading...</p>}>
      {/* user() is undefined while loading, the value when ready */}
      <Show when={user()} fallback={<p>Error loading user</p>}>
        {(u) => (
          <div>
            <h1>{u().name}</h1>
            <button onClick={refetch}>Refresh</button>
          </div>
        )}
      </Show>
    </Suspense>
  );
}

SolidStart — Full-Stack

SolidStart adds file-based routing, SSR, and server functions:

npm create solid@latest
# Choose: SolidStart, TypeScript

File structure:

src/
  routes/
    index.tsx         → /
    about.tsx         → /about
    users/
      index.tsx       → /users
      [id].tsx        → /users/:id
  app.tsx
// src/routes/users/[id].tsx
import { createAsync, useParams } from "@solidjs/router";
import { Show, Suspense } from "solid-js";
import { getUser } from "~/lib/users"; // server function

export default function UserPage() {
  const params = useParams();
  const user = createAsync(() => getUser(Number(params.id)));

  return (
    <Suspense fallback={<p>Loading...</p>}>
      <Show when={user()}>
        {(u) => (
          <article>
            <h1>{u().name}</h1>
            <p>{u().email}</p>
          </article>
        )}
      </Show>
    </Suspense>
  );
}
// src/lib/users.ts — server functions
"use server";

export async function getUser(id: number) {
  const res = await fetch(`https://api.example.com/users/${id}`);
  return res.json();
}

export async function createUser(data: { name: string; email: string }) {
  // Runs on the server only — safe to access DB
  return db.insert(users).values(data).returning();
}

Context (Dependency Injection)

import { createContext, useContext, type ParentComponent } from "solid-js";
import { createStore } from "solid-js/store";

const AuthContext = createContext<{ user: () => User | null; login: (u: User) => void }>();

export const AuthProvider: ParentComponent = (props) => {
  const [state, setState] = createStore<{ user: User | null }>({ user: null });
  const value = { user: () => state.user, login: (u: User) => setState("user", u) };
  return <AuthContext.Provider value={value}>{props.children}</AuthContext.Provider>;
};

export const useAuth = () => useContext(AuthContext)!;

Migrating from React

React SolidJS
useState(0) createSignal(0)
useEffect(() => {}, [dep]) createEffect(() => { dep(); })
useMemo(() => calc, [dep]) createMemo(() => calc())
useReducer createStore
useContext useContext (same API)
React.memo Not needed — no re-renders
key prop in lists Use <For> instead of map()
useRef createSignal or let el!: HTMLElement

Key differences:

  • Components run once — no "re-render" concept. Put reactive logic inside JSX or effects.
  • Access signals by calling themcount() not count.
  • Use <For> for lists — not .map() — for efficient keyed rendering.
  • Destructuring signals breaks reactivity — pass signals or use stores.

Guidelines

  • Never destructure signals: const { x } = state breaks reactivity. Use state.x or createMemo.
  • Use <For> instead of Array.map in JSX for efficient list rendering.
  • Components run once — initialize logic at the top level, not in callbacks.
  • Use createStore for objects/arrays that need fine-grained updates.
  • Use createResource for async data — it integrates with <Suspense> automatically.
  • createMemo is cached — prefer it over calling createEffect to compute derived values.
  • SolidStart "use server" functions run exclusively on the server — safe for DB access.

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/terminalskills-skills-solid-js/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

terminalskills-skills-solid-js.ocm.jsonjson
{
  "ocm": "1",
  "id": "terminalskills-skills-solid-js",
  "kind": "skill",
  "name": "solid-js",
  "description": "SolidJS — fine-grained reactive UI library without a virtual DOM. Use when building high-performance UIs, choosing a React alternative with better reactivity primitives, or using SolidStart for full-stack apps with SSR and server functions. Covers signals, effects, memos, stores, and migration patterns from React.",
  "publisher": "terminalskills",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "general"
    ],
    "tags": [
      "skill-md",
      "solidjs",
      "reactive",
      "signals",
      "performance",
      "frontend",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "SolidJS — fine-grained reactive UI library without a virtual DOM. Use when building high-performance UIs, choosing a React alternative with better reactivity primitives, or using SolidStart for full-stack apps with SSR and server functions. Covers signals, effects, memos, stores, and migration patterns from React."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/terminalskills/skills",
      "path": "skills/solid-js/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/terminalskills/skills/blob/HEAD/skills/solid-js/SKILL.md",
      "key": "terminalskills/skills/skills/solid-js/SKILL.md"
    },
    "compatibility": "SolidJS 1.x / 2.x. SolidStart 1.x. Requires Node.js 18+ for build tooling.",
    "license": "Apache-2.0"
  },
  "instructions": "# SolidJS\n\n## Overview\n\nSolidJS is a declarative UI library that compiles JSX to real DOM operations — no virtual DOM, no diffing. Reactivity is fine-grained: only the exact DOM nodes that depend on changed data update. The result is near-native performance with a React-like authoring experience.\n\n## Installation\n\n```bash\n# New SolidJS project\nnpx degit solidjs/templates/ts my-app\ncd my-app\nnpm install\nnpm run dev\n\n# Or with Vite\nnpm create vite@latest my-app -- --template solid-ts\n```\n\n## Reactivity Primitives\n\n### createSignal — Reactive State\n\n```typescript\nimport { createSignal } from \"sol",
  "cost": {
    "context_tokens": 1844
  }
}

Fetch it by URL: GET /api/v1/registry/terminalskills-skills-solid-js/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.