WebGL Glow and Blog Upgrades

It’s been a little while since the last update (I have blog posts in mind, just lacking time to write them), but I’ve been busy tweaking the code behind the blog. If you’ve loaded the homepage on recently, you’ve may have noticed that things have more motion. I’ve given the site a slight visual upgrade, along with a bunch of architectural stuff to make builds and deployments more reliable. Thanks to Google Gemini for a bit of vibe coding on the side (a future blog post about my feelings behind this).

So what have I done?

Shader Magic: Direct WebGL Particles & Grid

In my first post, I talked about the space theme and the simple star parallax background. It was neat, but I wanted something that felt much more modern, premium, and alive.

So I sat down with Gemini and wrote a custom WebGL particle and grid background from scratch. No heavy libraries, just pure canvas and WebGL shader code (going back to my interests about 25 years ago).

Here's how the rendering pipeline works:

  1. The Particles: A custom vertex and fragment shader, renders up to around 600 floating particles, dynamically scaling their count based on your screen size.
  2. The Bloom Pass: I added a two-pass Gaussian blur (horizontal and vertical shaders) to capture bright points in the scene and blur them to make a nice effect.
  3. The Vignette: The post-processing shader blends the sharp particles with the blurred bloom texture and applies a smooth vignette to the corners.
  4. Interactive Grid: On top of the floating particles, there is an interactive grid. If you move your cursor around, the grid nodes warp and illuminate relative to the distance to your mouse cursor. (Inspired by Geometry Wars on the old XBox)

Saving the Battery: A Custom Play/Pause Switch

WebGL is beautiful, but rendering 60 fps on a high-refresh monitor can be a bit of a battery hog (especially if you're reading a long post on a laptop). I didn't want to compromise on performance or accessibility.

First, the effect automatically detects system settings (prefers-reduced-motion) and small screens (width < 768px) and defaults to paused.

Next, I'm limiting the frame rate to 30fps to give your GFX card time to breathe.

Finally, I built a custom, vertical play/pause toggle component in Svelte 5 and embedded it right into the top navigation bar. I think it looks kinda cool in my own nerdy way. If you turn the background animation off, the animation loop is completely paused, saving 100% of the GPU/CPU cycles. The preference is saved in localStorage, so your choice persists between visits.

Hardening the AI Summariser

Because I still suck at writing summaries, the blog relies on a backend pipeline to automatically generate them when building. But the previous implementation was a bit fragile.

I've updated that whole pipeline to make things less prone to breakage

Svelte 5 Snippets & Lottie Cleanup

I’ve also cleaned up some of the Svelte 5 code.

The Navigation component now leverages Svelte 5 Snippets. By using the new {@render children()} syntax, I can pass custom interactive components—like the WebGL play/pause toggle—straight into the navbar template without cluttering the navigation types or components.

I’ve also finally added links to my GitHub! You can find a link on the About Page, and a brand-new Lottie-animated icon on the Contact Page.

I had to work with Gemini a bit to get the icon looking the way I wanted. Originally it was inverted colours, and solid. The first frame was a blank circle also, so I had to rotate the animation timeline a bit.

So with that, I think that pretty much covers the latest round of updates! If you want to check out the code or see how this was all put together, head over to my GitHub or hit me up on the Contact Page.