DEV Community

Alex Spinov
Alex Spinov

Posted on

SolidStart Has a Free API That Makes Solid.js a Full-Stack Framework

SolidStart is the meta-framework for Solid.js — file-based routing, server functions, and streaming SSR with Solid's fine-grained reactivity.

File-Based Routing

src/routes/
  index.tsx           → /
  about.tsx           → /about
  products/
    index.tsx         → /products
    [id].tsx          → /products/:id
  api/
    products.ts       → /api/products
Enter fullscreen mode Exit fullscreen mode

Server Functions: RPC Without an API

"use server";

import { db } from "./db";

export async function getProducts(category?: string) {
  return db.product.findMany({
    where: category ? { category } : {},
    orderBy: { createdAt: "desc" },
    take: 20,
  });
}

export async function createProduct(data: { title: string; price: number; url: string }) {
  return db.product.create({ data });
}
Enter fullscreen mode Exit fullscreen mode
// In your component — calls server function directly!
import { createResource } from "solid-js";
import { getProducts } from "./server";

function ProductList() {
  const [products] = createResource(() => getProducts("electronics"));

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

createAsync: Data Loading

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

const getProductData = cache(async (id: string) => {
  "use server";
  return db.product.findUnique({ where: { id } });
}, "product");

export function routeData({ params }) {
  return { product: createAsync(() => getProductData(params.id)) };
}

export default function ProductPage() {
  const { product } = useRouteData();
  return <h1>{product()?.title}</h1>;
}
Enter fullscreen mode Exit fullscreen mode

Signals: Fine-Grained Reactivity

import { createSignal, createEffect, createMemo, For, Show } from "solid-js";

function Dashboard() {
  const [filter, setFilter] = createSignal("");
  const [products, setProducts] = createSignal([]);

  const filtered = createMemo(() =>
    products().filter(p => p.title.toLowerCase().includes(filter().toLowerCase()))
  );

  createEffect(() => {
    console.log(`Showing ${filtered().length} products`);
  });

  return (
    <div>
      <input onInput={(e) => setFilter(e.target.value)} placeholder="Search..." />
      <Show when={filtered().length > 0} fallback={<p>No products found</p>}>
        <For each={filtered()}>
          {(product) => <ProductCard product={product} />}
        </For>
      </Show>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

API Routes

// src/routes/api/products.ts
import { APIEvent } from "@solidjs/start/server";

export async function GET(event: APIEvent) {
  const url = new URL(event.request.url);
  const category = url.searchParams.get("category");
  const products = await db.product.findMany({ where: { category } });
  return Response.json(products);
}

export async function POST(event: APIEvent) {
  const body = await event.request.json();
  const product = await db.product.create({ data: body });
  return Response.json(product, { status: 201 });
}
Enter fullscreen mode Exit fullscreen mode

Build reactive data apps? My Apify tools + SolidStart = lightning-fast dashboards.

Custom solution? Email spinov001@gmail.com

Top comments (0)