DEV Community

Alex Spinov
Alex Spinov

Posted on

SolidStart Has a Free Full-Stack Framework — React-Like Syntax With True Reactivity

SolidJS compiles to direct DOM updates — no virtual DOM diffing. SolidStart adds routing, SSR, and API routes on top. The result? React's DX with 10x better performance.

What is SolidStart?

SolidStart is the full-stack framework for SolidJS. It handles server-side rendering, file-based routing, API routes, and server functions — powered by Vinxi and Nitro under the hood.

Why SolidStart

1. Fine-Grained Reactivity

import { createSignal } from "solid-js";

function Counter() {
  const [count, setCount] = createSignal(0);

  // This div NEVER re-renders. Only the text node updates.
  return (
    <div>
      <p>Count: {count()}</p>
      <button onClick={() => setCount(c => c + 1)}>Increment</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

No virtual DOM. No component re-renders. Only the exact DOM node that changed updates.

2. Server Functions

"use server";

async function getUser(id: string) {
  return await db.users.findUnique({ where: { id } });
}

async function createPost(title: string, content: string) {
  return await db.posts.create({ data: { title, content } });
}
Enter fullscreen mode Exit fullscreen mode
// Use directly in components
function UserProfile(props: { userId: string }) {
  const user = createAsync(() => getUser(props.userId));
  return <h1>{user()?.name}</h1>;
}
Enter fullscreen mode Exit fullscreen mode

3. File-Based Routing

src/routes/
├── index.tsx              → /
├── about.tsx              → /about
├── blog/
│   ├── index.tsx          → /blog
│   └── [slug].tsx         → /blog/:slug
├── api/
│   └── users.ts           → /api/users
└── (auth)/
    ├── login.tsx          → /login
    └── register.tsx       → /register
Enter fullscreen mode Exit fullscreen mode

4. Data Loading with createAsync

import { createAsync, cache } from "@solidjs/router";

const getProducts = cache(async () => {
  "use server";
  return await db.products.findMany({ where: { active: true } });
}, "products");

export default function Products() {
  const products = createAsync(() => getProducts());

  return (
    <For each={products()}>
      {(product) => (
        <div>
          <h3>{product.name}</h3>
          <p>${product.price}</p>
        </div>
      )}
    </For>
  );
}
Enter fullscreen mode Exit fullscreen mode

5. Actions (Form Handling)

import { action, redirect } from "@solidjs/router";

const createTodo = action(async (formData: FormData) => {
  "use server";
  const title = formData.get("title") as string;
  await db.todos.create({ data: { title } });
  throw redirect("/todos");
});

export default function NewTodo() {
  return (
    <form action={createTodo} method="post">
      <input name="title" required />
      <button type="submit">Create</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

Performance

Benchmark SolidStart Next.js SvelteKit
Bundle size (hello) 7KB 85KB 15KB
Update perf (JS Framework Bench) #1 #15 #5
Memory usage Low High Medium

SolidStart vs Next.js vs SvelteKit

SolidStart Next.js SvelteKit
Reactivity Fine-grained signals Virtual DOM Compiled
Re-renders None (surgical updates) Component-level Component-level
Server functions "use server" Server actions +page.server.ts
JSX Yes (compiled) Yes (virtual DOM) No (Svelte syntax)
Learning curve Low (React-like) Low Low

Getting Started

npm init solid@latest my-app
# Choose: SolidStart
cd my-app
npm install
npm run dev
Enter fullscreen mode Exit fullscreen mode

The Bottom Line

SolidStart proves you don't need a virtual DOM for a great developer experience. React's syntax with surgical DOM updates, full-stack capabilities, and the best raw performance of any framework.


Need data tools? I build scraping solutions. Check my Apify actors or email spinov001@gmail.com.

Top comments (0)