Category
Technical Notes
Reading paths
Read end to end.
Building an AI Podcast Index
An eight-part build-along: a locally-running tool that ingests a YouTube podcast channel, extracts guests and topics, lets you clip-search by intent, and generates questions for future episodes — using uv, FastAPI, Vite + React, and a provider-switchable LLM client.
Start →Python Monorepos in 2026
A five-part series on building Python monorepos with uv workspaces — package boundaries, Pydantic-to-TypeScript shared schemas, a Vite + React frontend co-living with FastAPI, and CI that scales.
Start →uv: the 2026 Python toolchain
A six-part series on uv — why it replaces pip, venv, pyenv, pipx, and pip-tools; how to start a new Python project in 2026; and a pragmatic migration path that keeps requirements.txt where it earns its keep.
Start →Browse all series →
See every reading path on the site.
- ·3 min read
The first real Alembic revision: a column, a backfill, and the parts autogenerate can't do
Last post set up Alembic in clipdex. This one cashes the bet: add a duration_ms column to processed_videos, backfill from the existing aggregation, and switch the /episodes endpoint to read it. Three commits. The parts autogenerate gets right, the parts it doesn't, and why the backfill is the line where raw SQL would have started to hurt.

- ·3 min read
Adopting Alembic in clipdex without rewriting the query layer
The previous post named four cracks in clipdex's raw-SQL migration story. This one closes them. Declarative models that mirror the live schema, a no-op baseline revision, `alembic stamp head`, and a frozen `migrations/legacy/` directory. No query code changes. Ninety minutes.

- ·3 min read
Lefthook for a Static Site: Four Hooks That Earn Their Keep
A static Astro site doesn't need Husky-grade ceremony. But it does have four failure modes worth catching before they reach `main`: a broken type, a leaked key, a post without a `directory:` field, and a build that silently breaks production. Here's the lefthook.yml I landed on, and why each hook is there.

- ·3 min read
Raw SQL migrations: when they're enough, and the four cracks that force Alembic
Clipdex ships migrations as numbered `.sql` files applied by a Taskfile loop. That's been the right call for a teaching artifact. Here are the four specific cracks that will eventually force a move to Alembic — and the test for when 'eventually' becomes 'now'.

- ·3 min read
SMS Is a Lossy Channel: An Architect's Guide to OTPs, Alerts, and Graceful Degradation
SMS looks like a reliable transport because it usually works. Architecturally, it's a best-effort store-and-forward network with no end-to-end SLA. Here's what every engineer should design for before wiring OTPs, alerts, or 2FA to a text message.

- ·3 min read
The question generator, the cron job, and shipping it locally
Grounded question generation is one prompt away. Wrap the project with a local cron, a one-line backup, and a popular-guests landing query — and the podcast index runs on its own.

- ·3 min read
The React side: guest pages, search UI, and codegen'd types
A Vite + React SPA with three real pages — popular guests, guest detail, search — wired to FastAPI through codegen'd TypeScript types from a shared Pydantic schema. No UI framework, three pages, type-safe end to end.

- ·3 min read
Search without embeddings: Postgres tsvector, LLM rerank, and 30-second clips
For a few hundred podcast episodes, Postgres full-text search plus an LLM rerank beats embedding-based RAG on both quality and operational simplicity. No vector DB, no embedding pipeline.

- ·3 min read
Building a provider-switching LLM client: one interface, three providers, task-tier routing
A small adapter package lets you swap Anthropic, OpenAI, and local Ollama via an env var, route cheap classification to Haiku and synthesis to Opus, and add prompt caching without touching call sites.

- ·3 min read
Entity resolution for guests: fuzzy matching first, LLM disambiguation second
The same person shows up as 'Bibhusan Bista', 'Bibhusan B.', and 'B. Bista' across three episodes. Don't ask the LLM first — try cheap deterministic matching, then escalate only the ambiguous cases.
