How It's Made - The Blog

2025-12-22

How It's Made - The Blog

Everybody’s dying. Some people are just doing it faster than others by choosing the wrong JavaScript framework. Me… as an Angular developer I’m here for a good time, not a long time. Now Svelte - that’s something else. Long before I became a developer I used to have a blog. That blog was made using Jekyll and lived as a GitHub page on a github.io domain. This blog is an almost exact visual copy of the old one. I loved the setup: I would write a post in markdown, host any images on a 3rd party and just git commit -> git push and that was that. I’ve tried to replicate this setup in a way that would teach me more Svelte, even if it ends but being a little overcomplicated. It’s a work in progress. Here’s some info for nerds, colleagues or prospective colleagues. If you’re neither of these - pay me more.

The Tech Stack

Here’s what powers this monument to narcissism you’re currently reading:

  • SvelteKit - Because I use Angular for work, React wasn’t complicated enough and Vue is too mainstream. At least Svelte 5 has runes now, which sound mystical but are really just state management with an occult twist.
  • MDsveX - For simple markdown and then maybe a component here and there.
  • Tailwind CSS v4 - Utility classes everywhere. My HTML looks like someone had a seizure on the keyboard, but hey, at least I don’t have to name things.
  • TypeScript - Strict mode enabled, naturally. Because nothing says “I hate myself” quite like adding type annotations to everything.

The Font Situation

I spent more time picking fonts than actually building this blog. By a lot.

The Particles Background

Step 1: “My last blog used particles.js. It’s been 11 years since its last update but how bad could it be?”

Step 2: Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode

Step 3: Install tsparticles. Realize the Svelte wrapper expects Svelte 4. Remove wrapper. Import engine directly. Finally works. Step 4: Question choices.

The particles are approximately what I felt to be my favorite color on that day (#9000f5 to be exact). There’s a subtle blur overlay so they don’t distract too much from the profound thoughts I’m sharing with the world.

The Routing Architecture

Blog posts live at /posts/[slug]. The homepage is the blog listing. Simple as. At some point these posts could become too many (right…) so I might have to add pagination.

There’s also an About page and a Music page. Both are markdown files. Both are probably empty. I’ll get to it …eventually.

The Build Process

It’s using @sveltejs/adapter-static because this gets deployed to static hosting. No server-side rendering, no edge functions, no complexity. Just HTML, CSS, and JavaScript being served like it’s 2005.

The Deployment Pipeline (A Journey Through Pain)

Initial Plan: Set up Gitea Actions for that sweet CI/CD professionalism. GitHub Actions syntax, portable workflows, something to show employers.

Reality Check: The Gitea lives in one Docker container. The blog lives in another docker container. Docker doesn’t have access to the host’s nvm out of the box. The runner doesn’t care. Workflow hangs on “Setting up Node.js” forever.

Current Solution: To me it was more fun to set it up with a Python Flask webhook receiver that:

  1. Listens on port 9001 (port 9000 was taken by something)
  2. Gets a POST from Gitea when I push to main only. I could push to other branches for testing and it won’t affect the live blog.
  3. Runs a bash script that has more environment variable exports than actual logic
  4. Responds with 200 OK immediately because Gitea has commitment issues and times out after 10 seconds
  5. The deployment script sources nvm, adds pnpm to PATH, pulls the latest code, runs pnpm install && pnpm run build, and copies everything to an nginx Docker container and restarts it.

It runs in a background thread because build times are longer than webhook timeouts. Logs go to both systemd journal and a file because Python’s stdout buffering makes systemd sad.

Total complexity: Higher than just SSHing in and running a script manually.

Total convenience: Also higher than just SSHing in and running a script manually.

Conclusion: Worth it? Ask me in six months when I’ve forgotten how it works and have to debug it at 2 AM.

All in All

This site was built in a couple hours with SvelteKit, some questionable design choices, and the crushing realization that web development in 2025 is somehow both easier and more complicated than it was 5 years ago.

Will I maintain it? Probably not. Will I write actual content? Maybe. Will I spend more time tweaking the particle configuration than writing posts? Absolutely.