Building this portfolio
Astro, posts written in Markdown, type that works as imagery and a single animation that knows when to step aside. The choices behind this site.
Sample post, written while building the site to show the format. Review it, adapt it to your voice or delete it.
A portfolio is first of all a page someone opens between two meetings. It has to load fast, read well on a phone and make people want to open a project. Everything else is decoration, and decoration has a cost.
Why Astro
The site is almost entirely static: pages, projects, posts. Astro generates HTML at build time and only ships JavaScript where it really helps. Here that comes down to one small script: the theme button, the mobile menu and the preview that follows the cursor over the project list.
No client-side framework, no bundle of several hundred kilobytes to display text.
One post, one file
Publishing a post means adding a Markdown file to src/content/blog/en/. The frontmatter is checked against a schema: when a field is missing or has the wrong type, the build fails with a clear message instead of shipping a broken page.
---
title: What I learned
summary: One or two sentences for the list and social cards.
date: 2026-11-20
tags: [Production, Go]
draft: false
---
Reading time, tag pages, the RSS feed and the sitemap are all derived from those files.
Type as imagery
The art direction rests on one idea: headlines are the image. Anton, a very condensed sans serif, spans the full width of the screen, sometimes as an outline only. Body text is set in Inter, which is much quieter.
Projects without a visual get a cover drawn from their initials. No image to produce, and a set that stays consistent even when a project has no screenshot.
A giant headline does the job of a photo, without the weight.
A single animation that knows when to step aside
On load, the letters of the title rise one by one. It is the only motion nobody asked for. Everything else answers an action: a hover, opening the menu.
And when the system asks for reduced motion, the animations go away:
@media (prefers-reduced-motion: reduce) {
.char {
transform: none;
animation: none;
}
}
What is left
Replace the placeholders with real projects, write the next posts, and connect a domain name. Everything else is in place.