Bun & Hono Development Standards

evergreenLast update on Jul 9, 2026
Download .md

Project Layout

project/
├── src/
│   ├── index.ts          # Entry point
│   ├── routes/           # Route handlers
│   ├── middleware/       # Hono middleware
│   ├── db/               # Drizzle / raw SQL
│   ├── types/            # TypeScript types
│   └── utils/            # Helpers
├── tests/
├── drizzle/              # Migrations
├── docker/
├── package.json
├── bun.lockb
└── tsconfig.json

Hono Router

import { Hono } from "hono";

const app = new Hono();

app.get("/users", async (c) => {
  const users = await db.select().from(usersTable);
  return c.json({ data: users });
});

app.post("/users", async (c) => {
  const body = await c.req.json();
  const user = await db.insert(usersTable).values(body).returning();
  return c.json({ data: user }, 201);
});

export default app;

Validation

Gunakan Zod untuk validasi:

import { z } from "zod";

const createUserSchema = z.object({
  name: z.string().min(2),
  email: z.string().email(),
});

app.post("/users", async (c) => {
  const body = await c.req.json();
  const parsed = createUserSchema.safeParse(body);

  if (!parsed.success) {
    return c.json({ error: parsed.error.flatten() }, 400);
  }

  // ...
});

Database

Gunakan Drizzle ORM dengan PostgreSQL:

import { drizzle } from "drizzle-orm/node-postgres";

const db = drizzle({ connection: process.env.DATABASE_URL });

Testing

Gunakan Bun test runner (built-in):

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

describe("user routes", () => {
  it("creates a user", async () => {
    const res = await app.request("/users", {
      method: "POST",
      body: JSON.stringify({ name: "Khoirul", email: "test@example.com" }),
    });

    expect(res.status).toBe(201);
  });
});

Docker Multi-Stage

Gunakan Bun multi-stage build untuk image kecil:

FROM oven/bun:1 AS base
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun build ./src/index.ts --outdir ./out

FROM oven/bun:1-slim
WORKDIR /app
COPY --from=base /app/out .
EXPOSE 3000
CMD ["bun", "run", "index.js"]

Hot Reload

bun --hot run src/index.ts