Breaking Things, Building Things - December 2025
December was one of those months where the private work felt like the main event but the side projects told the more interesting story. Between building infrastructure for AI agents at work and spinning up everything from browser extensions to newsletter tooling at home, I managed to squeeze 539 commits across 64 repositories into the calendar. The split was roughly even between client work and personal projects, which feels about right when youâre trying to keep both plates spinning.
The month had a theme: infrastructure. Whether it was building Langfuse telemetry into runtime environments, wrestling with SQLite analytics that could keep up with real traffic, or setting up content pipelines for workshop platforms, most of December was spent on the plumbing that makes everything else possible. Not glamorous, but deeply satisfying when it works.
I also spent considerable time building tools for myself - a pattern thatâs become increasingly important. When youâre working with AI assistance daily, having the right scaffolding makes everything faster.
Highlights
December brought several substantial pieces of work across both client projects and personal tooling. The analytics work alone represents weeks of iteration, whilst the workshop platform finally came together after months of planning.
Local Analytics with SQLite
The standout technical achievement this month was building a complete analytics system from scratch. After years with Fathom Analytics, I wanted something more integrated - live visitor counts, popular posts, real-time traffic breakdowns without external API calls. What started as a simple tracking experiment evolved into an analytics engine that handles thousands of pageviews daily.
The system uses SQLite for storage with a queue-based ingestion pipeline that batches writes to avoid blocking requests. Added user agent parsing for browser and device detection, IP-to-country mapping using Cloudflare headers, and bot detection to keep the data clean. The database schema includes indices for common queries and a rollup mechanism for historical data aggregation.
Most interesting was solving the over-fetching problem on the posts route. Initially every visit triggered analytics queries that slowed everything down. Fixed it by implementing feature flags, optimising query patterns, and adding server-side caching. The live visitors component now updates every 15 seconds without dragging down page loads. Full write-up published at Local Analytics with SQLite and SvelteKit.
Svelte Bits Workshop Platform
The workshop platform project reached a milestone this month. Built the complete checkout flow using Polar, integrated Better Auth for authentication with email/password and social providers, and set up the database schema for courses, tutorials, and user enrolments. The content system supports both video tutorials (with timestamps and resource links) and workshops (with GitHub repos and live session scheduling).
Added SEO configuration across all pages using svead, implemented role-based access control for premium content, and built admin tooling for managing workshops and inquiries. The architecture uses SvelteKit with Turso for the database, Cloudflare Turnstile for spam protection, and Resend for transactional emails. The whole thing deploys to Railway with automated database backups and pull/push functionality.
Client Infrastructure Work
On the client side, built substantial infrastructure for AI agent systems. Implemented Langfuse telemetry with OpenTelemetry integration for distributed tracing, set up AWS Bedrock support alongside Anthropicâs API for model flexibility, and consolidated agent variants into a single deployable runtime with environment-based configuration. The Docker builds required careful dependency management and caching strategies to keep image sizes reasonable.
Added real-time capabilities for agent interactions, built HTTP proxy support for shadow mode testing, and improved error handling across the stack. Also helped migrate UI components and optimise state management patterns, which meant lots of refactoring and testing to ensure nothing broke in production.
Blog Posts
Two posts this month, both documenting technical decisions that felt worth sharing. The analytics piece captures months of iteration distilled into practical patterns, whilst the Linux post records a brief detour into distro evaluation.
Building Self-Hosted Analytics
The SQLite analytics post walks through the entire system architecture - from request tracking hooks to query optimisation to maintenance tasks. Covers visitor anonymisation with salted hashes, concurrent write handling, and how to structure indices for real-time queries. The deduplication logic alone took several iterations to get right, and the post includes the final working solution.
Most valuable section might be the performance optimisation part. Explains how to batch inserts, avoid N+1 queries, and implement feature flags for gradual rollout. Also details the migration strategy from external analytics providers and how to maintain both systems during transition.
Linux Distribution Hopping
Spent a weekend evaluating new Linux distributions after my existing setup felt stale. Tried Omarchy with its tiling window manager for about 16 hours before admitting defeat - couldnât wrap my head around the keyboard-driven workflow. Switched to EndeavourOS instead, which gave me Archâs rolling release model without the installation pain. The post captures the reasoning and migration process for anyone considering similar moves.
Links:
Open Source
Released several tools this month, mostly focused on developer workflows and AI integration. The Claude-related projects saw the most activity, with MCP servers and skills repositories getting regular updates and community contributions.
Svalettab Browser Extension
Built a browser extension that generates random colour palettes and font pairings for new tabs. Uses variable fonts from Fontsource, implements contrast checking for accessibility, and includes a click-to-copy feature for colour values. The trickiest part was supporting both Chrome and Firefox with their different extension APIs whilst maintaining a single codebase.
Took styling cues from Palettab but rebuilt everything in Svelte 5 with runes. Added the dimple divider effect using SVG paths, smooth fade-in animations, and hover states that show font source links. The extension doesnât track anything or use external APIs - everything happens client-side. Available in both Chrome Web Store and Firefox Add-ons.
CCLog Tool and Claude Skills
Created cclog, a tool for syncing Claude Code chat history to SQLite for analysis. Handles the JSON export format, tracks tool calls and results, and structures everything for SQL queries. Wrote it in Bun for speed and the Bun native SQLite.
Extended my svelte-claude-skills repository with comprehensive documentation on reactivity patterns, migration gotchas from Svelte 4 to 5, and remote function usage. Added skill activation hooks, research verification guidelines, and detailed examples of async integration patterns. The repository now serves as reference documentation for anyone building Claude Code extensions.
MCPick Profiles Feature
Added profiles support to mcpick, allowing predefined sets of MCP
servers to be installed as groups. Useful for different work
contexts - one profile for web development, another for data analysis,
etc. Also implemented CLAUDE_CONFIG_DIR support for custom config
locations and fixed several edge cases in the installation flow.
The profiles feature came from a community suggestion and got merged within days. Added error handling, shell injection protection, and scope support for scoped npm packages. Most satisfying bit was the clean abstraction that made the feature feel natural within the existing command structure.
Links: