DEV Community

Alex Spinov
Alex Spinov

Posted on

SolidStart Has a Free Meta-Framework With True Reactivity (No Virtual DOM)

React re-renders your entire component tree on every state change. Solid doesn't — it updates only the exact DOM nodes that changed. SolidStart brings this surgical reactivity to a full-stack meta-framework.

Here's why SolidStart deserves a spot in your 2026 toolkit.

What SolidStart Gives You for Free

  • Fine-grained reactivity — no virtual DOM, no re-renders, just direct DOM updates
  • File-based routing with nested layouts and data loading
  • Server functions — call backend code directly from components (RPC-style)
  • SSR, SSG, and CSR — choose per route
  • Vinxi-powered — built on Nitro, deploys everywhere (Vercel, Netlify, Cloudflare, Node)
  • Islands architecture optional — ship zero JS for static content

Quick Start

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

Reactivity Without Re-Renders

In React, updating a counter re-renders the entire component. In Solid:

import { createSignal } from 'solid-js';

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

  console.log('This runs ONCE, not on every update');

  return (
    <button onClick={() => setCount(c => c + 1)}>
      Count: {count()} {/* Only THIS text node updates */}
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

The console.log runs once. The DOM update is surgical — only the text node with count() changes.

Server Functions (The Killer Feature)

// src/routes/dashboard.tsx
import { createAsync } from '@solidjs/router';
import { query } from '@solidjs/router';

const getUser = query(async () => {
  'use server';
  const session = await getSession();
  return db.users.find(session.userId);
}, 'user');

export default function Dashboard() {
  const user = createAsync(() => getUser());

  return (
    <div>
      <h1>Welcome, {user()?.name}</h1>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

The 'use server' directive means getUser runs on the server. No API route needed. No fetch boilerplate. Type-safe end to end.

Actions (Mutations Made Simple)

import { action, useSubmission } from '@solidjs/router';

const addTodo = action(async (formData: FormData) => {
  'use server';
  const title = formData.get('title') as string;
  await db.todos.create({ data: { title } });
});

export default function Todos() {
  const submission = useSubmission(addTodo);

  return (
    <form action={addTodo} method="post">
      <input name="title" />
      <button disabled={submission.pending}>Add</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

Performance Comparison

Metric SolidStart Next.js SvelteKit
Bundle size (counter) ~3KB ~85KB ~5KB
Updates mechanism Direct DOM Virtual DOM diff Compiled
Component re-renders Never Every state change N/A
Memory usage Lowest Highest Low
JS Framework Benchmark #1-2 #15-20 #3-5

Solid consistently ranks at the top of JS framework benchmarks alongside vanilla JS.

Deploy Anywhere

SolidStart uses Vinxi (built on Nitro), so it deploys to:

  • Vercel, Netlify, Cloudflare Workers
  • AWS Lambda, Deno Deploy
  • Any Node.js server
  • Static hosting (SSG mode)

The Verdict

SolidStart combines React's familiar JSX syntax with performance that rivals vanilla JavaScript. If you've ever wished React was faster without reaching for complex memoization — Solid is the answer.


Need help building production web scrapers or data pipelines? I build custom solutions for startups and enterprises. Reach out: spinov001@gmail.com

Check out my awesome-web-scraping collection — 400+ tools for extracting web data.

Top comments (0)