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).
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" } });
}