Code & Development

SolidJS in 2026: Why fine-grained reactivity is outperforming the Virtual DOM

SolidJS redefines frontend performance in 2026 by ditching the Virtual DOM for fine-grained reactivity, ensuring faster updates and efficient code.

SolidJS in 2026: Why fine-grained reactivity is outperforming the Virtual DOM

Technical Guide · Framework · SolidJS · Jun 2026 v1.9.13 stable · 2.0 Beta active


TL;DR

  • SolidJS does not use Virtual DOM. Each signal is connected directly to the DOM node it controls. When the state changes, only that node updates — no tree comparison, no component re-render.

  • The core weighs 7.6KB gzipped. React + ReactDOM are ~45KB.

  • Components execute only once. Not on every state change — only at mount.

  • In 2026, Solid 2.0 Beta brings async as a first-class primitive: pass a Promise to a createMemo and the reactive graph handles the rest.

  • LLM SDKs (Vercel AI SDK, Genkit, Anthropic SDK) are pure TypeScript — they work in Solid just like in Next.js. What doesn't work are React-specific UI hooks (useChat, useCompletion).

  • npm downloads: ~2.4M/week, ~60% year-over-year growth. Job market: minimal — specialists, not generalists.


Why this framework matters — and when it doesn't

In 2026, the question is no longer whether the Virtual DOM works, but whether the cost of reconciliation is still acceptable for your application. Choosing a frontend framework transcends syntax; it is a decision about which mental model will guide your team for the coming years.

The Virtual DOM was a clever solution to a real problem: how to update the UI without touching the DOM manually? React responded with an in-memory copy of the interface, tree comparison, and applying the differences. It worked. It worked so well that it became the industry default for a decade.

SolidJS answered the same question differently. Instead of building and comparing trees, it connects each piece of state directly to the DOM node that displays it. When the state changes, the node updates. There is no tree to compare because there is never a copy — there is only the connection.

The difference is not cosmetic. It is architectural. And in 2026, with Solid 2.0 in mature beta and the stable version at 1.9.13, the question is no longer "does this work?" — it is "when is it worth the switch?"

Ryan Carniato, creator of SolidJS and now Principal Engineer for Open Source at Netlify, spent over a decade refining the framework's reactive model. It is not an experiment — it is a philosophy tested in production. In 2026, this philosophy influences Angular, Vue 3, and even the direction of the React compiler.

"Fine-grained reactivity is not premature optimization. It is not paying for what you don't use."


The ecosystem in numbers — Jun 2026

Metric

Value

Weekly npm downloads

~2.4M

GitHub stars

35K+

Core gzipped

7.6KB

Year-over-year growth

~60%

SolidJS in 2026 occupies a fascinating position in the JavaScript ecosystem. It may not be the most popular framework, but it is likely the most influential of the last five years. The signals paradigm it pioneered is now the foundation of Angular's reactivity, the philosophical basis of Vue's system, the competitive pressure behind the React compiler, and a candidate for inclusion in the JavaScript language itself via TC39.

⚠️ Honest trade-off: The SolidJS ecosystem is still young. UI libraries are limited, most React libraries do not have a port for Solid, and community resources are scarce compared to React — fewer tutorials, fewer answers on Stack Overflow, fewer production-tested patterns for edge cases. The presence in the job market is minimal. Evaluate if the libraries you need exist before committing.


The three primitives that replace all the magic

Learn these three and you have learned the framework. Everything else is built on top of them.

SolidJS Primitives
Signal
State source

Getter e setter que rastreiam automaticamente os consumidores sem arrays de dependência.

Memo
Derived value

Calculado de forma preguiçosa, atualiza somente quando necessário.

Effect
Side effect

Executa interações externas em resposta a mudanças reativas.

Three essential concepts to understand the framework

Primitive 01 — Signal

The source of state. A getter and a setter. The detail that matters: it automatically tracks who reads it. No dependency arrays — the runtime detects consumers during execution.

Primitive 02 — Memo

Derived, lazy, and pure value. It recalculates only when something it depends on changes, and only when someone actually reads it. It is the useMemo of React, but without the manual array and without the stale closure trap.

Primitive 03 — Effect

The side effect. The only place allowed to touch the external world — DOM, network, console. It re-executes only when its inputs change. No useEffect, no deps list, no synchronization bug.

JSX
import { createSignal, createMemo, createEffect } from "solid-js";// 1. Signal: a origem do estadoconst [preco, setPreco] = createSignal(100);// 2. Memo: derivado, lazy — só recalcula quando lido e quando preco mudaconst comImposto = createMemo(() => preco() * 1.1);// 3. Effect: efeito colateral — SEM array de dependênciascreateEffect(() => {  console.log("Total com imposto:", comImposto());  // O Solid rastreou automaticamente que comImposto() foi lido aqui});// Componente — executa UMA vez, nunca re-renderizafunction Preco() {  return <p>{comImposto()}</p>; // só o nó de texto atualiza}

Key difference: The component in Solid executes only once. React calls the component function on every render. In Solid, only signals and effects re-execute — the component itself is executed only at mount, setting up the reactive connections.


Complex state with createStore

For nested objects and arrays, basic signals get verbose. The createStore uses Proxies to track property access in depth, maintaining fine-grained reactivity even in complex structures.

JSX
import { createStore, produce } from "solid-js/store";function TodoApp() {  const [state, setState] = createStore({    todos: [],    filtro: "todos",  });  const adicionarTodo = (texto) => {    setState(produce((s) => {      s.todos.push({ id: Date.now(), texto, feito: false });    }));  };  const toggleTodo = (id) => {    setState(      "todos",      (todo) => todo.id === id,      "feito",      (feito) => !feito    );    // Só o campo "feito" do item específico atualiza no DOM  };  return (    <ul>      {state.todos.map((todo) => (        <li onClick={() => toggleTodo(todo.id)}>{todo.texto}</li>      ))}    </ul>  );}

Async as a first-class citizen — Solid 2.0 Beta

The central change in Solid 2.0 is that async is now first-class. Computations can return Promises and the reactive graph handles suspension and resumption automatically.

JSX
// Solid 2.0 Beta: createAsync como primitivo padrãoimport { createAsync } from "@solidjs/router";function Perfil(props) {  // O grafo reativo cuida de suspensão e retomada  const usuario = createAsync(() => buscarUsuario(props.id));  return <h1>{usuario()?.nome}</h1>;  // Sem useState, useEffect, dependências manuais, try/catch}// ATENÇÃO Solid 2.0: leia o signal ANTES do awaitconst dobro = createMemo(async () => {  const c = count(); // ← leia aqui, ANTES do await  await delay(100);  return c * 2;      // ← não leia count() depois do await boundary});

⚠️ Mental model shift in 2.0: In Solid 2.0, if you define signals and immediately read from the system, you might not see what you expect because writes are still batched. Use flush() to observe the updated state in unit tests. Read the signal before any boundary await.


React vs. SolidJS: what the architectural difference means in practice

Criterion

React 19

SolidJS 1.9 / 2.0

Rendering model

Virtual DOM + diffing

Direct DOM via signals ✅

Component re-execution

On every state change

Only once ✅

Dependency array

Manual — source of bugs

Automatic — runtime tracks ✅

Bundle size

~45KB (react + react-dom)

~7.6KB core ✅ 6× smaller

JS Framework Benchmark

Top 10, but behind Solid

Close to vanilla JS ✅ 1st tier

Async (data fetching)

useEffect + useState or TanStack Query

createAsync / createResource (2.0 native)

Global state

Zustand / Redux / Context

Native createStore, global signals

npm downloads (jun/2026)

~50M/week (ecosystem)

~2.4M/week (+60% y/y)

Job market

Dominant

Minimal — specialists

Meta-framework

Next.js (mature, 11M/wk)

SolidStart 1.3 (stable, growing)


The five technical criteria

01 — Scalability

Solid's fine-grained reactivity scales sublinearly. In centralized store systems (NgRx standard), the cost of an update tends to O(n) — proportional to the number of subscribers. In nested observables (RxJS), it can reach O(n²). In signals, the cost approaches O(1): the update propagates only to the calculations that effectively depend on the changed signal.

For long lists and frequent updates, this is measurable. Companies like Radware reported Solid bundles of ~80KB compared to ~290KB for React for equivalent functionality. Jolt AI uses Solid on 6 platforms (web, VS Code, JetBrains, macOS, Windows, Linux) with 93% code reuse while maintaining a low memory footprint for embedded IDE environments.

The scalability limit is not in performance — it is in the ecosystem.

02 — Learning curve

JSX is familiar to those coming from React. The API feels familiar. The mental model, however, does not. Solid looks like React on the surface but is fundamentally different underneath. Those who learn Solid after React often go through a moment of disorientation: "why does my console.log inside the component only run once?" — because the component only executes once.

The curve rises especially with signals in asynchronous contexts. In Solid 2.0, if you expect a signal read to track after an await, you will have problems. Tracking happens synchronously.

For developers without a React background, the curve can be smoother: they don't carry the wrong habits. What takes weeks for those coming from React can take days for those coming from vanilla JS.

03 — Performance and throughput

The JS Framework Benchmark is the broadest indicator available. Solid consistently stays in the first tier, alongside Inferno and vanilla JS, above React, Vue, and Angular.

The gain does not come from heuristics or optimization: it comes from the model. No Virtual DOM, no reconciliation, no tree copying. The compiler transforms JSX into direct DOM operations at build time.

JSX
import { createSignal } from "solid-js";function Counter() {  const [count, setCount] = createSignal(0);  // Esta função executa UMA vez — não a cada clique  // Só o nó de texto com {count()} atualiza no DOM  return (    <button onClick={() => setCount(count() + 1)}>      Clicado {count()} vezes    </button>  );}// O que o compilador Solid gera (simplificado):// const button = document.createElement("button");// const text = document.createTextNode("");// createEffect(() => { text.data = `Clicado ${count()} vezes`; });// button.addEventListener("click", () => setCount(count() + 1));

04 — Latency and SSR

Solid supports SSR, streaming SSR, and Suspense. The compiler combined synchronous, streaming, and asynchronous SSR into the same output, with a non-reactive Async SSR approach that is simpler and faster. Reusing static strings in templates yields a 5–8% gain where there are many lines.

The latency perceived by the user is favored by the smaller bundle: 7.6KB of framework means faster Time-to-Interactive even before any content optimization.

05 — Community support

Ryan Carniato, currently Principal Engineer for Open Source at Netlify, has been developing Solid's reactive model for over a decade. The official Discord has an active core team. Version 1.9.13 was released in May 2026. SolidStart 1.3 is the stable meta-framework.

The biggest support limitation is not quality — it is quantity: if you get stuck on a specific edge case, there might not be a ready answer on Stack Overflow.


Use cases: where SolidJS really delivers

✅ Use SolidJS for

Real-time dashboards and visualizations: updates at 60fps — metric charts, orderbooks, IoT telemetry. Fine-grained reactivity updates only the DOM node of the value that changed, without re-rendering the entire panel.

Widgets embedded in other systems: the 7.6KB bundle makes Solid ideal for components that live inside pages that already have their own stack. Chat widget, video player, checkout form — without loading 45KB of external runtime.

Apps with strict performance requirements: 2D games in the browser, rich editors, tables with thousands of rows updating in real-time.

New projects with a team open to learning: JSX, TypeScript, Vite — everything is familiar. What changes is the mental model.

❌ Avoid when

The library you need does not exist for Solid: Rich text editors (Lexical, TipTap), animation libraries (Framer Motion), specific charting libraries — check first.

Priority is hiring or fast onboarding: the job market for SolidJS is minimal. If the plan includes hiring frontend devs quickly, React drastically reduces onboarding costs.


SolidStart: the meta-framework

SolidStart 1.3 is the Next.js equivalent for Solid: file-based routing, SSR, server functions, and form actions.

JSX
// src/routes/contato.tsx — SolidStart 1.ximport { createAsync, action, redirect } from "@solidjs/router";import { getContatos } from "~/lib/db";// Server function — roda só no servidorconst enviarMensagem = action(async (formData: FormData) => {  "use server";  const nome = formData.get("nome") as string;  await salvarMensagem({ nome, ts: Date.now() });  return redirect("/obrigado");});// Componente isomórfico — SSR + hidratação no clienteexport default function Contato() {  const contatos = createAsync(() => getContatos());  return (    <main>      <h1>Contato</h1>      <form action={enviarMensagem} method="post">        <input name="nome" required />        <button type="submit">Enviar</button>      </form>      <ul>        {contatos()?.map(c => <li>{c.nome}</li>)}      </ul>    </main>  );}

SolidJS with LLMs — chats, editorial pipelines, and agent loops

Why fine-grained reactivity matters for AI apps

Every LLM chat interface solves the same problem: a token arrives every few milliseconds via Server-Sent Events (SSE), and the UI needs to append it to the displayed text without redrawing anything around it.

React: Virtual DOM and Re-rendering

Each new token triggers a setState.

The component re-renders completely.

Virtual DOM diffs the entire string.

Applies differences to the DOM after reconciliation.

500 tokens generate 500 reconciliation cycles.

SolidJS: Fine-Grained Reactivity with Signals

Each new token updates a signal.

Only one text node in the DOM changes.

There is no complete re-rendering.

Targeted and efficient update.

Reduces processing in chat interfaces.

In React, each new token triggers a setState, the component re-renders, the Virtual DOM diffs the entire string and applies the difference. For 500 tokens in 30 seconds, that is 500 reconciliation cycles in the same open conversation.

In Solid, the new token updates a signal — a single text node in the DOM changes, with nothing else.

The same argument multiplies in editorial pipelines with multiple agents running in parallel, where each step (research, draft, review, SEO) emits tokens independently. Keeping the state of each step in separate signals means that the progress of one agent causes no cost to the others.


Chat with token-by-token streaming

JSX
import { createSignal, createEffect, For, onCleanup } from "solid-js";type Message = { role: "user" | "assistant"; content: string };function ChatLLM() {  const [mensagens, setMensagens] = createSignal<Message[]>([]);  const [streamAtual, setStreamAtual] = createSignal("");  const [carregando, setCarregando] = createSignal(false);  const enviar = async (texto: string) => {    setMensagens(m => [...m, { role: "user", content: texto }]);    setCarregando(true);    setStreamAtual("");    const res = await fetch("/api/chat", {      method: "POST",      body: JSON.stringify({ mensagens: mensagens() }),      headers: { "Content-Type": "application/json" },    });    const reader = res.body!.getReader();    const decoder = new TextDecoder();    while (true) {      const { done, value } = await reader.read();      if (done) break;      const chunk = decoder.decode(value, { stream: true });      for (const linha of chunk.split("\n\n")) {        if (!linha.startsWith("data: ")) continue;        const token = linha.slice(6);        if (token === "[DONE]") break;        // Signal acumula → APENAS o nó de texto do assistente atualiza        setStreamAtual(prev => prev + token);      }    }    setMensagens(m => [...m, { role: "assistant", content: streamAtual() }]);    setStreamAtual("");    setCarregando(false);  };  return (    <div class="chat">      <For each={mensagens()}>        {(msg) => (          <div class={`msg msg--${msg.role}`}>{msg.content}</div>        )}      </For>      {/* Só este nó de texto atualiza a cada token */}      {carregando() && <div class="msg msg--assistant streaming">{streamAtual()}</div>}      <input onKeyDown={(e) => e.key === "Enter" && enviar(e.currentTarget.value)} />    </div>  );}

Why it matters: setStreamAtual it is called hundreds of times per response. In React, each call re-renders the entire component — including the list of previous messages. In Solid, only the text node of the current streaming block updates.


Editorial pipeline with agent loop

A typical editorial pipeline chains agents: research → draft → editorial review → SEO → publication. Each step can take 10–60 seconds and emits tokens independently. Each agent has its own signal — completely isolated updates.

TYPESCRIPT
Pesquisa → Rascunho → Revisão → SEO → Publicar   ↓           ↓         ↓        ↓       ↓ signal     signal    signal   signal  signal   ↓           ↓         ↓        ↓       ↓DOM node   DOM node  DOM node DOM node DOM node

Each signal updates its own DOM node — no interference between steps.

JSX
import { createSignal, createMemo, Show } from "solid-js";type EtapaStatus = "idle" | "rodando" | "feito" | "erro";function PipelineEditorial() {  // Cada agente tem seu próprio signal — completamente isolados  const [pesquisa,  setPesquisa]  = createSignal({ tokens: "", status: "idle" as EtapaStatus });  const [rascunho,  setRascunho]  = createSignal({ tokens: "", status: "idle" as EtapaStatus });  const [revisao,   setRevisao]   = createSignal({ tokens: "", status: "idle" as EtapaStatus });  const [seo,       setSeo]       = createSignal({ tokens: "", status: "idle" as EtapaStatus });  // Memo derivado — só recalcula quando qualquer etapa muda  const progresso = createMemo(() => {    const etapas = [pesquisa(), rascunho(), revisao(), seo()];    return etapas.filter(e => e.status === "feito").length;  });  const rodarEtapa = async (    setter: (v: (prev: any) => any) => void,    endpoint: string,    payload: object  ) => {    setter(prev => ({ ...prev, status: "rodando" }));    const res = await fetch(endpoint, {      method: "POST",      body: JSON.stringify(payload),      headers: { "Content-Type": "application/json" },    });    const reader = res.body!.getReader();    const dec = new TextDecoder();    while (true) {      const { done, value } = await reader.read();      if (done) break;      // Apenas o signal desta etapa atualiza — os outros não são tocados      setter(prev => ({ ...prev, tokens: prev.tokens + dec.decode(value) }));    }    setter(prev => ({ ...prev, status: "feito" }));  };  const iniciarPipeline = async (tema: string) => {    await rodarEtapa(setPesquisa, "/api/agent/pesquisa",  { tema });    await rodarEtapa(setRascunho, "/api/agent/rascunho",  { pesquisa: pesquisa().tokens });    await rodarEtapa(setRevisao,  "/api/agent/revisao",   { rascunho: rascunho().tokens });    await rodarEtapa(setSeo,      "/api/agent/seo",       { texto:    revisao().tokens });  };  return (    <div class="pipeline">      <p>Etapas concluídas: {progresso()} / 4</p>      <button onClick={() => iniciarPipeline("IA generativa em 2026")}>Iniciar</button>      <Etapa titulo="🔍 Pesquisa"  dados={pesquisa()} />      <Etapa titulo="✍️ Rascunho"  dados={rascunho()} />      <Etapa titulo="📝 Revisão"   dados={revisao()}  />      <Etapa titulo="🔖 SEO"       dados={seo()}      />    </div>  );}

SolidJS vs. Next.js for apps with AI agents

LLM SDKs are framework-agnostic

LLM SDKs are pure TypeScript — they work in any JS environment. Vercel AI SDK (streamText, generateText, generateObject), Firebase Genkit, LangChain.js, Anthropic SDK, OpenAI SDK: all run in SolidJS, Next.js, SvelteKit, or Vanilla JS without modification.

What is React-specific are only the UI hooksuseChat, useCompletion, useAssistant. In Solid, you replace these hooks with signals. The business logic and the LLM call remain identical.

Technical comparison

Criterion

Next.js (App Router)

SolidJS + SolidStart

Cost per token received via SSE

Component re-render + Virtual DOM diff

Text node update via signal — O(1) ✅

State of multiple parallel agents

useState per agent → cascade re-renders

Signal per agent → isolated updates ✅

Streaming server functions

React Server Components with native streaming

Server functions + createAsync / SSE

Initial Server-Side Rendering

Mature, well-documented

Functional and stable, less mileage

LLM SDKs

Same TypeScript ecosystem

Same TypeScript ecosystem

Framework bundle

~45KB + Next.js runtime

~7.6KB core ✅ 6× smaller

UI components for chat

shadcn/ui, Radix — ready for React

Kobalte (Radix port), Solid UI — smaller selection

Dashboards with 10K+ rows

Manual optimization with useMemo

Native via fine-grained reactivity ✅ 2× faster

Hiring / onboarding

Mature market

Scarce specialists

The same chat — Next.js and SolidJS side by side

Next.js — hook useChat (React-specific):

TSX
// Next.js App Router — "use client"import { useChat } from "ai/react"; // hook React — não funciona no Solidexport default function Chat() {  const { messages, input, handleInputChange, handleSubmit } = useChat();  // Cada token → re-render do componente inteiro  return (    <div>      {messages.map(m => <div key={m.id}>{m.content}</div>)}      <form onSubmit={handleSubmit}>        <input value={input} onChange={handleInputChange} />        <button type="submit">Enviar</button>      </form>    </div>  );}

SolidJS — same SDK, UI layer with signals:

TSX
// SolidJS — streamText do Vercel AI SDK funciona aqui sem modificaçãoimport { createSignal, For } from "solid-js";import { streamText } from "ai";          // ← mesmo SDK, sem modificaçãoimport { anthropic } from "@ai-sdk/anthropic";export default function Chat() {  const [msgs, setMsgs] = createSignal([]);  const [stream, setStream] = createSignal("");  const enviar = async (texto) => {    setMsgs(m => [...m, { content: texto }]);    // streamText é agnóstico — funciona em qualquer JS runtime    const result = await streamText({      model: anthropic("claude-sonnet-4-6"),      prompt: texto,    });    for await (const delta of result.textStream) {      // Apenas o nó de texto do stream atualiza — sem re-render      setStream(s => s + delta);    }    setMsgs(m => [...m, { content: stream() }]);    setStream("");  };  return (    <div>      <For each={msgs()}>{(m) => <div>{m.content}</div>}</For>      {stream() && <div>{stream()}</div>}      <input onKeyDown={e => e.key === "Enter" && enviar(e.currentTarget.value)} />    </div>  );}

Which scenario to choose

Scenario

Choice

Why

Real-time agent monitoring dashboard

SolidJS

Dozens of agents with tokens in parallel — O(1) per update

Editorial pipeline with granular progress UI

SolidJS

5 isolated signals vs. Zustand + manual memoization

Chat as a feature of an existing React/Next.js product

Next.js

useChat it works; migrating doesn't solve the real bottleneck (LLM latency)

SaaS with SEO + blog + dashboard + chat

Next.js

RSC, broad ecosystem, more mature meta-framework

💡 The real difference: The choice between Solid and Next.js for LLM apps is not about which AI SDK you can use — both have access to the same TypeScript ecosystem. The difference lies in two points: (1) rendering model — Solid updates the token text node with O(1); (2) meta-framework maturity — Next.js has RSC, more deploy adapters, and a broader UI ecosystem.


Ecosystem — Skills available for SolidJS

The official directory lists over 220 packages in 10 categories: 22 primitives, 4 routers, 23 data packages, 5 visualization, 82 UI, 35 plugins, 9 starters, 21 build utilities, 22 add-ons, and 3 testing.

Official packages — the core

Package

What it solves

Install

solid-js

Core — signals, memos, effects, stores, flow control (For, Show, Switch), Suspense, Error Boundaries

npm i solid-js

@solidjs/router

Declarative routing with lazy loading, nested routes, preload, createAsync + query for data fetching with cache and deduplication

npm i @solidjs/router

@solidjs/start

Complete meta-framework — SSR, file-based routing, server functions, streaming, deploy adapters (Vercel, Netlify, Cloudflare, Node)

npx create-solid@latest

@solidjs/meta

Management of <head> isomorphic (title, meta, link) compatible with SSR and streaming

npm i @solidjs/meta

vite-plugin-solid

Official Vite plugin — transforms Solid JSX, HMR, SSR mode, dev tools integration

npm i -D vite-plugin-solid


Headless UI and design systems

Unstyled components — you bring the CSS. The philosophy is the same as Radix UI in the React ecosystem: accessibility and behavior ready, appearance entirely yours.

@kobalte/core — 1,700+ ⭐

Native headless Solid components: Accordion, AlertDialog, Combobox, DatePicker, Select, Tabs, Toast, Tooltip, and more. Base of Solid UI (shadcn port). Full WAI-ARIA, managed focus and keyboard.

BASH
npm i @kobalte/core

corvu

Native headless Solid primitives with a focus on granular customization: Drawer, Dialog, Tooltip, Disclosure, Popover. Provides createFocusTrap, createPreventScroll as reusable utilities. Tailwind + UnoCSS plugin included.

BASH
npm i corvu

@ark-ui/solid — multi-framework

45+ headless components based on state machines (Zag.js). Supports Solid, React, Vue, and Svelte. Battle-tested in Chakra UI, used by OVHCloud and PluralSight. v5.37 recently published. Fully type-safe.

BASH
npm i @ark-ui/solid

Solid UI — shadcn/ui port

solid-ui.com — unofficial port of shadcn/ui + tremor-raw for Solid, built on Kobalte and corvu, styled with Tailwind CSS. Ownership philosophy: you copy the component, it is yours. Over 1,300 stars on GitHub. Not an npm package — you copy and paste the components.


Solid Primitives — reactive utilities

Managed by core team members but kept separate from the core for independent iteration. The goal is to wrap client and server functionality in a fully reactive API layer. Each primitive is individually tree-shakable.

JSX
// Instale só o que precisar — cada pacote é independenteimport { createIntersectionObserver } from "@solid-primitives/intersection-observer";import { createDebounce }             from "@solid-primitives/scheduled";import { createGeolocation }          from "@solid-primitives/geolocation";import { createLocalStorage }         from "@solid-primitives/storage";import { createResizeObserver }       from "@solid-primitives/resize-observer";import { createEventListener }        from "@solid-primitives/event-listener";import { createKeyHold }              from "@solid-primitives/keyboard";import { makeTimer, createCountdown } from "@solid-primitives/timer";// Exemplo: debounce de busca + intersection para lazy-loadfunction BuscaLazy() {  const [query, setQuery] = createSignal("");  const [ref, setRef] = createSignal(null);  const debouncedQuery = createDebounce((v) => setQuery(v), 300);  createIntersectionObserver(ref, ([entry]) => {    if (entry.isIntersecting) carregarMais();  });  return (    <div>      <input onInput={(e) => debouncedQuery(e.currentTarget.value)} />      <div ref={setRef}>sentinela de scroll</div>    </div>  );}

Data and server state

Package

Use case

Note

@solidjs/router (query + createAsync)

Data fetching integrated into the router with key-based cache, deduplication, and revalidation. The canonical path in SolidStart — zero extra dependencies

✅ Recommended for SolidStart

@tanstack/solid-query v5.100+

Full port of TanStack Query. Supports refetchInterval, enabled, mutations, infinite queries, devtools

Use when you need polling or advanced features

@solidjs/tanstack-table

Port of TanStack Table — sorting, filtering, pagination, virtualization. Data as stores, reactive columns

Ideal for heavy data grids

⚠️ Attention when using @tanstack/solid-query: the return of the primitives is a store (not an object), and its properties are only tracked in a reactive context. Do not destructure the result outside of a tracking scope.


Forms

Forms are the case where Solid's fine-grained reactivity shines the most: validating a field in real-time without re-rendering the rest of the form is O(1) here, not an optimization you need to implement.

@modular-forms/solid — Field-level validation: only the field with the error re-evaluates. Minimal bundle by modular design (tree-shaking by feature). Integrates with Zod, Valibot, Arktype.

BASH
npm i @modular-forms/solid

@gapu/formix — Flexible API for complex form state. Alternative to modular-forms with a more familiar API for those coming from React Hook Form.

BASH
npm i @gapu/formix

Testing

Package

What it does

Notes

@solidjs/testing-library

Port of Testing Library for Solid — renders components in real DOM (jsdom/happy-dom), queries by role/text/label, fire events, async utilities

Recommended by the core team along with Vitest

vitest

Official recommended test runner. Integrates natively with Vite, support for Solid JSX without extra configuration, fast watch mode

Add vite-plugin-solid to vitest.config.ts

solid-jest

Allows running and testing Solid code in Node.js via Jest — alternative for projects already using Jest

Prefer Vitest in new projects

solid-devtools

Chrome extension + dev tools library: visualizes the reactive graph in real-time, inspects signals, stores, and components

Dev only — does not impact production bundle


Styling, animation, and DnD

Package

What it does

solid-transition-group

Entry/exit animations inspired by Vue Transition. <Transition> and <TransitionGroup> with CSS classes or Web Animations API

@solid-dnd/sortable

Drag-and-drop and list reordering — reactive primitives for sortable lists, kanban boards, and tree views

solid-styled-components

CSS-in-JS in the style of styled-components — tagged template literals, theming, SSR-safe

solid-icons

Collection of icons (Feather Icons fork) compiled as Solid components — tree-shakable, no SVG sprite

solid-refresh

HMR for Solid in multiple bundlers (Vite, Webpack, esbuild). Maintains reactive state during module reload


Minimum stack for production — from zero to production

BASH
# 1. Scaffold com SolidStart (meta-framework completo)npx create-solid@latest meu-appcd meu-app && npm install# 2. UI headless com acessibilidadenpm install @kobalte/core          # componentes headless nativos# ou: npm install @ark-ui/solid    # multi-framework, mais componentes# 3. Formulários — escolha umnpm install @modular-forms/solid   # field-level validation, bundle mínimo# 4. Server state — escolha um# Opção A: nativo do SolidStart (zero deps extras)# import { query, createAsync } from "@solidjs/router"# Opção B: TanStack Query (polling, retries, devtools)npm install @tanstack/solid-query# 5. Primitivos utilitários (instale só os que precisar)npm install @solid-primitives/scheduled             # debounce, throttlenpm install @solid-primitives/intersection-observer # lazy loadnpm install @solid-primitives/storage               # localStorage reativo# 6. Testingnpm install -D vitest @solidjs/testing-library happy-dom# 7. Dev tools (só development)npm install -D solid-devtools

⚠️ What is still missing: The ecosystem has real gaps compared to React — rich text editors (no Lexical or TipTap port), complex animation libraries (no Framer Motion port — use solid-transition-group + Web Animations API), maps (use vanilla Leaflet/Mapbox wrappers). For data charts: D3 works directly with Solid (native DOM access), and there are wrappers like solid-apexcharts and solid-recharts, but with less maintenance than the React equivalents. Always check solidjs.com/ecosystem before assuming something doesn't exist.


Solid 2.0 — the next chapter

The Solid 2.0 roadmap (GitHub Discussion #2425) is ambitious:

  • Pull-based run-once SSR — new server-side rendering architecture

  • Concurrent transitions — smoother UI updates during asynchronous operations

  • Self-healing error boundaries — more resilient error recovery

  • Immutable diffable stores — improved state management primitives

  • Automatic batching — signal updates grouped for optimal performance

  • Lazy memos and derived signals — more efficient computed values

  • createAsync as standard primitive — recommended approach for async data fetching

The Solid 2.0 Beta skipped the planned Alpha phase — creator Ryan Carniato noted that "most milestones within Alpha do not seem relevant enough to justify their own phase".

TC39 Signals — the proposal that goes beyond Solid

The model that SolidJS popularized is being standardized in the language. Maintainers of Angular, Vue, Svelte, Solid, Preact, Qwik, MobX, Ember, RxJS, and more are collaborating on a TC39 proposal to add signals to JavaScript. It is already in Stage 1, with a polyfill available.

JAVASCRIPT
// A proposta do TC39: signals na linguagem, sem frameworkconst count = new Signal.State(0);const double = new Signal.Computed(() => count.get() * 2);count.set(1);double.get(); // 2

What started as the core philosophy of Solid may become a native JavaScript primitive.


Aligning with business — the technical decision

SolidJS is not the safe choice. It is the right choice for a specific set of conditions — and the wrong choice for another equally specific set.

If your product competes on load time, frame rate, interaction latency, or bundle size, SolidJS delivers measurable advantage. Fine-grained reactivity is not marketing: it is a model that provably generates less work per update.

If your product competes on shipping speed, team size, ease of hiring, or breadth of third-party integrations, React is still the answer for most cases.

Use SolidJS when

  • Rendering performance is a measurable product criterion

  • Bundle size matters (embedded apps, mid-range mobile, TV)

  • UI updates are frequent and granular (real-time, 60fps)

  • LLM applications with multiple agents emitting tokens in parallel

  • Team already knows React and is open to the new mental model

  • You are building something new with freedom of stack choice

  • The libraries you need have a Solid version available

Consider another option when

  • Hiring and fast onboarding are a priority — go for React

  • You depend on UI libraries without a Solid port (Framer Motion, Lexical…)

  • The team has never had contact with fine-grained reactivity — the curve has a real cost

  • SolidStart does not yet have the deploy adapter you need

  • Performance is not in your OKRs — optimize where it hurts

"SolidJS proves that the Virtual DOM was a transitional solution. If your users feel the difference — use Solid. If they don't, your current stack is probably good enough."


Sources and data — Jun 2026

  • solidjs.com / docs.solidjs.com — official documentation, primitives, fine-grained reactivity, changelog

  • InfoQ (may/2026) — "SolidJS 2.0 Beta: First-Class Async, Reworked Suspense and Deterministic Batching"

  • Tomas Listiak / listiak.dev (feb/2026) — "The State of Solid.js in 2026" — bundle data (7.6KB), enterprise use cases (Radware, Jolt AI)

  • PkgPulse Guides (mar/2026) — React vs SolidJS and SolidJS vs Svelte comparisons, npm downloads (1.49M–2.41M/week), 60% y/y growth

  • SoloDevStack (may/2026) — version data (solid-js 1.9.13, SolidStart 1.3.2)

  • GitHub solidjs/solid — Discussion #2425 — official Solid 2.0 roadmap

  • npmjs.com/package/solid-js — official description, integrations, environment support

  • Zylos Research (mar/2026) — "LLM Output Streaming and Real-Time Token Delivery Architectures" — SSE as standard for agents, MCP/A2A

  • GitHub peerreynders/solid-start-sse-chat — reference implementation of SSE chat in SolidStart

  • BCMS Blog (feb/2026) — "Top 10 Next.js Alternatives in 2026" — SolidStart "2x faster in dashboards with 10K+ rows"

  • Toptal (may/2026) — "SolidJS vs React: The Go-to Guide" — meta-framework comparison

  • solidjs.com/ecosystem — official directory (220+ packages in 10 categories)

  • kobalte.dev, corvu.dev, solid-ui.com — documentation for main UI packages

  • tanstack.com/query/solid — official documentation for TanStack Query for Solid (v5.100+)

  • github.com/solidjs-community/solid-primitives — documentation and catalog of Solid Primitives


Download data, versions, and benchmark positions reflect June 2026. Solid 2.0 is in beta — the API may change before the stable release. Company data (Radware, Jolt AI) is reported by the ecosystem, not independently verified. The "2x faster for dashboards with 10K+ rows" data is reported by BCMS in comparison with Next.js. Compare live at pkgpulse.com and framework-benchmarks.as93.net before deciding.