Skip to main content
Bun’s Bun.serve() integrates directly with the bundler, letting you serve HTML, TypeScript, JSX, and CSS from a single server process with hot module reloading in development and optimized production builds.

Quick start

Import HTML files and pass them to the routes option in Bun.serve():
server.ts

HTML routes

HTML as an entrypoint

The web starts with HTML, and so does Bun’s fullstack dev server. Import an HTML file directly from your TypeScript or JavaScript server code:
Pass these to routes in Bun.serve():
When a request arrives for /, Bun scans the HTML for <script> and <link> tags, runs the bundler on the referenced files, and serves the result.

What Bun does to your HTML

An index.html like this:
index.html
Gets transformed into:
Multiple <script> tags are combined into a single bundle, and multiple CSS files are merged into one stylesheet. Asset URLs are content-hashed for cache busting.

Processing pipeline

1

Script processing

Transpiles TypeScript, JSX, and TSX from <script> tags. Bundles imported dependencies. Generates sourcemaps for debugging. Minifies when development is false.
2

CSS processing

Processes <link rel="stylesheet"> tags. Concatenates CSS files and rewrites url() references to include content-addressable hashes.
3

Asset processing

Rewrites image and font URLs to include content-addressable hashes. Small assets in CSS are inlined as data: URLs to reduce HTTP requests.
4

HTML rewriting

Combines all <script> tags into one and all <link> tags into one, producing a new HTML file that references the bundled assets.
5

Serving

Bundled files are exposed as static routes using Bun’s built-in static file serving. The same mechanism as passing a Response to static in Bun.serve().

React integration

No Webpack, Vite, or Create React App required. Bun handles transpilation and bundling automatically.

Development mode

Enable development mode with development: true:
In development mode, Bun:
  • Includes sourcemaps so devtools show original source
  • Disables minification
  • Re-bundles assets on each request to an .html route
  • Enables hot module reloading (HMR)
  • Echoes console.log calls from the browser to the terminal

Hot module replacement

HMR is enabled by default in development mode. To configure it explicitly:
When console: true is set, console.log(), console.warn(), and console.error() calls from your frontend code are forwarded to the terminal over the same WebSocket connection used for HMR.

Development vs production comparison

API routes

HTTP method handlers

Dynamic routes

Production builds

Use bun build to bundle your full-stack application before deployment:
When the bundler sees an HTML import in server-side code, it bundles the frontend assets and replaces the import with a manifest object that Bun.serve() uses to serve pre-bundled assets.

Runtime bundling

Set development: false to enable in-memory caching without a build step:
With development: false, Bun:
  • Bundles assets lazily on the first request
  • Caches the result in memory until the server restarts
  • Adds Cache-Control and ETag headers
  • Minifies JavaScript

Docker deployment

Dockerfile

Plugins

Bundler plugins work when bundling static routes. Configure them in bunfig.toml:
bunfig.toml

TailwindCSS

bunfig.toml
index.html

Custom plugins

bunfig.toml
my-plugin.ts

Inline environment variables

Configure how process.env.* references are handled in frontend code:
bunfig.toml
Only literal process.env.FOO references are replaced — not import.meta.env or dynamic access. If an environment variable is not set, you may see ReferenceError: process is not defined in the browser.

Project structure

A recommended structure for a Bun fullstack application:
The fullstack dev server is still evolving. CLI integration with bun build, file-based API routing, and built-in SSR are planned for future releases.