Blog/content/2025/10/building-with-bun.md

3.3 KiB

title date tags excerpt draft
Building a Modern Blog with Bun and TypeScript 2025-10-20
Web Development
TypeScript
JavaScript
A deep dive into building a performant, modern blog using Bun's runtime, TypeScript, and server-side rendering. Learn about the architecture decisions and tradeoffs. false

Building a Modern Blog with Bun and TypeScript

When I set out to build this blog, I had a few key requirements in mind: fast page loads, minimal JavaScript shipped to the client, and a great developer experience. Here's how I achieved all three.

Why Bun?

Bun is an all-in-one JavaScript runtime that's significantly faster than Node.js for many operations. It includes:

  • A blazing-fast JavaScript/TypeScript runtime
  • Built-in bundler
  • Native TypeScript support
  • Package manager
  • Test runner

For this blog, the combination of native TypeScript support and the built-in bundler made Bun an obvious choice.

Architecture Overview

The blog uses a hybrid approach:

Server-Side Rendering

All HTML is generated on the server using JSX as a templating language. This means:

  • Fast initial page loads - No waiting for JavaScript to download and execute
  • SEO friendly - Search engines see fully rendered HTML
  • Works without JavaScript - Core functionality doesn't depend on client-side JS

AppShell Pattern

The blog implements an "AppShell" pattern where:

  1. First visit loads the full page with AppShell (sidebar, header, etc.)
  2. Navigation replaces only the <main> content
  3. Subsequent requests send a custom header to indicate AppShell is already loaded
  4. Server returns just the content, not the full shell

This gives us SPA-like navigation speed with SSR benefits.

Markdown Processing

Blog posts are written in Markdown and processed at build time:

// Simplified example
import { marked } from 'marked';

const html = marked.parse(markdownContent);

The plugin:

  • Scans the content directory
  • Parses frontmatter (title, date, tags, etc.)
  • Converts markdown to HTML
  • Stores everything in SQLite for fast queries

Performance Results

The result? Page loads under 128KB including:

  • All HTML
  • All CSS (inlined)
  • Minimal JavaScript for interactivity

First contentful paint happens in under 100ms on a fast connection.

Developer Experience

With Bun's --watch flag, the entire development workflow is seamless:

bun run --watch ./index.tsx

This watches for changes and hot-reloads the server. Combined with the markdown plugin, changing a blog post immediately reflects in the browser.

Lessons Learned

What Worked Well

  • JSX for templating - Familiar, type-safe, and no new syntax to learn
  • SQLite for search - Fast, embedded, and perfect for a small blog
  • Bun's speed - Development is incredibly fast

What Could Be Better

  • Hot reloading - Would love client-side HMR for styles
  • Build step - Currently all processing happens at runtime
  • TypeScript types - Virtual modules need proper type definitions

Conclusion

Building with Bun has been a great experience. The performance is excellent, and the developer experience is top-notch. If you're building a new project and want to try something modern, I highly recommend giving Bun a shot.

The code for this blog is open source - check it out on GitHub!