I got into building my own website since I was around 9 years old, initially for showcasing the Pokémon MIDI files I've collected around the internet.
Around the time of graduating from university, I started to build websites as my portfolio seriously, I got the domain from that time. in 2014 looked like this in 2014

Websites like these did help me get into cool things and lots of opportunities come my way because of them. It is fun every time designing and building websites for myself, yet I would left them untouched after a few months. Since 2019 when my career seems to be stable and life started to have different priorities, I completely stopped building them, (apart from just a few mini sites for sending a few job applications), I even took the entire site down.

After a while, I realized I can't bar myself from putting things out there. Social platforms are great for the social aspect, but they usually focused on one medium, it is far from enough for me.

This time I am going to do something different, and document the mistakes, pains, and solutions I found along the last few years.

The Problems with building a personal website

If I examine my experience with building websites over the last decades, my pains with this task could be summarized into:

Technology stopped being fun after a while.

Carefully crafting the website and curating its content takes a lot of time. I can enjoy them until it becomes repetitive plumbing and no longer feels like learning. At some point, I would start to miss other aspect of life.

Missing the work-life balance

I think I started to focus too much on showcase my capability as a designer/developer with my website.
Of course, Showing that I am able to build a website even in the internet climate nowadays is kind of the point of building a website.

However, treating the website as a professional showcase has somehow made it feels more like work, ruining the fun for me.

Unmanageably cool

This is more of a mindset problem.

Maybe as a way to justify my website being an existence away from the ease-of-use platforms out there, I need to make up with a lot of cool stuffs that would not be possible else where.

I can learn a lot building these seemly cool things, but the time spent to make it responsive and accessible would take just as much time. It can easily suck away a lot of time and energy I have on the project.

Another potential dead end is that, I stopped liking the things I am building because it has fallen out of trend, or just my taste. Even worse, in order to keep being cool, I have to curate the content differently. One example could be that it used to be considered cool to write as least as possible about design projects, I gave into that trend. Turned out this muted "minimal" approach does not make the archive feels complete, in turn it does not inspire me to keep going.

The Approach This Time

1. Showcase both serious work things as well as personal stuffs.

No matter how it might be seen as unprofessional by some people, I feel this is the right way to build a website that fully embodies me as a person. It makes me more comfortable to publish things that feel less complete.

2. Minimal tech, as independent as possible.

This time, I won't be budgeting to use those awesome hosted headless CMS like Sanity I uses at work. I would prefer a solution with less layers, less files to tweak, no passwords to remember. And the site should be servable on static hosting.

The IndieWeb movement has inspired me a long time ago. I've seen a deck from people behind KirbyCMS proposing interesting ideas over the topic. Although I am not yet at the stage considering the "connected" aspect of my website, I would love to build a site that is portable, and the content is in my control.

There will be another section about the specific tech choices later.

3. Build the cool things later.

Defer the visual effects and unconventional design later until the amount of content can justify the extra investment. This is not saying that the design can be suboptimal, I would still love to make the features around archive complete and accessible.

Fortunately, bare-bone websites are more appreciated now.

The Right Stack

I like(?) to start my projects like this:

  • struggle with things I use everyday and should be pretty good at
  • struggle with things with pretty good design and should be pretty easy to get into

Eventually I end up with a basic Next.js stack, which I use for more than 6 years for work. But it is a framework more designed to make performant web applications with advanced hosting options they'd like to sell you. For my website, I had to wrangle it into the direction of simplicity.

Flat-file CMS and revisiting PHP

I started building my first portfolio using a CMS called Stacey, it is the first flat-file PHP CMS I got to know. The concept of flat-file CMS is that a .txt text file and its media assets in individual folders will turn them into individual pages. Flat-file CMS requires no database. It is truly portable and easy to author.

Kirby adopted the flat-file idea and turns it into a serious, powerful commercial product. Kirby ticks all the boxes

  • It can optimize images on the fly and caches it.
  • It has a backstage environment called Panel for even simpler on-the-go publishing experience.
  • It can also be turned into a headless CMS, which was released at the perfect moment where many of us struggling developing React SPA with a traditional CMS.
  • It can generate static output that does not require a LAMP stack.

In fact, Kirby is the go-to CMS we've been using at work and for freelance projects during my time in Berlin.

However in the first 30 minute of setting up the PHP environment and start writing my template in PHP, I've decided, with great sadness, Kirby is not suitable for my project, the investment is somehow too high. Their license model is totally fair, but the problem lies at my side – time and tooling investment.

The PHP eco-system has came a long way, but the developer experience of Node eco-system is still unrivaled. In order to use Kirby, I would have to write relatively less familiar PHP code without Visual Studio Code's out-of-the-box support. Auto-completion and IntelliSense are separated things to setup and even purchase.

Eventually I decided to try bending Next.js into a flat-file CMS.

How I turned Next.js into a flat-file CMS

Next.js also checks many boxes and the user experience is quite comparable to a Kirby setup.
When using MDX with the new App Router makes the experience even closer to a flat-file CMS.

  • MDX allows me to write simple files in markdown that can be turned into pages by Next.js
  • MDX allows me to write actual code whenever I want maximum control
  • Next's App Router enables me to put media assets in the folder of the route. Previously with Pages Router, the assets needs to be organized elsewhere.

With three-days of tweaking, experimenting I can author my content like this:

a screenshot of a project folder, all content and assets in one place

This image shows how I organize a "project" on my website, the content (page.mdx), metadata (data.toml), and assets (the images) are all in one folder.

The metadata file data.toml contains the data needed for listing them on the homepage.

# data.toml

title = "Trip to Japan and Taiwan"
description = "Pictures from the trip"

image = "/images/project-previews/trip-2023-2024-jp-tw.jpg"
selected = true
tags = ["travel"]
date = 2024-01-25

The content file page.mdx is a bit more involved:

import { ProjectLayout, pageDataToNextMetadata } from "@/components/base-layouts";
import data from "./data.toml"; // import the metadata via `@lcdev/toml-loader`

export default function Page(props) {
  return <ProjectLayout {...props} pageData={data} className="prose prose-xl max-w-none prose-img:mb-0" />;

export const metadata = pageDataToNextMetadata(data); // feed data into here for metadata for setting page title and other SEO purpose

## Markdown Content Starts here...

As seen above, the content file still ends up with some programs in it for the layout and metadata. It is possible to move them out into a individual layout.tsx, but due to the need of importing a local ./data.toml file, they must be added in each project folder. Separate it into a different file is possible but does not really reduce the amount of repetitive code.

And then the project folder is placed directly within the app folder:

a screenshot showing how I organize the projects in Next JS, they are directly in the app router folder.

I have two categories "work" and "life" and each project sit in one of them.

For importing the images in MDX with simple Markdown syntax, I use rehype-mdx-import-media

// next.config.mjs

import createMDX from "@next/mdx";
import rehypeMdxImportMedia from "rehype-mdx-import-media";

const withMDX = createMDX({
  options: {
    rehypePlugins: [rehypeMdxImportMedia],

I use next-image-export-optimizer for optimizing the images for static export. I feel one day NextJS might support this out of the box.


I'm in general pretty happy how this turns out. Having a proper setup turns out to be even more important than I initially thought. Without a good setup I would love using everyday, it is hard to have the motivation to keep adding content and update the website.

Using Next.js is staying in my comfort zone, but this is where I can focus on experimenting with more exciting things like react-three-fiber in the future.

it is still too early to say how long I will keep treating this website as my happy place. I've learned the importance of documentation and how it is one of my favorite activity. Judging by the amount of thing I just wrote about building it in the early stage of the project. I feel like it will be an important place for me to organize my thoughts.