01: Bun basics
bun init
To initialize a package.json along with other project specifications, run the command bun init, which also sets up typescript in your project
bun run
bun run is the stand-in replacement for the npm run command, used to run scripts or individual files.
However, where it differs is in automatic support for watch mode and hot reload with these options:
--watch: runs the file in watch mode, restarting state--hot: runs the file with hot reloading, keeping current state
The difference between watch mode and hot reload is that watch mode is stateless, meaning any state it has is reinitialized when it reloads the file, as opposed to hot reloading, which keeps the state.
Environment variables
All environment variables from any .env files are automatically loaded into process.env, so just use process.env to access any environment variables.
You can also set environment variables in scripts, like so by setting it in front of the command you're trying to run.
{
"scripts": {
"dev": "NODE_ENV=development bun run --watch index.ts"
}
}
You can also manually specify env files to load with the --env-file= option:
bun --env-file=.env.abc --env-file=.env.def run build
running HTML files
Bun has first class support for running html files, which works exactly like live server does for VSCode. This is great because you don't have to set up a server for simple frontend development.
bun index.html
All references to TSX and CSS in your HTML code will just work and compile out of the box.
You can also specify multiple index HTML entrypoints by manually adding them or specifying through a globa pattern.

bun install
bun install is the stand-in replacement for npm install
bunx
bunx is the standard replacement for npx , used to run scripts or local dependencies without installing them.
JSX
Bun supports JSX out of the box, but you can specify options in your tsconfig.json to support using different frameworks like preact or solidjs.
Here are the key configuration fields in the tsconfig.json to do:
jsx: Controls how JSX is transpiled. Options include"react","react-jsx", and"react-jsxdev"jsxImportSource: Module for JSX runtime whenjsxis"react-jsx"or"react-jsxdev"(e.g.,"preact") .
You can also set pragmas on an individual file if you want to avoid overriding for all JSX files:
// @jsxImportSource preact
The most important thing to realize here is that you can only change the JSX import source if the jsx setting is set to "react-jsx" or "react-jsxdev"
bun build
CLI
{
"scripts": {
"build": "bun build --outdir=./dist --watch ./src/app.ts ./src/sw.ts"
}
}
--outdir: the directory to put the bundle files into--watch: builds in watch mode
The other arguments are the entrypoints for bundling. Each entrypoint outputs to 1 js bundle file.
Building CSS
You can use bun build to compile CSS linking/importing other CSS files into one large, production-optimized CSS file:
@import "foo.css";
@import "bar.css";
Just like other bundlers, you can simply import your CSS into your JS or TS to make it work and then build with the TS as the entry point:
import "./style.css";
import MyComponent from "./MyComponent.tsx";
// ... rest of your app
compiling to binary
You can use the bun build --compile option to compile a tyepscript entry point into a binary for windows or mac.
bun build --compile --target=bun-windows-x64 app.ts
Here are the options you can configure:
--windows-icon=: for this option you pass the filepath to.icofile you want to be the icon for the binary--windows-hide-console: If set, then the console window will not be shown when executing the binary.--bytecode: makes your app startup faster by compiling to bytecode.--minify: makes the app executable smaller by minifying your code--sourcemap: builds a source map--outfile <file>: lets you name the executable
building for mac
bun build --compile --target=bun-darwin-arm64 ./path/to/my/app.ts --outfile myapp
building for production
Here are the best options to use when building for production:
bun build --compile --minify --sourcemap --bytecode ./path/to/my/app.ts --outfile myapp
Using Bun.build()
The Bun.build() method is a powerful API that lets you bundle your frontend code at blazing speed. It works with TS entrypoints, HTML entrypoints, and even CSS entrypoints.
await Bun.build({
entrypoints: [path.join(import.meta.dir, "frontend", "index.html")],
outdir: path.join(import.meta.dir, "dist"),
});
Here are all the options you can pass in to configure the build:
entrypoints: required. A list of entrypoints to build fromoutdir: required. the path to the directory you want the bundle to go to.target: the environment to build for. Here are the values you can pass:"bun": build for bun"node": build for node"browser": build for the browser
minify: whether to minify the bundle, a boolean. The default isfalse
TypeScript
By default, typescript with bun only works for server-side node and bun types. If you want to use typescript definitions in a browser context, like for window and document, put these triple slash directives at the top of any ts file that will get bundled into a browser js file:
/// <reference lib="dom" />
/// <reference lib="dom.iterable" />
Important API notes
Bun supports most web standards while also offering node compatibility. This leads to a lot of important details when it comes to Bun vs Node:
Bun vs Node
Bun prefers the ES6 syntax of using the import.meta instead of __dirname, so use that.
Supported web standards
- request and response web standards
- text decoder
Importing JSON files
You can import JSON files into your bun code directly as javascript objects to use:
import json from "./package.json" with { type: "json" };
typeof json; // "object"
import html from "./index.html" with { type: "text" };
typeof html; // "string"
import toml from "./bunfig.toml" with { type: "toml" };
typeof toml; // "object"