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.

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
createMemoand 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.
Getter e setter que rastreiam automaticamente os consumidores sem arrays de dependência.
Calculado de forma preguiçosa, atualiza somente quando necessário.
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.
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.
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.
// 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 boundaryawait.
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.
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.
// 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.
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.
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
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:
setStreamAtualit 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.
Pesquisa → Rascunho → Revisão → SEO → Publicar ↓ ↓ ↓ ↓ ↓ signal signal signal signal signal ↓ ↓ ↓ ↓ ↓DOM node DOM node DOM node DOM node DOM nodeEach signal updates its own DOM node — no interference between steps.
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 hooks — useChat, 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):
// 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:
// 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 |
|
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 |
|---|---|---|
| Core — signals, memos, effects, stores, flow control ( |
|
| Declarative routing with lazy loading, nested routes, preload, |
|
| Complete meta-framework — SSR, file-based routing, server functions, streaming, deploy adapters (Vercel, Netlify, Cloudflare, Node) |
|
| Management of |
|
| Official Vite plugin — transforms Solid JSX, HMR, SSR mode, dev tools integration |
|
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.
npm i @kobalte/corecorvu
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.
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.
npm i @ark-ui/solidSolid 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.
// 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 |
|---|---|---|
| Data fetching integrated into the router with key-based cache, deduplication, and revalidation. The canonical path in SolidStart — zero extra dependencies | ✅ Recommended for SolidStart |
| Full port of TanStack Query. Supports | Use when you need polling or advanced features |
| 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.
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.
npm i @gapu/formixTesting
Package | What it does | Notes |
|---|---|---|
| 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 |
| Official recommended test runner. Integrates natively with Vite, support for Solid JSX without extra configuration, fast watch mode | Add |
| Allows running and testing Solid code in Node.js via Jest — alternative for projects already using Jest | Prefer Vitest in new projects |
| 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 |
|---|---|
| Entry/exit animations inspired by Vue Transition. |
| Drag-and-drop and list reordering — reactive primitives for sortable lists, kanban boards, and tree views |
| CSS-in-JS in the style of styled-components — tagged template literals, theming, SSR-safe |
| Collection of icons (Feather Icons fork) compiled as Solid components — tree-shakable, no SVG sprite |
| HMR for Solid in multiple bundlers (Vite, Webpack, esbuild). Maintains reactive state during module reload |
Minimum stack for production — from zero to production
# 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 likesolid-apexchartsandsolid-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
createAsyncas 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.
// 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(); // 2What 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.


