Portfolio · System

The portfolio that keeps itself up to date

Not a static CV page but a system: Notion is the source, three Python scripts build the site, and every morning it publishes itself. You're looking at it right now.

A portfolio starts aging the day you publish it. The numbers fall behind, the changelog stops, the latest project is three months old. Not because the work stopped, but because updating is manual labour.

So I built a portfolio that keeps itself up to date. The projects, the changelog, the growth chart and the numbers at the top of the site: none of them are typed into the page. Everything comes from two Notion databases I use daily anyway, and the site rebuilds and republishes itself every morning.


Outdated from day one

"I build AI systems" has become a cheap claim. Everyone puts it on their profile. The difference isn't the claim, it's whether you can click on it. I wanted a portfolio that is its own proof: a site that shows what's running, by running on it itself.

The practical problem was a classic. Every time something was finished, I had to open the site, edit HTML, upload files. You do that twice, and then never again. The records I did keep lived in Notion, where my tasks and projects already are. The solution was obvious: let the site grow out of those records, instead of maintaining a copy next to them.

Change the source, never the output.


One source, three scripts, a fresh site every morning

Every project card, changelog line and toolkit tile on the homepage is a row in a Notion database, with a handful of fields that drive the behaviour: which section it lands in, whether it's published, and in what order. Adding a new project means creating a database row. I don't touch the HTML.

The whole pipeline, three scripts
  • build_portfolio.py turns the content database into projects, changelog, toolkit and workflow on the site, in two languages at once.
  • build_timeline.py reads my task board and builds the growth chart from it, week by week.
  • update_hero.py refreshes the numbers at the top of the site, straight from the same source.

The scripts write their output between fixed markers in the page:

<!-- BUILD:portfolio:projects:start --> ... generated by build_portfolio.py ... <!-- BUILD:portfolio:projects:end -->

That rule enforces discipline: there is exactly one place where content lives, and it's not the website. Everything between the markers gets overwritten on the next build. The scripts are also predictable: a second run without database changes changes nothing, and a built-in count stops the build if items go missing along the way. A half-empty section never quietly goes live.

Since the latest rebuild, publishing isn't an action anymore. Every morning at a quarter past eight, the full pipeline runs by itself: refresh the content, and only if something actually changed does the site get republished. No change means no publication. The server also only accepts files on a fixed list, so an accidentally included internal file can never become public. It fails safely: a forgotten file simply doesn't appear, instead of the wrong file leaking.


Proof instead of claims

The strongest argument for this setup is that you're looking at it. The growth chart on the homepage shows hundreds of completed tasks, week by week, spread over fourteen skill domains. That data comes from the same task board I work with daily. The chart can't lie without my own records lying with it.

2Notion databases as the only source
3Python scripts build the site
2languages from the same pipeline
0manual work per update

A fresh build every morning; publication only when something changed.

Meanwhile the site has grown from one page into a small ecosystem: project pages per system, an article series built from plain text files, and a bilingual variant built from the same databases. The pipeline stayed the same; it just gained sources.


Automatic is not the same as automatically good

The technology turned out to be the easy part. The hard part is editing. A system that publishes everything that's finished also publishes things that mean nothing to a visitor. So nothing goes live without a deliberate choice: every card has a status, and only what I set to "published" reaches the site. The AI helps write the copy, but a page only goes live after I've read the real, rendered version. That human gate isn't a weakness of the system, it's its most important part.

And there's a second trap: tinkering with the system is more addictive than making content. An evening spent polishing the pipeline feels productive, but a visitor sees none of it. The rule I set myself: the system is done once it's boring, and the attention belongs to what it shows.


Three lessons from the rebuild

01
Half translated is worse than not translated

The first language toggle translated only the buttons, not the content. The result: an "English" site that was mostly Dutch. That system was removed entirely and only came back once the whole content pipeline was bilingual, with an English title and description field per card in the database.

02
Not every finished task is portfolio material

A version bump of a tool matters internally, but says nothing to a visitor. The filter for the changelog: something an outsider understands and that says something about what I can do. The rest stays in the records.

03
Verify the chain, not the assumption

The biggest bugs came from assumptions about how data flows: a file that turned out not to load, a structure that was flatter than expected. Since then I first prove what actually arrives at the receiving end, and only then build. And it works the other way too: human thinking regularly pulls an AI out of a dead-end fixing loop. The AI looks sharply at its own piece, the human oversees the whole.


Make your own site self-updating

The setup isn't tied to my tools. All you need is one place where your work is already being tracked (a task list, a spreadsheet, a database) and the agreement that the site grows out of that. Let an AI sketch your own variant with the prompt below.

  1. Name your source. The place where your work already lives. That becomes the only place you still update.
  2. Name what the site shows. Projects, a changelog, numbers: pick what means something to a visitor.
  3. Let the AI make the plan. Starting small is fine: one section that refreshes itself is already a living portfolio.
Copy this prompt
I want my portfolio site to keep itself up to date, instead of me updating it by hand.

My situation:
- I currently track my work in: [for example: Notion, a spreadsheet, Trello]
- My site runs on: [for example: a static site, WordPress, no site yet]
- I want to show: [for example: projects, a changelog of finished work, numbers]

Interview me briefly first about what my records contain and how technical I am.

Then propose a setup with:
1. Which source becomes the single place of truth, and which fields it needs.
2. How the site gets built from that source, as simply as possible.
3. A safe publishing step, where I decide what becomes visible.
4. The first step I can take this weekend.

Be honest about what I'd better not automate.

Part of a bigger system

This portfolio is itself one of the systems it shows. The databases the site builds from are largely maintained by Kai, my AI assistant, and the knowledge behind the projects lives in my second brain. What you're reading isn't a description of a way of working, it is the way of working, in production.

Explore further

All projects this site shows are on the homepage, live from the source.

An example of what flows through this pipeline: the full build story of Wire Spine, an AI concept album.

See the living portfolio Meet Kai, my AI assistant