Skip to content

Dev Server

vantris dev starts a native development server — Node.js node:http or Bun.serve, with no HTTP or WebSocket dependency. Both runtimes go through the same createDevServer(), so behaviour is identical under Node.js and Bun.

bash
vantris dev            # → http://localhost:3000

What the dev server does

  • Serves index.html as the entry document, injecting the HMR client.
  • Transpiles .ts/.tsx on the fly with esbuild — transform only, no bundling. Each module is served individually, so startup is instant and unaffected by app size.
  • Resolves bare imports through an on-demand dependency bundler into node_modules/.vantris/deps/. CommonJS packages get real named exports, and subpath imports (react-dom/client) work.
  • Serves CSSimport "./x.css" becomes a processed, style-injecting module; a <link> is served as text/css. See CSS.
  • Inlines asset imports — images, fonts, media, wasm, txt, json. See Static Assets.
  • Drives Hot Module Replacement over a typed WebSocket protocol.

Configuration

Host and port live in the dev block; everything about the networking layer (HTTPS, proxy, CORS, SPA fallback, base) lives in server.

ts
import { defineConfig } from "vantris";

export default defineConfig({
  dev: {
    port: 3000,       // default
    host: "localhost", // default
  },
});

Binding to your network

By default the server binds to localhost and is only reachable from your machine. Expose it on the LAN with --host:

bash
vantris dev --host          # all interfaces (0.0.0.0)
vantris dev --host 0.0.0.0
vantris dev --host 192.168.1.42

When bound to a shared address, both a Local and a Network URL are printed on start.

The serving allowlist

Serving follows a Vite-style allowlist — this is a security boundary, not a convenience:

  • Source modules come from rootDir (/src/*).
  • public/ contents are served at /.
  • Everything else under the project root — node_modules, package.json, lockfiles, config files — is not reachable.

So a stray fetch("/vantris.config.ts") in the browser returns a 404, and your secrets and tooling files never leak into a page.

Error overlay

When a module fails to transpile or a transform throws, the dev server pushes a type: "error" message over HMR and the browser shows a dismissable in-browser overlay with the message and location. It's cleared automatically on the next successful update — so you fix the file, save, and the overlay disappears with the applied change.

Dependency handling

The first time a bare import is requested, Vantris bundles that package on demand and caches the result. You never list your dependencies. Two options tune this:

ts
export default defineConfig({
  optimizeDeps: {
    include: ["react", "react-dom/client"], // pre-bundle at startup
    exclude: ["some-esm-only-lib"],          // serve as native ESM
  },
});

Modules served from /@vantris/deps/ are marked third-party, so Chrome DevTools greys them out in Sources and skips them while stepping. See Dependency Pre-Bundling for the full model.

Networking features

The server block turns on HTTPS, request proxying, CORS, and the SPA fallback:

ts
export default defineConfig({
  server: {
    https: true,                                   // self-signed dev cert
    proxy: { "/api": "http://localhost:8080" },    // proxy a prefix
    cors: { origin: ["http://localhost:3000"] },   // CORS headers
    spaFallback: true,                             // history fallback (default)
    base: "/app/",                                 // mount under a sub-path
  },
});

Each is covered on the Networking page and in the Server Options reference.

Plugins in dev

Plugin hooks run in the dev server just as they do in the build: resolveId/load/transform shape the module pipeline, transformIndexHtml rewrites the served HTML, handleHotUpdate customises HMR, and configureServer gives a plugin access to the running server. See the Plugin API.

Under the hood

The dev server never bundles your source in development — it transforms each module individually and lets the browser's native ES module loader assemble the graph. Dependencies are the exception: they're pre-bundled so you don't ship hundreds of node_modules requests to the browser. This "transform, don't bundle" model is why the dev server is fast regardless of how large the app grows.

Released under the MIT License.