github solidjs/solid v2.0.0-rc.0
v2.0.0 RC - The Big <Reveal>

pre-release3 hours ago

Solid 2.0 RC: The Big <Reveal>

The hardest problems in UI frameworks were never about rendering. We've always had a DOM we could mutate efficiently. The early challenge was synchronization — showing a consistent interface no matter what was going on, and doing it efficiently. Fine-grained reactivity solved that a decade ago. Update exactly what changed. Skip the rest.

The problem that never went away was async. Every framework, including ours, treated it as a condition that happened to it. Something a synchronous core would have to weather.

Today Solid 2.0 reaches Release Candidate, and it takes the other path: async is a property of the reactive system itself. It's part of the graph. That one decision runs through everything in this release. The model does more, so the framework does less.

Async Lives in the Graph

A computation can return a Promise(or Async Iterator), and everything downstream just understands. No special primitive to absorb it. No manual loading state. No null checks.

import { createMemo, isPending, Loading } from "solid-js";

function Profile(props) {
  const user = createMemo(() => fetchUser(props.id));

  return (
    <Loading fallback={<Skeleton />}>
      <h1 class={{ stale: isPending(user) }}>{user().name}</h1>
    </Loading>
  );
}

That's the whole data-fetching story. user is a memo that happens to be async. <Loading> covers it until it's ready. When props.id changes, the old content stays visible while the new answer is in flight, and isPending tells you a change is coming — not "is anything fetching anywhere," but "is a new answer to this question on the way."

Derived state, error handling, transitions, optimistic updates all fall out of this one idea. And because async lives in the graph, the same components work whether their data comes from a client fetch, a server render, or a server function. The server story layers onto your app instead of replacing it.

The full async story deserves more than a section. A deep dive series starts next week.

Less to Learn, More to Use

Everything Solid 2.0 removes is something you had to learn. Everything it adds is something you get to use. These weren't features we cut. They were workarounds you had to learn. Now they're just how Solid works:

  • createResource — gone. Async flows through ordinary memos.
  • batch — gone. Everything batches. Writes apply on a microtask; flush() when you need them now.
  • startTransition / useTransition — gone. The graph holds a consistent state on its own; isPending and latest read it.
  • on and createComputed — gone. Split effects — createEffect(compute, apply) — separate tracking from side effects.
  • produce and createMutable — gone. Store setters hand you a draft you mutate. That's just how stores work now.

The 1.x migration guide maps every removal to its replacement.

The new APIs are a different story. You don't need optimistic stores, projections, actions, or reveal ordering to build your first app. You might not need them for your tenth. But when you do, they're there, and they work with everything else. Learn less, do more. And the runtime is only half of it.

One Plugin, Whole Platform

Our tooling made the same trade.

Solid 2.0 ships a new compiler toolchain written in Rust on top of OXC, and @solidjs/vite-plugin defaults to it automatically. Upgrade the plugin and you're compiling Solid with native tooling. Zero configuration. Nothing to migrate. The Babel preset remains available as an option.

Workload babel-plugin-jsx oxc compiler Speedup
Fixture corpus (88 files, 175 KB, all 10 modes) 440 ms 19 ms 23x
129 KB single module 545 ms 9.4 ms 58x
1 MB single module 24,975 ms 70 ms 355x

And the plugin now has a start mode — a turnkey serving layer, as a mode of the plugin itself:

// vite.config.ts
import { defineConfig } from "vite";
import solid from "@solidjs/vite-plugin";

export default defineConfig({
  plugins: [solid({ start: true })]
});

That's a complete app setup on plain Vite. No entry files, no index.html, no dev server script. The plugin owns entries, dev serving, and the build. You write src/App.tsx and go.

Everything layers on from there:

  • A SPA by default. start: true alone is client mode: dev serves your app client-rendered onto a streamed document shell, and vite build emits a purely static dist/client — deployable to any static host.
  • File-system routing via the router-neutral filesystem-routing package — SolidStart-proven conventions, HMR and code splitting, GET/POST API routes as fetch middleware, typed route emission for Solid Router.
  • SSR with solid({ start: true, ssr: true }). The plugin swaps render for hydrate, turns on the hydratable transforms, and ships the server bundle. The production contract is one function — handleRequest(request) — which is why it composes with any host platform. Fetch-style middleware (start.middleware), a per-request setup seam for routers (start.setup), and typed environment variables validated by Standard Schema — with a build-time scan that fails the build if a server secret leaks into a client chunk — round out the serving layer.
  • Server functions. "use server" is now a core feature backed by @solidjs/web/server-functions — typed RPC, streaming returns, progressive enhancement, and custom serialization in any Vite app. The server side of a server function is your function body — validation, auth, logging are lines of code, not framework hooks. Anything referenced only inside the body never reaches the client; the directive boundary is itself the privacy mechanism.
import { reload } from "@solidjs/web";

export async function addTodo(title: string) {
  "use server";
  await db.insert(title);
  return reload({ revalidate: "todos" });
}
  • When it's time to ship one build emits dist/client plus a server module that default-exports a web-standard Fetchable handler — the convention Workers, Netlify Functions, Nitro, Bun, and deno serve already speak. The platform Vite plugins from Cloudflare, Netlify, and Nitro adopt Solid's server environment directly, so there is no Solid adapter layer to configure or for us to maintain. Deployment is web standards plus your platform's own tooling. Full deployment guide.

SolidStart Finished Its Job

A metaframework exists to fill the gaps in its framework. SolidStart's job was to provide what core couldn't. Over the 2.0 cycle, each of those capabilities moved home: server functions into core, the serving layer into start mode, file-system routing into a router-neutral package. What remained at the end of that process was a wrapper around things that no longer needed wrapping.

So instead of shipping a hollow 3.0, we're retiring it. Start mode replaces SolidStart.

If you run SolidStart in production today, nothing breaks. SolidStart will continue to receive maintenance releases, and the migration guide is available now. For most apps the move is mechanical, and the migration assistant below flags the rest. This isn't an ending — it's the framework finishing the job the metaframework started.

The Ten-Second Tour

If you followed the beta announcement, you know the foundations. For everyone else each item links to the docs:

  • <Loading>, <Errored>, <Reveal>. Suspense, ErrorBoundary, and SuspenseList, reconsidered for the new async model — stale content stays visible on revalidation, boundaries heal, reveal order is coordinated.
  • Actions and optimistic state in core. action, createOptimistic, and createOptimisticStore make in-flight mutations render immediately and reconcile when the server answers.
  • Draft-first stores. Setters take a draft you mutate; projections and derived stores (createStore(fn), createProjection) replace the write-back patterns of 1.x.
  • Unified lists. One <For> with keying modes replaces For/Index; <Repeat> renders by count with no diffing.
  • A DOM model closer to HTML. Standard attribute semantics, boolean presence/absence, class objects and arrays, ref directive factories.
  • A cleaner package graph. The reactive core is @solidjs/signals, the web runtime is @solidjs/web, stores live in solid-js itself.

The design rationale for all of it lives in the 2.0 RFCs.

What's Next

Two things are deliberately not in this post.

The async model deserves a real deep dive. A series starts next week: reads, writes, and the wire — how components stay latency-agnostic whether data comes from a memo, an optimistic mutation, or a streaming server.

And for those who notice serverFunctions: { components: true } in the config types: yes, server functions can return components. Reactive server components are in experimental preview behind that flag, and they get a full announcement after 2.0 stable. They're worth the wait.

Try It, Migrate to It

Preview documentation for Solid 2.0 is live at v2.solidjs.com.

For new projects, choose the Solid V2 templates from:

npm create solid@latest

For migrating existing projects, follow the guides here.

We are also developing a migration assistant that scans your project and prints specific guidance for every 1.x migration site it detects — legacy imports, one-argument createEffect, onMount, Suspense/Index/classList, the old store helpers:

npx solid-migration-assistant

The ecosystem didn't wait. Solid Router 2.0 ships alongside the RC with fully typed routes, params, and navigation and Solid Meta 1.0 is now a thin layer over 2.0's built-in head registry. Prefer TanStack? The fullstack-tanstack template pairs TanStack Router and TanStack Query with start mode out of the box, and TanStack Start already ships a Solid 2.0 beta (@tanstack/solid-start@beta). The libraries you actually build apps with — And the libraries you actually build apps with — Solid Primitives, Kobalte, Solid Testing Library, Storybook, and AG Grid — have been working hard to support 2.0 through the betas and are ready to use with the RC today. Utilities, components, metaframeworks, testing, routing, head management: the stack is ready before the release is.

Thank You

It's hard to describe the Herculean effort that has gone into making this happen over the last 5 months. I never thought we'd accomplish so much in such a short time. It is always the quality of life things that you tend to skimp on and that was the difference. Solid 2.0 Beta was pretty "Solid" before we even launched it. Years of researching the best patterns for declarative reactivity reached their culmination.

But what I didn't expect was how different this was compared to when we prepared for the Solid 1.0 release. A lot smaller community then and it felt like it was taking forever. This time, I went on paternity leave for 6 weeks to bond with my son Nico and we didn't miss a beat. The beta testers, the AI agents, just kept pushing forward. While I was determined not to let the core scope creep, everything else sort of just came along with it. Things I had pencilled in for Solid 3.0 or 4.0 even. I actually had a Solid 3.0 plan document sketched up 6 months ago — we've accomplished everything in it.

And that might just be how these things go in an age of AI, but it's important to recognize the people who make that possible. And there are too many to recognize but I will give a quick shout out.

Starting with those that directly support my work, Sentry my benevolent employer, and Cursor whose credits made the impossible possible.

And to everyone involved in testing and contributing to the beta:
@brenelz @yumemi-thomas @mizulu @titoBouzout @GabbeV @birkskyum @dangkyokhoang @tsushanth @maciek50322 @kanashimia @SnowingFox @atk @AFatNiBBa @snatvb @better-salmon @m-canton @arpitjain099 @DominicDolan @deluksic @danon @danielalanbates @beanscg @trusktr @sonukapoor @rtritto @ngotruonghuy @mudmaster556 @jpdutoit @gameroman @echab @danielrkling @katywings @clinuxrulz @ahzvenol @tonghuaxingdsb @thomasbuilds @thep0y @subotac @spokodev @samualtnorman @rvlzzr @rrshaban @rexblade58 @mitsuhiko @mesram @mariokresic @madaxen86 @lxsmnsyc @Tommypop2 @LadyBluenotes @le0-0 @jer3m01 @iamssen @gnomical @developerdizzle @devagrawal09 @milomg @mihar-22 @tannerlinsley @crassicus @alfi-dim @aekobear @WolffM @VXsz @PierBover @Jungzl @JLouisa @DakshSinghDhami @CxRes

Release Candidate means the API is frozen but not that there won't be bugs, so we really appreciate everyone updating their projects and reporting issues. If you're an ecosystem builder or maintain projects on Solid 1.0 please consider migrating now and reporting any issues.

Let's get Solid 2.0 to an official release!

Don't miss a new solid release

NewReleases is sending notifications on new releases.