Building This Blog
Building This Blog
This blog has no framework, no build step, and exactly one external dependency: marked.js for rendering markdown. Here's how it works.
Architecture
The entire site is a single HTML page. Navigation is handled with hash routing — the URL fragment determines what to show:
#/— the home page, a list of posts#/post/hello-world— an individual post
When you click a post, the app fetches the corresponding .md file, runs it through marked.js, and injects the resulting HTML into the page. That's it.
The manifest
Posts are indexed in a manifest.json file:
{
"title": "Hello, World",
"slug": "hello-world",
"date": "2025-01-15",
"excerpt": "A first post to break the silence."
}
The app loads this file once, then uses it to build the post list and look up metadata for individual posts.
Adding a new post
Two steps:
- Create a
.mdfile in theposts/folder - Add an entry to
posts/manifest.json
No compilation, no deployment pipeline. Save the files and refresh.
Styling
The design is inspired by Bear's Red Graphite theme — warm off-white background, soft black text, a pop of red for links. The typography uses Avenir Next with generous line-height and a narrow content column.
The CSS is one file, under 200 lines. No preprocessor, no utility classes, no design system. Just styles.
Trade-offs
This approach has real limitations:
- No server-side rendering. Search engines may not index the content well.
- No syntax highlighting. Code blocks are plain text.
- Client-side fetching. Each post requires a network request.
For a personal blog with a handful of posts, these trade-offs are fine. If they weren't, I'd reach for something heavier. But right now, the simplicity is the point.
The stack
| Layer | Choice |
|---|---|
| Markup | Plain HTML |
| Styles | Plain CSS |
| Logic | Vanilla JS |
| Content | Markdown |
| Rendering | marked.js (CDN) |
| Server | Any static file host |
Sometimes less really is more.
← Back to posts