It is 4:30 AM. I have had 4 cups of cappuccino from the evening till night and I am also dealing with a bit of loose motion. Neither is letting me sleep. I have to attend office at 9 but don't know if the loose motion will even let me. So I sit down and started coding.
I do not have a personal website. I figure if I am going to be awake anyway I might as well build one.
By morning I have a working portfolio and blog. No CMS. No database. Just files.
The stack
- Next.js
- MDX for contents
No CMS
The whole content system is just a folder called content/. Each blog post is an .mdx file with some metadata at the top.
---
title: "My Post Title"
publishedAt: "2024-03-20"
summary: "A short description."
---
Your content goes here.You write a file. Push to git. The site rebuilds. That is it.
How it works
A small utility reads the content/ folder at build time. It uses gray-matter to parse the metadata and reading-time to calculate how long a post takes to read.
import fs from "fs";
import path from "path";
import matter from "gray-matter";
import readingTime from "reading-time";
const CONTENT_DIR = path.join(process.cwd(), "content", "blog");
export function getPostBySlug(slug: string) {
const filePath = path.join(CONTENT_DIR, `${slug}.mdx`);
const source = fs.readFileSync(filePath, "utf-8");
const { data, content } = matter(source);
const stats = readingTime(content);
return {
meta: { ...data, slug, readingTime: stats.text },
content,
};
}Then next-mdx-remote renders the MDX on the server. No client side JavaScript needed for the content.
The structure
content/blog/*.mdx- blog posts versioned in gitsrc/lib/blog.ts- reads files and parses metadatasrc/app/blog/[slug]/page.tsx- renders each post with SSGsrc/components/mdx-components.tsx- custom renderers for links and images
Every page is static. The metadata function pulls title and summary from the file to generate OpenGraph and Twitter cards automatically.
Code highlighting
rehype-pretty-code handles syntax highlighting. You just write normal code blocks and it does the rest.
function greet(name) {
const message = `Hello, ${name}!`;
console.log(message);
return message;
}What I learned
- You do not need a CMS for a personal site. A folder of files works fine.
- MDX gives you React inside markdown without the complexity.
- Sometimes the best time to build something is when you cannot sleep.
Not consuming caffeine after 7 PM from now on. Atleast I will give it a try.