Quickstart
Build your first app with Bun
Overview
Build a minimal HTTP server with Bun.serve, run it locally, then evolve it by installing a package.
- Step 1
Initialize a new project with
bun init.terminalbun init my-appbun initprompts you to pick a template:Blank,React, orLibrary. For this guide, pickBlank.terminalbun init my-appText✓ Select a project template: Blank + .gitignore + CLAUDE.md + .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc -> CLAUDE.md + index.ts + tsconfig.json (for bun check and editor autocomplete) + README.mdThe new
my-appdirectory contains a basic Bun app. - Step 2
Run
index.tswithbun run.terminalcd my-app bun run index.tsTextHello via Bun! - Step 3
Replace the contents of
index.tswith the following code:index.ts
const server = Bun.serve({ port: 3000, routes: { "/": () => new Response('Bun!'), } }); console.log(`Listening on ${server.url}`);Run
index.tsagain.terminalbun run index.tsTextListening on http://localhost:3000/Visit
http://localhost:3000to test the server. You should see a page that says"Bun!".Seeing TypeScript errors on Bun?
bun initinstalls Bun's TypeScript declarations and configures yourtsconfig.json. If you're trying out Bun in an existing project, you may see a type error on theBunglobal.To fix this, first install
@types/bunas a dev dependency.terminalbun add -d @types/bunThen add the following to your
compilerOptionsintsconfig.json:tsconfig.json{ "compilerOptions": { "lib": ["ESNext"], "target": "ESNext", "module": "Preserve", "moduleDetection": "force", "moduleResolution": "bundler", "allowImportingTsExtensions": true, "verbatimModuleSyntax": true, "noEmit": true } } - Step 4
Install the
figletpackage and its type declarations. Figlet is a utility for converting strings into ASCII art.terminalbun add figlet bun add -d @types/figlet # TypeScript users onlyUpdate
index.tsto usefigletinroutes.index.ts
import figlet from 'figlet'; // [!code ++] const server = Bun.serve({ port: 3000, routes: { "/": () => new Response('Bun!'), "/figlet": () => { // [!code ++] const body = figlet.textSync('Bun!'); // [!code ++] return new Response(body); // [!code ++] } // [!code ++] } }); console.log(`Listening on ${server.url}`);Run
index.tsagain.terminalbun run index.tsTextListening on http://localhost:3000/Visit
http://localhost:3000/figletto test the server. You should see a page that says"Bun!"in ASCII art.Text____ _ | __ ) _ _ _ __ | | | _ \| | | | '_ \| | | |_) | |_| | | | |_| |____/ \__,_|_| |_(_) - Step 5
Now add some HTML. Create a new file called
index.html:index.html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Bun</title> </head> <body> <h1>Bun!</h1> </body> </html>Then, import this file in
index.tsand serve it from the root/route.index.ts
import figlet from 'figlet'; import index from './index.html'; // [!code ++] const server = Bun.serve({ port: 3000, routes: { "/": index, // [!code ++] "/figlet": () => { const body = figlet.textSync('Bun!'); return new Response(body); } } }); console.log(`Listening on ${server.url}`);Run
index.tsagain.terminalbun run index.tsTextListening on http://localhost:3000/Visit
http://localhost:3000to test the server. You should see the static HTML page.
You've built an HTTP server with Bun and installed a package.
Run a script
Bun can also execute "scripts" from your package.json. Add the following script:
{
"name": "my-app",
"module": "index.ts",
"type": "module",
"private": true,
"scripts": { // [!code ++]
"start": "bun run index.ts" // [!code ++]
}, // [!code ++]
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^7"
}
}
Then run it with bun run start.
bun run start
Listening on http://localhost:3000/