10LOC

Bun

Bunintermediate

Use Bun.write for zero-dependency file output

import { write } from "bun";

export const saveJsonReport = (path: string, report: Record<string, unknown>) =>
  write(path, JSON.stringify(report, null, 2) + "\n");

Write files in Bun without extra dependencies or shelling out.

Bunintermediate

A tiny Bun test fixture helper

import { beforeEach, afterEach, test, expect } from "bun:test";
import { file } from "bun";
import { mkdtemp, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";

Keep Bun tests small by extracting repeated setup into a fixture helper.

Bunadvanced

On-the-fly TS/JSX transforms with Bun.Transpiler

const transpiler = new Bun.Transpiler({ loader: "tsx" });

const source = `
  interface Props { name: string }
  export const Greeting = (props: Props) => <h1>Hello, {props.name}!</h1>;

Bun.Transpiler exposes Bun's own TS/JSX-to-JS compiler as a callable class, for transforming source strings at runtime without shelling out to a build step.

Bunadvanced

Parallel work with Bun's Worker

export const countPrimesOnWorker = (from: number, to: number) => {
  const workerCode = `
    self.onmessage = ({ data: [from, to] }) => {
      let count = 0;
      for (let n = from; n < to; n++) {

Bun's Worker API uses real OS threads, so CPU-bound work can be split across workers created from an in-memory blob: URL, with no separate worker file needed.

Bunintermediate

Benchmarking Bun's cold start against Node with performance.now()

const measureColdStart = (cmd: string[]) => {
  const start = performance.now();
  Bun.spawnSync(cmd);
  return performance.now() - start;
};

Bun.spawnSync plus performance.now() around each call turns a cold-start comparison against Node into a five-line, dependency-free benchmark.

Bunintermediate

A static file router that falls back to Bun.file

import { serve, file } from "bun";

const PUBLIC_DIR = `${import.meta.dir}/public`;

const server = serve({

A fetch handler can serve API routes first and fall back to Bun.file for anything else, building a static file server without a separate static-file middleware.

Bunadvanced

Calling a C function from Bun via bun:ffi

import { dlopen, FFIType, suffix } from "bun:ffi";

const path = `libsqlite3.${suffix}`;

const { symbols } = dlopen(path, {

bun:ffi's dlopen loads a shared library and JIT-compiles a JS-to-native binding for each symbol, letting Bun call C functions directly with no N-API glue code.

Bunintermediate

Bun's automatic .env loading vs the dotenv package

declare module "bun" {
  interface Env {
    DATABASE_URL: string;
    DEBUG?: string;
  }

Bun parses .env, .env.local, and .env.production automatically before your code runs, so import 'dotenv/config' is not just unnecessary but dead weight.

Bunintermediate

Hot-reloading a dev server with bun --hot

declare global {
  var server: ReturnType<typeof Bun.serve> | undefined;
  var reloadCount: number;
}

bun --hot re-evaluates changed files without restarting the process, so an HTTP server's listener survives a save instead of dropping every open connection.

Bunadvanced

Piped-stdio subprocesses with Bun.spawn

const proc = Bun.spawn(["bun", "-e", "console.log((await Bun.stdin.text()).toUpperCase())"], {
  stdin: "pipe",
});

proc.stdin.write("hello from the parent\n");

Bun.spawn's stdin/stdout are a FileSink and a ReadableStream, so you can write to a child process incrementally and read its output as it streams back.

Bunintermediate

A WebSocket server using Bun.serve's built-in upgrade

export const wsServer = Bun.serve({
  fetch(req, server) {
    return server.upgrade(req) ? undefined : new Response("Upgrade failed", { status: 500 });
  },
  websocket: {

Bun.serve() upgrades an HTTP request to a WebSocket in the fetch handler and reuses one handler object across every connection, no ws package needed.

Bunadvanced

Bundling programmatically with Bun.build()

try {
  const result = await Bun.build({
    entrypoints: ["./src/index.ts"],
    outdir: "./dist",
    minify: true,

Bun.build() is the bun build CLI as a JS function, returning artifacts you can inspect, write, or serve directly instead of shelling out.

Bunintermediate

Password hashing with Bun.password, no bcrypt dependency

export const hashPassword = (password: string) =>
  Bun.password.hash(password, { algorithm: "argon2id", memoryCost: 19456, timeCost: 2 });

export const verifyPassword = (password: string, hash: string) => Bun.password.verify(password, hash);

Bun.password.hash and .verify wrap argon2 and bcrypt natively, so hashing a password needs no bcrypt or argon2 npm package at all.

Bunintermediate

Snapshot testing with bun:test in 10 lines

import { test, expect } from "bun:test";

const formatInvoice = (id: number, cents: number) => ({
  id,
  total: `$${(cents / 100).toFixed(2)}`,

toMatchSnapshot() saves a value's serialized shape on first run and diffs it on every run after, catching output changes you didn't write assertions for.

Bunintermediate

Bun.$ shell scripting for cross-platform build scripts

import { $ } from "bun";

await $`rm -rf dist`;
await $`mkdir dist`;

Bun's $ template literal runs a small bash-like shell with no /bin/sh dependency, so build scripts behave identically on Windows, macOS, and Linux.

Bunintermediate

Streaming a file response with Bun.file(), no extra deps

import { serve, file } from "bun";

const server = serve({
  async fetch(req) {
    const pathname = new URL(req.url).pathname;

Bun.file() returns a lazy file handle that streams straight into a Response, so serving a large file never buffers it fully in memory.

Bunintermediate

Querying bun:sqlite, Bun's built-in embedded database

import { Database } from "bun:sqlite";

const db = new Database(":memory:");
db.exec(`CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)`);

bun:sqlite ships inside the Bun binary with a synchronous, prepared-statement API, so a local database needs zero npm installs.

Bunintermediate

Bun.serve() with a routes object: a zero-dependency HTTP server

export const app = Bun.serve({
  routes: {
    "/api/health": new Response("ok"),
    "/api/users/:id": (req) => Response.json({ id: req.params.id }),
    "/api/users": {

Bun.serve()'s routes option matches paths, HTTP methods, and :params natively, replacing a router dependency for most REST APIs.