Projects
Things I run, and the people they are for.
Everything here runs on the meklab cluster. Public projects link to a read-only GitHub mirror; the source of truth is a self-hosted GitLab.
Live in use In progress active development Archived finished or superseded
-
meklab
A three-node Kubernetes cluster at home, operated like production.
Migrated a Docker Compose estate on Proxmox to a highly available k3s cluster managed by Flux. Vault-backed secrets through External Secrets Operator, Prometheus and Loki observability deployed before any user-facing service, Traefik and cert-manager ingress, Longhorn block storage, Garage object storage, KEDA scale-to-zero for accessory services, and Authentik single sign-on in front of everything. The security posture assumes public exposure even though reachability is private.
- GitOps from a self-hosted GitLab CE, with CI reaching the cluster through an agent tunnel rather than a kubeconfig secret
- Split-horizon DNS across three resolvers, all managed by ExternalDNS
- Backup strategy across VMs, cluster volumes, and an offsite archive, with restores actually exercised
k3s · Flux · Vault · Longhorn · Traefik · Prometheus · Loki · Authentik · Proxmox · Tailscale
-
OpenClef
An open-source, self-hosted sheet music library for performers.
Existing tools are tablet-locked and single-user, or treat scores as generic files. OpenClef models what musicians actually search by: works, arrangements, parts, instruments, and composers. Product design and technical requirements documents were validated with prospective users before implementation began. Full export to forScore is a first-class requirement so the tool fits how musicians already perform.
- Native authentication and a storage abstraction layer
- Chunked upload-and-parts pipeline
- Frontend framework chosen through a written decision document
Python · FastAPI · PostgreSQL · SQLAlchemy
-
DVD ripping appliance
A 2009 MacBook Pro turned into a one-button DVD archiver for a grandfather.
Insert a disc, get a lossless rip, transferred to network staging, auto-ejected, with a chime. No terminal, no login, no decisions. A FastAPI and htmx interface with server-sent events shows progress in plain language. The ripper is an explicit SQLite-backed state machine, so a bad disc, a dropped network, or a power cut resumes rather than restarts.
- Pull-based deployment so the appliance updates itself over the mesh network
- TMDB metadata lookup so discs land in the library correctly named
- Audio CD support in progress
Python · FastAPI · htmx · SQLite · ffmpeg · mkvmerge
-
vinyl
Digitizing an inherited record collection: inventory, capture, QC, and library import.
A capture station with a kiosk interface, an inventory server with barcode accession cards, and a pipeline from raw capture through track splitting and quality checks into the media library. Built so a non-technical operator can run a whole session alone.
- Two-pass silence-detection track splitting with ffmpeg, after rejecting in-memory approaches that fail on long sides
- Acoustic fingerprinting through AcoustID and MusicBrainz, with fingerprint failure used as a signal that a recording is home-made
- Printed accession cards with barcodes tie the physical record to its digital master
Python · FastAPI · ffmpeg · Chromaprint · MusicBrainz · ReportLab
-
recipe-pipeline
Handwritten family recipe cards, scanned, OCR'd, structured, and served from Mealie.
Scans go through a handwriting OCR model, then a text model turns noisy output into well-formed recipe records with title, ingredients, steps, and provenance. Hard cases escalate to a stronger cloud vision model, and only the failed tail ever leaves the machine. Results land in a self-hosted Mealie instance in the cluster.
- Prompt regression harness that checks the structuring stage against every sample card
- Ingredient parsing on import, with a backfill for existing recipes
- Worker runs in-cluster against CPU-only inference sized deliberately for the hardware
Python · FastAPI · Ollama · Mealie · S3
-
scribe
Send a link, PDF, or image to Slack; get a summary in thread and a full note in Obsidian.
A headless Slack-first service that extracts text, summarizes it through an LLM gateway, writes a note into a vault, and can produce a narrated audio version with chapter markers for an audiobook library.
- Text-to-speech output as chaptered m4b files, deep-linked from the note
- Runs against local CPU inference with a documented context budget
Python · Slack API · Ollama · Kokoro TTS · Obsidian
-
YardWise
A garden journal built for one family, handed over with an AI-readable maintainer manual.
Django with server-rendered templates and htmx, phone-first, no build step. The owner is non-technical, so the repo ships a handover manual written for an AI assistant with a project-scoped token: the owner directs, the assistant edits, the pipeline gates the release.
- Property map, plant inventory with filters, sharing between family accounts
- Release is a semver tag; Flux image automation promotes it with no manual deploy step
- Project-only membership and a scoped token keep the blast radius to one repo
Python · Django · htmx · PostgreSQL · Flux
-
mekchess
Chess engines, neural nets, and Lichess bots in Rust, self-hosted.
A long-term playground in Rust: a Cargo workspace with a core move generator checked against an established oracle, with engines and a Lichess bot planned on top.
- FEN parsing and board representation with property-style tests against a reference library
Rust
-
pocket-agc
A jailbroken smartphone as a faithful drop-in replacement for the Apollo Guidance Computer.
Research and design scaffold for running an Apollo Guidance Computer emulation on a phone with a period-faithful DSKY interface.
Research
-
Archival audio cleanup
Hours-long tape, record, and CD transfers, split into tracks, identified, and sorted.
Fingerprinting identifies commercial recordings; anything unmatched is treated as a home recording and transcribed with a CPU-sized speech-to-text model so decades of unlabeled audio can be classified at all. Also untangled a library fractured by playlist names written into album tags. Next step is folding it into vinyl as the stage that splits record captures and delivers the tracks into Jellyfin.
ffmpeg · beets · AcoustID · faster-whisper · Python
-
Wits and Wagers
A multiplayer party game with a large tabletop question pack, deployed to the cluster.
Containerized and deployed from the private registry. Evaluated LLM-generated trivia and measured that small models fix answer shape but not facts, so the shipped pack is the curated tabletop one.
TypeScript · Next.js