DEV Community

Alex Spinov
Alex Spinov

Posted on

SolidStart Has a Free API Framework That Outperforms Next.js in Every Benchmark

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
Enter fullscreen mode Exit fullscreen mode

File-Based Routing

src/routes/
  index.tsx          -> /
  about.tsx          -> /about
  users/
    index.tsx        -> /users
    [id].tsx         -> /users/:id
  api/
    users.ts         -> /api/users
Enter fullscreen mode Exit fullscreen mode

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>
  )
}
Enter fullscreen mode Exit fullscreen mode

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 })
}
Enter fullscreen mode Exit fullscreen mode

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>
  )
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Need a fast frontend for scraped data? Scrapfly provides web data APIs. Email spinov001@gmail.com for data + frontend solutions.

Top comments (0)