Behind the bot that runs my house
A behind-the-scenes build log of the private Telegram bot that drives my site from the pocket: one bot and a plugin router, an allowlist that is the entire security model, the features it runs today, and what's coming next.
Most of what this site can do is trapped behind a login. A household money ledger, a chore board, a to-do spine, a newsletter gate, a trip itinerary, a status page, an agents console — each one is a private admin page that wants a browser, a session, and some navigation. None of that fits the moment you actually need it: standing at the counter with a receipt, or seeing a deploy go red from a bus seat. So I built a second front door that lives where my thumb already is — a private Telegram bot. This is the behind-the-scenes of how it's put together, what it does today, and where it's going.
One bot, not fifteen
The temptation with a project like this is to spawn a bot per feature — a money bot, a chores bot, a deploy bot — until you're juggling a drawer of BotFather tokens. I went the other way: one bot, one webhook, one plugin router.
Every Telegram update lands at a single endpoint. The router verifies it, then dispatches into a code-defined feature catalog — each feature registers a slug, an optional push schedule, command handlers, and whether it needs callback buttons. Adding a capability is adding a module to the registry, not standing up new infrastructure.
The catalog does double duty: it holds the whole roadmap, and the admin console badges what's actually wired versus what's still 'not built yet.' That means the console is the plan — I can see the shape of the finished thing while half of it is still a promise. The bot token lives in the secrets store, rotatable with no redeploy; feature toggles are just database rows the console flips.
The allowlist is the entire wall
A bot that can spend money and complete chores cannot be a thing strangers can poke. The security model is deliberately boring and total: an identity allowlist maps Telegram user ids to roles — admin, household, traveler. An update from anyone else is logged and silently dropped. No reply, no error, not even a rejection — the bot should be invisible to anyone who guesses it exists.
The silence is also the onboarding flow: a new person DMs the bot, nothing happens, but their user id surfaces in the console's Log tab. I map them to a role, and their next message just works.
Three more rules hold the line. Features default off — a fresh deploy pushes nothing until I flip a toggle. The webhook fails closed: it checks a secret header in constant time and 503s if the secret is unset, and it acknowledges Telegram in milliseconds, doing the real work afterward so a slow query can't trigger a retry storm. And every actionable button carries an HMAC signature, because callback data is attacker-suppliable by any allowed user — a stale button from a day-old message can't replay an action. Every table is row-level-secured with no anonymous access.
What it actually does
The features fall into four shapes.
Morning pushes. A daily briefing folds overdue and due-today to-dos (bills keep their 💳 identity), chores, and a weather line for home into one message. A trip companion pings the traveler with tomorrow's stop. A site-health canary watches the same signal the public status page renders and only speaks on a real transition.
Capture from the pocket. Send a photo of a receipt and Claude's vision parse pulls merchant, amount, category, and date straight into the ledger — no command, no typing. /money 12.50 Dunkin logs a manual transaction with the category inferred from the vendor.
Approve from chat. The Friday newsletter draft and each LinkedIn post arrive with Approve / Discard buttons that run the exact same status-guarded send the admin page uses — a pressed button from an admin-role identity is an admin action, red-line checks and all. A /hire inquiry fires a lead alert the instant it's filed.
Quick actions. /todo add, /todo list with a ✓ button per row, /todo done; a chores nudge whose inline checkmarks complete the chore and re-render the list in place. One pure ordering function feeds the numbered list, the buttons, and the done command so they can never drift apart.
Built in phases — and the review that earned its keep
I shipped this in phases, letting the catalog carry the unbuilt parts as visible roadmap rather than hidden TODOs. Phase 3 landed five household-action features in a single pull request — and then I ran a high-effort, multi-angle code review over that PR before merging.
It was worth it. The review found eight real bugs, two of them genuinely nasty: an unguarded database call that would have crashed the webhook handler — which, because Telegram redelivers anything that doesn't get a clean acknowledgment, would have turned into roughly 24 hours of retry storms. And a newsletter approve button left live after a permanent send failure, so a tap would have looked like it worked while doing nothing. All eight were fixed in one commit, tests green, same day. The lesson that stuck: for a surface that holds credentials and moves money, the review is not optional polish — it's part of building the thing.
What's next
Phase 4 is already drawn in the catalog. An /ask concierge that runs the site's semantic search from inside the chat, so the bot can answer questions about my own work and link the source. A note-to-self that lets me dump free-form text and have Claude classify and route it to the right spine — a to-do, a money note, a draft. A CRSS flashcard drill for spare minutes.
The larger arc is wiring the bot to the rest of the platform's nervous system. The site now runs a small fleet of autonomous agents — a credential steward and supervisor that govern the access estate, plus a roster of audit operators — and they already open incidents and email on failures. Telegram is the obvious place for those to surface: an incident I can acknowledge with a tap, a daily agent-health line next to the chore nudge, a gate where a risky action waits for a human yes. The approve-from-chat plumbing is already proven on newsletters and LinkedIn; pointing it at the agents is mostly a matter of catalog entries.
The throughline of the whole project is small: build a command center you actually trust, and put it in the place you already are. The hard part was never the features. It was making the front door safe enough to leave unlocked in your pocket.
Get the next one
An occasional note when something genuinely new ships here — essays, free tools, projects. No schedule, no filler, easy out.
Need something like this built?
I design and ship AI tools, full-stack apps, and data pipelines — end to end, to production. Tell me the problem in a sentence; I'll give you an honest read on fit within a day.
Work with me →