· 1 min read · #engineering #nextjs
How this site is built
Next.js, Tailwind, markdown files and a handful of small client components. Notes on a site that tries to stay out of the way.
Every note here is a plain markdown file in the repo. No database, no login screen standing between me and writing. This note doubles as the documentation.
Adding a note#
Drop a .md file into content/posts/. The filename becomes the URL:
content/posts/my-new-note.md → lanka.lol/notes/my-new-note
The frontmatter carries everything the site needs:
---
title: "My new note"
description: "One or two sentences for lists, RSS, and social cards."
date: "2026-08-26"
tags: ["ai", "engineering"]
draft: false
---
draft: true keeps a note out of every list and feed; it only renders when opened directly in development.
The pipeline#
At build time each file goes through gray-matter for frontmatter, then a unified/remark/rehype chain: GFM tables and task lists, heading slugs, anchored headings, and Shiki for syntax highlighting. Light and dark themes are baked in as CSS variables, so there is no client-side highlighter and no flash.
export function readingMinutes(content: string): number {
const words = content.trim().split(/\s+/).length;
return Math.max(1, Math.round(words / 220));
}
The motion#
Most of the movement is plain CSS: masked text reveals, scroll-driven progress bar, a native <dialog> for the menu. Page changes use React's <ViewTransition>, and the title of a note morphs from the list into the page. A few small client components handle the rest, and everything respects prefers-reduced-motion.
The rest#
- Next.js App Router, every page statically prerendered.
- Tailwind CSS v4 with a small token set: one paper, one ink, one signal colour.
- Fraunces and DM Mono for type.
- RSS at
/rss.xml, plus sitemap, robots and per-note OG images.