I have owned wag.dk for years. For most of that time it sat empty, or worse, it ran an old WordPress install that I never updated, never themed properly, and never felt proud of. Every time I thought about writing something, the friction of logging into wp-admin, dealing with plugins, and fighting the block editor killed the impulse.
This weekend I decided to fix that. Not by finding a better WordPress theme. Not by migrating to Ghost or Substack. But by building exactly what I wanted: a static site that I control completely, generated by Python, styled with intention, and fed by nothing more than JSON files and Markdown.
The Problem with WordPress (For Me)
WordPress is an incredible piece of software. It powers half the web for good reason. But for a personal blog that exists mainly for my own memory and pleasure, it felt like overkill:
- Database dependency: My content locked inside MySQL tables I do not want to manage.
- Plugin fatigue: SEO plugins, caching plugins, security plugins — each one a liability.
- Theme bloat: Every theme wants to be everything to everyone. I want almost nothing.
- Login friction: Writing a post should feel like editing a text file, not operating a CMS.
What I actually wanted was closer to a digital notebook that happens to be on the web. Something I could write in any text editor, version control with Git, and deploy by copying files to a server.
The Architecture
The site is built around a simple idea: JSON is the database, HTML is the output, Python is the glue.
blog/
├── content/posts/ ← generated post .html files
├── templates/
│ ├── post_template.html
│ ├── index_template.html
│ └── category_template.html
├── data/
│ ├── posts.json ← index of every post
│ └── categories.json ← category/subcategory tree
├── static/style.css
├── generate_post.py ← turns raw text into a post
├── build_site.py ← rebuilds all pages from JSON
└── email_listener.py ← polls inbox, triggers generation
Two JSON files drive everything. posts.json is the canonical index — every post's title, date, category, excerpt, filename, and tags live there. categories.json defines the tree: Tech, Geek, Food, Apps, each with their own subcategories.
When I add a post, I append to posts.json, run build_site.py, and the script regenerates the homepage, category pages, and any indexes. No database queries. No cache invalidation. Just files.
Design: Clean Minimal
I explored three visual directions before settling on this one. The dark terminal style felt cool but heavy for long reads. The playful geek style was fun but risked feeling dated. The clean minimal approach won because it gets out of the way.
The palette is intentionally restrained:
- Warm stone background (
#fafaf9) — easier on the eyes than pure white. - Thin borders (
#e7e5e4) — structure without weight. - Light-weight headings — the content carries the voice, not the typography.
- Soft category colors — just enough to distinguish Tech from Food without shouting.
Every element exists because it needs to. No gradients, no shadows for decoration, no hero images that slow down the page. The design philosophy is Scandinavian editorial: generous whitespace, clear hierarchy, and typography that respects the reader.
The Email-to-Blog Pipeline (Coming Soon)
Here is where it gets interesting. The end goal is to email my blog. I want to fire off an email from my phone with a rough draft, have a Python script poll the inbox, send the body through an LLM API to clean it up and format it, generate the HTML post, update the JSON index, rebuild the site, and deploy.
The pipeline looks like this:
Email → email_listener.py → LLM API → generate_post.py
→ update posts.json → build_site.py → deploy
No web interface. No login. No markdown parser to fight with. Just write an email and hit send. The machine does the rest.
Why Static Sites Still Matter
In an era of Notion blogs, Substack newsletters, and Medium publications, building a static site from scratch might seem archaic. But the benefits are real:
- Speed: No server-side rendering, no database calls. Just files served by Nginx.
- Security: No PHP, no SQL injection surface, no plugin vulnerabilities.
- Portability: The entire site is text files. I can host it anywhere.
- Ownership: My content lives in Git, not in someone else's database.
- Longevity: HTML and CSS will outlast every platform trend.
What Is This Site For?
I want to be clear: this is not a growth-hacking project. I am not optimizing for newsletter subscribers or SEO rankings (though the site is structured well for search engines). This is a memory palace — a place to dump findings, document projects, share recipes, and geek out about things that fascinate me.
The categories say it all:
- Tech — Python scripts, hardware hacks, automation pipelines.
- Geek — Sci-fi thoughts, space tracking, gaming experiments.
- Food — Sourdough APIs, fermentation logs, recipes that worked.
- Apps — iOS tools, web experiments, CLI utilities I actually use.
This post is the first brick. The foundation is laid, the templates are ready, and the JSON structure is solid. Next up: wiring the email listener, refining the build script, and actually writing about the things I build.
If you are reading this, the site is live. Welcome to wag.dk.