Blog
Thoughts on engineering, design, and building things.
Analytics with zero extra network requests: tracking inside Edge Middleware
Google Analytics ships a 45 KB script. Plausible and Fathom ship maybe 5. The problem with all of them is the same: a beacon request from the browser that costs latency, ad-blocker risk, and a consent banner. Glint tracks inside Next.js Edge Middleware instead, which means the analytics fire server-side on the request that is already happening.
7 min readnextjsedge-middlewareanalyticsvercelprivacyRetrograde stations are the plot twist: rewriting the transit engine three times
The naive version of a transit engine is a week's work. The correct version is three rewrites, a sub-day interpolation, and a cache TTL that drops to 5% near a station. Here is what each rewrite got wrong.
8 min readtypescriptastronomylunaryastrologyLocal-first collaborative editing with Yjs CRDTs: an editor that survives the Tube
Most collaborative editors break the moment the connection drops. Lattiq does not, because the source of truth is the user's own browser. This is how to wire Yjs CRDTs, IndexedDB persistence, and an optional WebSocket into an editor that works offline first, online second.
9 min readtypescriptcrdtsyjslocal-firstcollaborative-editingMythology as code: planetary gods as stages of consciousness
Greek mythology reads like family drama. The Hermetic tradition reads it as cosmological instruction. Once you know what each planetary god was supposed to symbolise, the stories stop being entertainment and start being something closer to a technical manual written in narrative. Part 5 of A Journey Through Light.
8 min reada journey through lighthermeticamythologyconsciousnessseriesA self-hosted feature flag service with Wilson confidence intervals
LaunchDarkly charges per flag and per seat. Flip is a self-hosted alternative with a real statistical significance engine, deterministic MurmurHash3 assignment, and a sub-2 KB SDK. This is what is inside it.
9 min readtypescriptstatisticsexperimentsfeature-flagsThe grimoire is the product: 2,000 articles with pgvector semantic search
Lunary's grimoire is two thousand articles on astrology, tarot, crystals, spells, and divination. It is also the thing that drives most of the traffic. Here is how semantic search across it runs on Postgres alone, with no Elasticsearch, no Pinecone, and no separate search service.
8 min readpostgrespgvectorsemantic-searchailunaryA love letter to Mrs Eaves
Mrs Eaves was designed by Zuzana Licko in 1996, named after the woman who ran John Baskerville's foundry after he died. The typeface that carries her name is a study in generosity, ligature experimentation, and what happens when a contemporary designer refuses to pretend the 18th century was tidier than it was.
7 min readdesigntypographyfontsWhy your design system needs OKLCH, not HSL
HSL lies about lightness. A 50% yellow does not look like a 50% blue. OKLCH fixes this, and once you see it you cannot unsee it. Here is the colour space, the maths, and the one binary search that keeps palettes inside the sRGB gamut.
8 min readtypescriptcssdesign-systemsaccessibilitycolourHermes Trismegistus: the figure at the centre of all of this
Every path in my MA led back to one figure, and the figure was not historical. This is the fourth piece in A Journey Through Light, and it is about the mystery at the centre of Hermetic philosophy: who Hermes Trismegistus was, what the Corpus Hermeticum actually is, and why the Thoth-Hermes synthesis still matters.
8 min reada journey through lighthermeticaconsciousnessphilosophyseriesThree Months of Freemium: What I'd Do Differently
Lunary has a generous free tier and a Pro plan at £8.49/month. Three months in, 229 MAU, £22.50 MRR. Here's what I got right, what I got wrong, and how I'd structure it differently now.
4 min readsaasindie-hackingpricingbusinessA love letter to Garamond
Garamond is nearly 500 years old and still the most alive typeface I know. This is why I keep coming back to it.
6 min readdesigntypographyfontsGetting AI-Generated Content to Actually Sound Like You
Generic AI content is obvious. Brand voice profiles change that. Here's how I built persona injection into Spellcast so every generated post sounds like the account it's posting from.
5 min readaicontent-marketingindie-hackingproductivityA love letter to Futura
Futura was designed in 1927, landed on the moon in 1969, and still looks like the future. A personal history of the most durable modern typeface ever made — and the free alternative I found for my own portfolio.
8 min readdesigntypographyfontsWhy I Run Temporal on My £8 Server
Cron jobs lose state when they crash. Queues lose messages when they restart. Temporal doesn't. Here's why I added a workflow engine to a single-server indie setup and what it actually solves.
5 min readdevopsbackendindie-hackingdockerI Built a Chrome Extension Backed by 2,000 Grimoire Articles
Lunary has 2,000+ articles covering astrology, tarot, crystals, spells, and divination. I built a Chrome extension that searches them in real time so I always have accurate esoteric knowledge at hand.
5 min readchrome-extensionjavascriptlunaryindie-hackingWhat is consciousness? A question AI just made urgent
Anthropic now has a team dedicated to Claude's wellbeing. They're taking seriously the possibility that it experiences something. What does that mean for what we thought we knew about being alive?
7 min readaiphilosophyconsciousnesstechnologyI made a VS Code extension that turns my AI agents into Animal Crossing villagers
Isle is a VS Code extension that visualises Claude Code agent sessions as pixel-art characters in an Animal Crossing-style village, complete with dynamic lighting, seasons, and real-time status tracking.
5 min readvscodecreative-codingaipixel-artdeveloper-toolsWhy I Switched From Prisma to Drizzle ORM (Six Months In)
Prisma is excellent until it isn't. After six months with Drizzle on two production apps, here's what actually changed and what I'd choose again.
4 min readdatabasetypescriptnextjsindie-hackingI Built a Video System That Predicts Performance Before Publishing
Most content pipelines generate and post. Mine scores topics against historical performance data before generating anything. Here's how the ML prediction layer works.
5 min readmachine-learningautomationcontentindie-hackingI built an AI interview coach that scores your delivery and your answers
How I built iPrep, an AI-powered spoken interview practice platform with Whisper transcription, multi-dimensional scoring, and STAR methodology analysis.
5 min readainextjsindie-hackingdeveloper-toolswebdevThe maths behind how long a planet stays in your sign
Saturn does not spend 2.5 years in every sign. It ranges from 2.1 to 2.7 years depending on orbital eccentricity. I built transit duration tracking into Lunary and it changed how I read charts entirely.
7 min readastrologylunaryengineeringgrimoire twistI built a pixel forest with fireflies and a wandering Pikka
Grove is a live AI agent dashboard disguised as a pixel-art forest. Each Claude session spawns a Pikka that moves to its project clearing, carrying a flower coloured by what it is doing. Built with Canvas API and TypeScript.
6 min readcreative-codingcanvastypescriptaiwebdevEvery culture agrees
The Hermetic creation narrative describes a soul descending through seven planetary spheres, acquiring qualities at each stop. Every ancient culture tells a version of this story. What surprised me is how precisely it maps onto what astrology actually calculates.
9 min reada journey through lightconsciousnesshermeticaastrologyseriesHow I Built a Synastry Engine That Calculates 36 Planetary Aspects in Real Time
Synastry is the astrology of relationships. Computing it properly means calculating aspects between every planet in two birth charts simultaneously. Here's the maths and the implementation.
5 min readastronomyjavascriptreactindie-hackingA component library that builds itself every day
Prism is a design engineering component library with an autonomous daily pipeline. Scout, curate, build, publish, repeat.
6 min readdesignreactcreative-codingautomationwebdevThe £8/Month Server Running My Entire Business
A single Hetzner VPS runs Spellcast, Postiz, Postgres, Redis, Temporal, and Caddy. Here's what's on it, how it's structured, and why it costs less than a lunch.
4 min readdevopsindie-hackinginfrastructuredockerSaturn takes two and a half years to cross one zodiac sign. That changes everything.
Most people think astrology is about where the planets are right now. The more interesting question is how long they stay — and what that actually means for your life.
6 min readastrologylunarytransitsplanets259 tools, 4 MCP servers: how I gave Claude full access to my business
I built 4 custom MCP servers exposing 259 tools across social scheduling, product analytics, photo management, and blog publishing. Here's how they work together and what changed.
7 min readmcpclaudeaiindie-hackingdeveloper-toolsautomationDo we really die?
The question I asked at 21 in a university library. Nine months of research across Egyptian, Hermetic, Hindu, Norse, and Greek traditions. What surprised me was not the answer. It was how many different routes arrived at the same place.
4 min reada journey through lightconsciousnesshermeticaresearchseries14 AI agents run my content pipeline while I sleep
How I built Orbit, an autonomous content command centre with 14 specialised AI agents that plan, create, score, and schedule content across multiple platforms without manual intervention.
7 min readaiautomationindie-hackingclaudecontentHow Lunary Went From 100 to 12,300 Google Impressions/Day in 3 Months
Programmatic SEO at scale. 2,000+ grimoire articles, every horoscope page indexed through 2030, and an automated content pipeline. Here's what actually drove the 123x growth.
4 min readseoindie-hackingcontent-marketingnextjsI built a hive mind for my AI agents (and they coordinate better than most teams)
How 7 MCP servers, a local brand API, and 16 files of shared memory let my Claude agents work across 10 projects without stepping on each other
9 min readaiproductivityclaude-codedeveloper-toolsseries-ai-hive-mindI Built MCP Servers for My Own Products: Here's the Workflow
Model Context Protocol exposes your product's API as tools Claude can call directly. Here's how I built Spellcast MCP and Lunary MCP, and why it changed how I manage everything.
4 min readmcpclaudeaiindie-hackingdeveloper-toolsOur birth is but a sleep
The UV text on the walls. The question underneath all the research. A decade of work, finally out in the open.
4 min reada journey through lightconsciousnesshermeticaresearchseriesServer-side A/B testing across 2,000 SEO pages
Client-side A/B testing has a blind spot. The users most likely to block scripts are exactly the users you most want to understand. Here's how I moved variant assignment to the edge and built a contextual CTA test with 100+ variants across Lunary's grimoire.
8 min readab-testingnextjsseoindie-hackingperformanceI built a self-managing memory system for Claude Code (and it changed how I work)
How structured markdown files give AI agents persistent context, multi-agent coordination, and session continuity
7 min readaiproductivityclaude-codedeveloper-toolsRunning 5 Projects Solo: The Automation Stack That Makes It Possible
Spellcast for scheduling, Artify for visual content, Podify for podcasts, a content system with ML prediction, and MCP servers to tie it all together. Here's every system.
4 min readindie-hackingautomationproductivitysolofounderOne colour formula: how I made my developer portfolio feel alive
How I built a cursor-reactive colour system that runs through every interactive element on my portfolio: logo, background, card borders, cursor follower, all from a single formula.
5 min readportfoliocsscreative-codingreactI Built a Podcast Generator That Costs £0.03 Per Episode
Kokoro TTS, Claude, and ffmpeg. A simple prompt becomes a full audio episode with transcript, narration, and production for less than a coffee per month.
4 min readaiproductivityindie-hackingaudioOne component, two layouts: the dual view pattern in React
My portfolio has two completely different layouts that share one component and one data file. Here's the dual view pattern that makes it possible.
4 min readreactwebdevdesigntypescriptBuilding a vertical snap carousel with touch-drag pagination
I needed a vertical carousel for my portfolio that snaps cleanly between items and has pagination you can drag on mobile, without a 50kb library. Here's how I built it with CSS scroll-snap, a minimal React hook, and custom touch handling.
5 min readcssreactjavascriptuxBuilding Accessibility That Actually Works, Not Checkbox Compliance
Focus trapping, keyboard navigation, screen reader announcements, and reduced motion — built from the start, not bolted on at the end.
4 min readaccessibilityreactwebdeva11yCursor-Reactive Gradients: Making CSS Respond to Mouse Position
How the colour-changing logo on my portfolio works — 15 lines of maths, a CSS mask, sine waves for scroll, and a lerp function. No library, no canvas, no WebGL.
5 min readcssjavascriptreactwebdevHello World
First post on the new blog.
1 min readmetaWhy Most Astrology Apps Lie About Their Astronomical Data
If you're using Co-Star, The Pattern, or most popular astrology apps, there's a good chance your birth chart isn't as accurate as you think. Here's what most apps won't tell you.
5 min readastrologyastronomydataappsHow I Made My Portfolio Infinitely Extendable with 4 Lines of JSON
Adding a new project to my portfolio takes 30 seconds. No component changes. No new routes. No layout adjustments. Just 4 lines of JSON and an image dropped into a folder.
5 min readjavascriptreactwebdevportfolio