SolidStart is the full-stack framework for SolidJS. Fine-grained reactivity, server functions, streaming SSR — and it compiles to actual DOM operations, not a virtual DOM.
What Is SolidStart?
SolidStart is the meta-framework for SolidJS (like Next.js is for React). File-based routing, server functions, SSR/SSG, and zero virtual DOM overhead.
Quick Start
npx create-solid@latest my-app
cd my-app && npm install && npm run dev
File-Based Routing
src/routes/
index.tsx -> /
about.tsx -> /about
users/
index.tsx -> /users
[id].tsx -> /users/:id
api/
users.ts -> /api/users
Server Functions
// src/routes/users/[id].tsx
import { createAsync, RouteDefinition } from '@solidjs/router'
import { action, query } from '@solidjs/router'
const getUser = query(async (id: string) => {
'use server'
const user = await db.users.findUnique({ where: { id } })
if (!user) throw new Error('User not found')
return user
}, 'user')
const updateUser = action(async (formData: FormData) => {
'use server'
const id = formData.get('id') as string
const name = formData.get('name') as string
await db.users.update({ where: { id }, data: { name } })
})
export default function UserPage() {
const params = useParams()
const user = createAsync(() => getUser(params.id))
return (
<div>
<h1>{user()?.name}</h1>
<form action={updateUser} method="post">
<input type="hidden" name="id" value={params.id} />
<input name="name" value={user()?.name} />
<button type="submit">Update</button>
</form>
</div>
)
}
API Routes
// src/routes/api/users.ts
import { json } from '@solidjs/router'
export async function GET() {
const users = await db.users.findMany({ take: 20 })
return json(users)
}
export async function POST(event: any) {
const body = await event.request.json()
const user = await db.users.create({ data: body })
return json(user, { status: 201 })
}
Fine-Grained Reactivity
import { createSignal, createEffect, For } from 'solid-js'
function TodoList() {
const [todos, setTodos] = createSignal<Todo[]>([])
const [filter, setFilter] = createSignal('all')
const filtered = () => {
if (filter() === 'done') return todos().filter(t => t.done)
if (filter() === 'active') return todos().filter(t => !t.done)
return todos()
}
// Only re-renders the EXACT DOM nodes that changed
// No virtual DOM diffing
return (
<div>
<For each={filtered()}>
{(todo) => <div>{todo.text}</div>}
</For>
</div>
)
}
Performance
| Metric | SolidStart | Next.js | Remix |
|---|---|---|---|
| Bundle size | 7KB | 85KB+ | 50KB+ |
| TTI | Fastest | Fast | Fast |
| Memory | Lowest | High (vDOM) | Medium |
| Reactivity | Fine-grained | Component-level | Component-level |
| Hydration | Minimal | Full | Progressive |
Deploy Anywhere
# Vercel
npm run build -- --preset vercel
# Cloudflare
npm run build -- --preset cloudflare-pages
# Node.js
npm run build -- --preset node-server
Need a fast frontend for scraped data? Scrapfly provides web data APIs. Email spinov001@gmail.com for data + frontend solutions.
Top comments (0)