Using Bun.serve()
's routes
option, you can run your frontend and backend in the same app with no extra steps.
To get started, import HTML files and pass them to the routes
option in Bun.serve()
.
import { sql, serve } from "bun";
import dashboard from "./dashboard.html";
import homepage from "./index.html";
const server = serve({
routes: {
// ** HTML imports **
// Bundle & route index.html to "/". This uses HTMLRewriter to scan the HTML for `<script>` and `<link>` tags, run's Bun's JavaScript & CSS bundler on them, transpiles any TypeScript, JSX, and TSX, downlevels CSS with Bun's CSS parser and serves the result.
"/": homepage,
// Bundle & route dashboard.html to "/dashboard"
"/dashboard": dashboard,
// ** API endpoints ** (Bun v1.2.3+ required)
"/api/users": {
async GET(req) {
const users = await sql`SELECT * FROM users`;
return Response.json(users);
},
async POST(req) {
const { name, email } = await req.json();
const [user] =
await sql`INSERT INTO users (name, email) VALUES (${name}, ${email})`;
return Response.json(user);
},
},
"/api/users/:id": async req => {
const { id } = req.params;
const [user] = await sql`SELECT * FROM users WHERE id = ${id}`;
return Response.json(user);
},
},
// Enable development mode for:
// - Detailed error messages
// - Hot reloading (Bun v1.2.3+ required)
development: true,
// Prior to v1.2.3, the `fetch` option was used to handle all API requests. It is now optional.
// async fetch(req) {
// // Return 404 for unmatched routes
// return new Response("Not Found", { status: 404 });
// },
});
console.log(`Listening on ${server.url}`);
bun run app.ts
HTML imports are routes
The web starts with HTML, and so does Bun's fullstack dev server.
To specify entrypoints to your frontend, import HTML files into your JavaScript/TypeScript/TSX/JSX files.
import dashboard from "./dashboard.html";
import homepage from "./index.html";
These HTML files are used as routes in Bun's dev server you can pass to Bun.serve()
.
Bun.serve({
routes: {
"/": homepage,
"/dashboard": dashboard,
}
fetch(req) {
// ... api requests
},
});
When you make a request to /dashboard
or /
, Bun automatically bundles the <script>
and <link>
tags in the HTML files, exposes them as static routes, and serves the result.
An index.html file like this:
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
<link rel="stylesheet" href="./reset.css" />
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<div id="root"></div>
<script type="module" src="./sentry-and-preloads.ts"></script>
<script type="module" src="./my-app.tsx"></script>
</body>
</html>