I Built a Website I Can Keep Long Term

In this millennium I probably built around a thousand versions of my personal website. That sounds ridiculous, but the pattern was real. New stack, new architecture, new excitement, then the same result. I would launch, maintain for a while, get tired of the maintenance burden and shut it down.

I have been coding for about eight years, so every rebuild reflected what I had just learned. That was part of the problem. My codebase had no stable center. As soon as I understood a better way to do something, I wanted to rewrite everything. I kept chasing technical quality while the actual content stayed underdeveloped.

Each version looked impressive in development and did almost nothing useful in production. Bills kept coming anyway. Sometimes I even built custom CMS systems to fix the previous CMS problems, then ran into new complexity immediately. I had no clear definition of done.

Why This Kept Failing

I was treating a writing website like a software product that needed continuous architectural evolution. What I needed was much simpler. I wanted a place where I could publish what I was working on, a few paragraphs at a time, without turning every update into a platform decision.

The mismatch was obvious once I admitted it. My real requirements were straightforward: write quickly, keep ownership of content, publish with low overhead and avoid endless maintenance loops. That pointed directly to a file-first approach.

The Tooling Diversion

I tried many apps and even forked open-source tools to build my own writing system. Full control sounded good on paper. In practice it became another maintenance job. My custom setup was inconsistent across Linux, macOS, Windows and Android. Syncing was fragile and as the time passed I was investing energy into infrastructure instead of writing.

Part of this came from trust issues around third-party platforms and data ownership. I wanted full control over my files and history. That instinct was right, but my implementation was too heavy.

Obsidian Became the Base

I eventually landed on Obsidian. Not because it is trendy, but because it gave me local files, a flexible plugin model, and speed. I built a custom routine around templates and shortcuts so I could create new drafts fast and keep them organized automatically. That changed my daily behavior. Writing felt easy again.

Then one simple idea connected everything: if my notes are already local Markdown files, those files can become the website source.

Finding MkDocs Through Work

I found MkDocs while working on client documentation. The requirement there was clear. Managers wanted text files that could be edited quickly and published without a heavy platform.

That was exactly what I needed personally.

At first I did not like MkDocs because I did not fully understand it. After spending time with it the model clicked: one project folder, Markdown as source, static HTML as output and a predictable build process. No client-side app layer required for reading basic content.

Building Quartz

Default themes did not match what I wanted, and most community themes looked like documentation portals. So I built my own theme and named it Quartz.

Quartz gave me a structure that felt like a personal writing space instead of a docs site. I redesigned navigation, kept the layout centered and readable and focused on mobile-first behavior. Later I split the theme into its own repository and used it as a submodule. That way I can evolve components in one place and reuse them where needed.

Custom Blocks Without Framework Debt

I still wanted rich presentation. I work with photography and music, so plain text alone is not enough for all posts. I needed reusable blocks for galleries, grouped media and interaction.

I did not want to return to a full React pipeline to get that. I also did not want to pollute Markdown files with raw HTML. The solution was markdown-custom-blocks with MkDocs. I can define custom block syntax, map it to templates, and generate clean HTML during build. In my setup, blocks use ::: syntax and can include the HTML, CSS, and JavaScript they need.

This gives me a good boundary. Markdown stays clean, components stay reusable and JavaScript is used for targeted interactivity, not as the core rendering system.

Why Build-Time Output Matters

The biggest practical win is build-time rendering. Pages ship as content, not as placeholders waiting for hydration. This changed both how the site feels and how it behaves operationally.

On the reader side, content appears immediately, there is no waiting for a frontend runtime to assemble basic article text and the layout is more stable because most of the page is already resolved before it reaches the browser.

On my side, there are fewer production edge cases tied to runtime rendering, simpler debugging because the generated HTML is explicit and less pressure to maintain a large client-side dependency graph for a mostly content-driven site.

I still use JavaScript where it matters. The difference is scope. It handles interaction, not page existence.

For this kind of site, that tradeoff is worth it.

2026 Goal: Stop Overcomplicating

One of my explicit goals for 2026 was to stop overengineering personal publishing.

My workflow now has a clean split: Obsidian is where I think and draft and MkDocs is where drafts become public pages. In practice, this makes the writing loop boring in a good way. I open the vault, draft ideas, refine structure and publish without switching mental models every hour. I am no longer juggling infrastructure tasks while trying to write.

The old loop looked like this: write a bit, notice a tooling limitation, start rebuilding the system, postpone publishing. The current loop is simpler: write, edit, publish.

That change is bigger than any framework migration I have done.

Decoupling and Ownership

The deeper reason for this setup is portability. My content is plain files under Git. I keep history. I keep source. I can swap the theme, change the generator or move infrastructure later without rewriting the writing itself.

That removes platform lock-in pressure and reduces migration risk in concrete ways. If Quartz changes, I can keep the same Markdown corpus. If MkDocs stops fitting my needs later, I still have clean source material with version history. If I want to republish selected articles somewhere else, I can do it from files I already own, not by exporting from a proprietary dashboard.

Decoupling is not an abstract architecture principle here. It is a practical guarantee that my writing outlives the current stack.

What Simplicity Means to Me

Earlier versions were often technical showcases. They reflected what I had just learned, but they did not always support what I was actually trying to do.

This version is different because success is measured by publishing consistency, not implementation novelty. I stopped treating the website as the product because the writing is the real product. The system exists only to support that work: keep authoring overhead low, keep output quality high, keep ownership intact and keep maintenance within reasonable limits.

If I can keep publishing useful posts without getting pulled into constant rebuild cycles, then this version is doing its job.