SolidStart Adapter
SolidJS with SolidStart meta-framework: fine-grained reactivity, no VDOM, server functions, file-based routing, and streaming SSR with renderToStream — TTFB under 2ms.
Solid 1.8 · No VDOM · Streaming SSR
Fine-grained reactivity
Signals update the exact DOM node that changed — no VDOM diffing, no component re-renders.
renderToStream()
Streaming SSR with Suspense support. TTFB under 2ms. Content streams as data resolves.
Server functions
'use server' directive marks functions that run exclusively on the server — called like regular functions.
File routing
routes/ directory generates routes automatically. Nested layouts with createRouteData().
Zero overhead
Solid compiles to precise DOM operations. Bundles are smaller than React with better runtime perf.
TypeScript native
Full TypeScript support including JSX types via solid-js/types.
Setup
bash
npm create lunx-dev@latest my-solid-app -- --framework solid --ts cd my-solid-app && npm install && npm run dev
Solid reactivity with signals
typescriptsrc/components/Counter.tsx
import { createSignal, createMemo, createEffect } from 'solid-js' export function Counter() { // Signals — like React useState but update DOM directly const [count, setCount] = createSignal(0) const [name, setName] = createSignal('World') // Memo — like useMemo but reactive automatically const doubled = createMemo(() => count() * 2) const greeting = createMemo(() => `Hello ${name()}! Count: ${count()}`) // Effect — runs when dependencies change createEffect(() => { document.title = `Count: ${count()}` }) return ( <div> <h2>{greeting()}</h2> <p>Doubled: {doubled()}</p> <input value={name()} onInput={e => setName(e.target.value)} /> <button onClick={() => setCount(c => c - 1)}>−</button> <button onClick={() => setCount(c => c + 1)}>+</button> </div> ) }
Server functions with 'use server'
typescriptsrc/routes/blog/index.tsx
import { createRouteData, useRouteData, refetchRouteData } from 'solid-start' import { createServerAction$ } from 'solid-start/server' // Runs on server only — called like a regular function from client async function getPosts() { 'use server' return await db.post.findMany({ orderBy: { createdAt: 'desc' } }) } export function routeData() { return createRouteData(getPosts, { key: 'posts' }) } export default function BlogIndex() { const posts = useRouteData<typeof routeData>() const [addPost, { Form }] = createServerAction$(async (form: FormData) => { 'use server' const title = form.get('title') as string await db.post.create({ data: { title, slug: slugify(title) } }) }) return ( <div> <Form> <input name="title" placeholder="New post title..." /> <button type="submit">Add Post</button> </Form> <Suspense fallback={<p>Loading...</p>}> <For each={posts()}> {post => <article><h2>{post.title}</h2></article>} </For> </Suspense> </div> ) }
Why Solid over React?
SolidJS uses the same JSX syntax as React but compiles to direct DOM operations — no virtual DOM reconciliation. A counter component in Solid updates a single text node; in React it re-executes the entire component function. This makes Solid ~2–3× faster at runtime for highly dynamic UIs.