seven / writing / 2026 / building-this-site-part-15 min read
§ 02 · 2026-05-03 · Craft · Field Notes

The Journey of Building My Website (part 1): why start from scratch, and the design decisions

Most developers have an unfinished personal website somewhere. This time I started from design philosophy instead of a template. Part one covers why, and the questions nobody asks you but you have to answer yourself.

I've had maybe two or three unfinished personal websites over the years.

Same story every time: find a Next.js starter, swap out the typeface, change the colours, add my name, stare at it for half an hour thinking "this doesn't feel like me," close the tab, and wait for inspiration.

This time was different. This time I stopped and asked one question first: who is this site actually for, and what does it need to do?


Not a portfolio — a business card

Most developer personal sites operate on portfolio logic: list your work, demonstrate your competence. Nothing wrong with that, but it felt odd for me. I'm a sophomore. I haven't built that much. Designing a page around showcasing achievements when there aren't many yet would just look sparse.

What I actually wanted was a business card combined with a thinking record.

Business card part: who you are, what you're working on, how to reach you. Concise, no padding.

Thinking record part: somewhere to put what I'm learning, decisions I've made, things I've got wrong. Nothing needs to be polished or important — just written down.

Once I settled on that framing, a lot of design decisions followed naturally.


Why not use a template

There are good-looking personal site templates on Vercel. The create-next-app defaults are serviceable. Hugo and Astro have solid options too. I considered them, then didn't.

Not because I thought I could do better aesthetically. Because I wanted to learn something in the process of building this.

The problem with templates isn't the aesthetics — it's that you don't know why they look the way they do. When you want to change one detail, you don't know where to start. I wanted to have an opinion about every decision in this site: why this font size, why this spacing, why this layout. Even if the answer is just "because it looks right to me."

Also: templates are designed to be neutral, to work for anyone. That's exactly why they make it hard to end up with something that feels distinctly yours.


Design philosophy: borrowing from print

I looked at a lot of sites I liked and tried to figure out what they had in common. The conclusion: I'm drawn to interfaces that feel like editorial print.

Specifically:

  • Grids and rules: Books have a text block. Web pages can too. Using lines to separate content feels more considered than just whitespace.
  • Margin notes and numbering: Things like § 01 / Now and № 001 — borrowed from academic documents and old newspaper layouts.
  • Density: I like pages that have some weight to them. Not cluttered, but not airy minimalism either.
  • Restraint in decoration: No gradients. No icon libraries. None of the animation you see on SaaS homepages.

This aesthetic has a side effect: it forces you to actually do the writing. If you can't rely on decoration, the content is the only thing. So building this site also pushed me to take every line of copy seriously, rather than placeholder it and come back later.


Type choices

Typography is probably the most important single decision on a site like this.

Body text: Source Serif 4. An open-source typeface from Adobe, designed specifically for long-form screen reading. Large x-height, moderate contrast, works well on both dark and light backgrounds.

Monospaced: JetBrains Mono. I use it every day when coding. Putting it on the site creates a continuity — this was built by an engineer, using an engineer's tools.

Both paired with the system sans-serif stack for UI chrome, where neutrality is appropriate.


Colour system

I made a deliberate choice: one accent colour, defined in OKLCH.

OKLCH is perceptually uniform — the same lightness value actually looks the same brightness to your eye, unlike HSL where red and yellow at the same lightness look completely different. This meant I could switch the accent between dark and light modes by adjusting a single value while maintaining consistent contrast.

For the accent: a warm amber-adjacent tone. Not aggressive, but distinct enough to do its job.

Backgrounds and foregrounds approach black and white without being pure black or pure white. Pure black feels dead; pure white feels clinical. Both get a slight warm cast.

Dark and light modes are implemented via CSS custom properties, toggled by prefers-color-scheme plus a manual switch.


Two language versions

This decision roughly doubled the complexity of the project. I still think it was right.

I have two potential audiences: Taiwanese people who read Chinese, and everyone else. If I only built one language version, I'd be excluding one of them.

I didn't use automated translation. Each language version is written independently — the Chinese and English are separate expressions of the same ideas, not translations of each other. It takes longer but both versions read naturally.

Technical implementation: next-intl. All copy lives in messages/en.json and messages/zh-TW.json. Routes use /en/... and /zh-TW/... structure, language switching is instant.


Design first, then features

I knew this principle. I violated it anyway, several times.

At one point I was spending hours thinking about "how will the contact form send email" and "how should the blog fetch posts dynamically" while the actual design sat half-finished. Eventually I forced myself to set those questions aside and get each page to a point I was genuinely happy with before touching the technical layer.

The result: all the features got built quickly, because the structure was already decided. If I'd built features first, the design would have stayed provisional — and provisional is just another word for forever unfinished.


Next: the technical implementation — Next.js 16 App Router, the MDX blog, and the infinite marquee that almost broke me.

Back to the blog