frameworks
Frameworks
Which Node frameworks and dev servers run under Verklet today, and what to expect from each.
Verklet runs Node.js-style code, not arbitrary native binaries. That means most JavaScript frameworks work in principle; the question is which ones we've actually tested and what edge cases bite. This page walks through the current state. The compatibility matrix is the authoritative one-line summary; this page is the longer form.
Node HTTP servers — supported
A plain node:http server is the most exercised path. It boots fast,
ports route through the preview service worker, and server-ready
fires the moment the listen callback runs.
import { createServer } from 'node:http';
createServer((req, res) => {
res.writeHead(200, { 'content-type': 'text/plain' });
res.end('hello from a tab\n');
}).listen(3000);
This pattern is what the playground ships out of the
box. Express works too — it's just node:http with middleware on top —
though the npm install step adds a one-time cost on cold boot.
Vite-style dev server — partial
A built-in shim implements enough of Vite's dev-server contract (module
graph, HMR over WebSocket, static asset serving) for simple React, Vue,
and Svelte starters to come up. The vite command routes to this shim
by default.
What's there:
- File watching → module invalidation → client refresh.
- Plain ESM,
.jsx/.tsxwith esbuild-style transform. - WebSocket HMR + EventSource fallback.
- Static file serving from
public/.
What's not:
- Custom Vite plugins that touch the resolver. Most plugin APIs aren't hooked up.
- SSR / server functions. The shim is dev-server-only.
- The full optimizer pipeline. Slow-to-compile deps may take longer than they would under real Vite.
You can switch to the real Vite CLI by passing
viteMode: 'real' to Runtime.boot() and ensuring vite is in your
mounted node_modules. That path runs the genuine CLI in a
node-compat worker; it's slower to start but matches Vite's behaviour
exactly. The shim is the default for now and is targeted for removal
once the real CLI is the proven default.
Next.js — partial
A minimal Next app (app router, no server actions, no middleware, no edge runtime) will build and serve. The supported workflow is:
- Mount a project with
nextinnode_modules. - Spawn
next dev— it binds a port; the preview SW routes it. - Edit a page, see the dev server reload.
What's likely to bite:
- Server actions call out to the framework's RPC system, which expects a real server environment. Not wired up.
- Edge runtime routes assume Vercel's edge primitives. Not available in-browser.
- Image optimisation uses sharp, a native dep. Use plain
<img>ornext/imagewithunoptimized. - Build → start mode works in narrow cases. Stick to
next devfor tutorial / demo use.
This compatibility band is the same shape as the rest of the "meta-framework on top of Node" category: the dev loop tends to work; the production-server features tend not to.
Vue, Svelte, SvelteKit — partial
Vue + Vite, Svelte + Vite, and a minimal SvelteKit dev server all come up. The same caveats as Vite apply (plugin coverage, real-vs-shim mode). SvelteKit's adapter system targets Vercel/Node/Cloudflare flavours; only the dev adapter is exercised today.
Nuxt, Astro, Remix, React Router — partial
Each of these has a "dev mode that runs on top of Vite" path and a "production server" path. The dev path works in narrow cases (Nuxt's Nitro init is the most finicky; Astro is the simplest). The production build/serve path is generally not exercised.
If you're embedding one of these for a tutorial or a customer demo, test the specific commands you intend to call. The compatibility matrix is conservative — "partial" means "we've seen it work for the canonical starter, not that every plugin combination boots."
What's intentionally out of scope
- Native addons.
node-gyp-built modules and.nodebinaries don't run. The runtime rejects them with a documented shim option. child_process. Spawning OS processes is meaningless inside a worker; the API surface is present but most calls error out.- TLS server. You can act as an HTTPS client; you cannot terminate TLS. The preview service worker handles transport.
If a framework you care about isn't on this page, it's not necessarily broken — it's likely just untested. Open an issue at github.com/verklet/verklet with the minimal repro and we'll add it to the matrix.