SolidStart is the full-stack meta-framework for SolidJS, offering file-based routing, server-side rendering (SSR), API routes, and edge-ready deployment. If you prefer SolidJS's fine-grained reactivity over React's virtual DOM, SolidStart is your path to building production applications. This guide covers deploying SolidStart on your VPS.
Why SolidStart?
- Fine-grained reactivity: SolidJS updates only what changes — no virtual DOM overhead
- Tiny bundle size: SolidJS is significantly smaller than React
- Full-stack: Server functions, API routes, and middleware built in
- Flexible rendering: SSR, SSG, CSR, or streaming — pick per route
- Vinxi-powered: Built on Vinxi/Nitro for universal deployment
Create a SolidStart Project
# Create new project
npm init solid@latest my-solid-app
cd my-solid-app
# Select: SolidStart, TypeScript, with SSR
# Install dependencies
npm install
# Project structure
my-solid-app/
├── src/
│ ├── routes/ # File-based routing
│ │ ├── index.tsx # Homepage (/)
│ │ ├── about.tsx # /about
│ │ └── api/ # API routes
│ │ └── hello.ts
│ ├── components/ # Reusable components
│ ├── lib/ # Utilities
│ └── app.tsx # Root component
├── public/ # Static assets
├── app.config.ts # SolidStart config
└── package.json
Build Routes and Components
// src/routes/index.tsx
import { createSignal } from "solid-js"
import { Title, Meta } from "@solidjs/meta"
export default function Home() {
const [count, setCount] = createSignal(0)
return (
<main>
<Title>My SolidStart App</Title>
<Meta name="description" content="A fast SolidStart application" />
<h1>Welcome to SolidStart</h1>
<button => setCount(count() + 1)}>
Count: {count()}
</button>
</main>
)
}
// src/routes/api/posts.ts — API Route
import { json } from "@solidjs/router"
export async function GET() {
const posts = await db.query("SELECT * FROM posts ORDER BY created_at DESC")
return json(posts)
}
// src/routes/blog/[slug].tsx — Dynamic Route
import { useParams } from "@solidjs/router"
import { createAsync } from "@solidjs/router"
const getPost = cache(async (slug: string) => {
"use server"
return await db.query("SELECT * FROM posts WHERE slug = ?", [slug])
}, "post")
export default function BlogPost() {
const params = useParams()
const post = createAsync(() => getPost(params.slug))
return (
<article>
<h1>{post()?.title}</h1>
<div innerHTML={post()?.content} />
</article>
)
}
Configure for Production
// app.config.ts
import { defineConfig } from "@solidjs/start/config"
export default defineConfig({
server: {
preset: "node-server",
port: 3000,
},
vite: {
build: {
target: "esnext",
},
},
})
Build and Deploy
# Build for production
npm run build
# Output structure:
# .output/
# ├── server/ # Node.js server bundle
# │ └── index.mjs
# └── public/ # Static assets
# Create systemd service
sudo cat > /etc/systemd/system/solidstart.service