Building a Self-Hosted Blog with Vite
January 5, 2025
vitejavascriptself-hosting
I recently added a blog to my portfolio site. Here's how it works.
The Goal
I wanted a blog that:
- Uses markdown for writing posts
- Has syntax highlighting for code
- Generates static HTML (no client-side rendering)
- Fits the existing terminal aesthetic
The Stack
The implementation uses three key libraries:
- marked - Markdown to HTML conversion
- highlight.js - Syntax highlighting for code blocks
- gray-matter - Parsing YAML frontmatter
How It Works
Posts are written as markdown files in src/posts/:
---
title: "Post Title"
date: "2025-01-05"
description: "A short description"
tags: ["tag1", "tag2"]
---
Your content here...
At build time, a Node script processes each post:
import { marked } from 'marked';
import hljs from 'highlight.js';
import matter from 'gray-matter';
// Configure syntax highlighting
marked.setOptions({
highlight: function(code, lang) {
if (lang && hljs.getLanguage(lang)) {
return hljs.highlight(code, { language: lang }).value;
}
return hljs.highlightAuto(code).value;
}
});
// Parse frontmatter and content
const { data, content } = matter(fileContent);
const html = marked(content);
The Result
Each post becomes a static HTML page at /blog/post-slug/. The listing page at /blog/ is also pre-rendered with all post cards.
No JavaScript required to read posts. No API calls. Just static HTML served by Nginx.
Why Static?
For a personal blog, static generation makes sense:
- Fast - No server-side rendering, just files
- Simple - No database, no backend to maintain
- Reliable - If Nginx is up, the blog is up
- Cheap - Minimal resources needed
The only downside is needing to rebuild when adding posts. But with a CI/CD pipeline, that's just a git push away.
Built with Vite + Tailwind CSS
Self-hosted on personal infrastructure