[]previous and next page

SolidStart

Dusk (@shadow-js/dusk) is the counterpart of SolidStart; read Dusk first and the Next.js guide for the server-side patterns (route handlers, actions, middleware).

For agentsUpdated

Dusk (@shadow-js/dusk) is the counterpart of SolidStart; read Dusk first and the Next.js guide for the server-side patterns (route handlers, actions, middleware). The mapping:

SolidStart Dusk
app.config.ts, Vinxi vite.config.ts with dusk() from @shadow-js/dusk/vite
entry-client.tsx (mount(() => <StartClient />)) The generated client entry (hydrateDusk), or your own src/entry-client.ts
entry-server.tsx (createHandler) createHandler from @shadow-js/dusk/server; its options live in src/entry-server.ts
FileRoutes, src/routes/* src/routes/*: [id].tsx, [...rest].tsx, (group)/, _layout.tsx; see routing
"use server", server functions, getRequestEvent serverFn or "use server", and getRequestEvent, from @shadow-js/dusk/server; see server functions
query, createAsync, action, <form action> A route loader that calls a server function with useLoaderData, useResource, useOptimistic, router.invalidate() after a mutation; a <form onSubmit>
API routes, middleware, sessions, cookies, CSRF routes/api/* method exports, the middleware option, createSessionManager, event.cookies, CSRF checks on by default; clerkMiddleware for Clerk
HttpStatusCode, HttpHeader Throw HttpError(status) or redirect(); headers on event.responseHeaders or the Response
Streaming SSR with deferStream mode: "stream" is the default; a useResource with deferStream: true created in the shell holds the first flush until it settles. Route loader data already resolves before the page renders, so route data needs no flag
Prerendering, static adapter, deployment presets export const prerender in a route, @shadow-js/dusk/static, the Node server; no other presets
import.meta.env, VITE_ variables import.meta.env, but only DUSK_PUBLIC_ names are allowed in client code

Without Dusk, a Response around the stream is the whole server-side contract:

src/server-handler.tsxtsx
import { Suspense } from "@shadow-js/web";
import { createComponent, renderToStream } from "@shadow-js/web/server";

function App() {
  return (
    <main>
      <Suspense fallback={<p>loading</p>}>
        <p>ready</p>
      </Suspense>
    </main>
  );
}

export function handle(_request: Request): Response {
  const stream = renderToStream(() => createComponent(App, {}), { renderId: "0" });
  return new Response(stream, { headers: { "content-type": "text/html; charset=utf-8" } });
}