Build fullstack applications with Bun’s integrated dev server that bundles frontend assets and serves API routes in a single process.
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.
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.
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().
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.
Use bun build to bundle your full-stack application before deployment:
bun build --target=bun --production --outdir=dist ./server.ts
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.
Configure how process.env.* references are handled in frontend code:
bunfig.toml
[serve.static]env = "PUBLIC_*" # Only inline env vars with this prefix (recommended)# env = "inline" # Inline all env vars# env = "disable" # Disable env var inlining (default)
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.