A Telegram Mini App game layer for a 100-day personal rebuild — serverless, zero infrastructure obligations, built in a single overnight session
The 100 HUD is a self-initiated Telegram Mini App that turns a structured 100-day rebuild into a playable game. It reads Oura Ring readiness automatically, scores six metrics as pace bars, seals each night with one tap, and keeps an AI coach one message away — all on a fully serverless Cloudflare stack with no database and no server to maintain.
The brief
I was starting a 100-day structured rebuild — specific targets across sleep, fitness, relationships, and business — and wanted a game layer that would make showing up feel like play, not logging. Existing habit apps are either too generic or too heavy. The constraint was tight: no new infrastructure, no new maintenance surface, frozen scope. It had to be explorable in a browser and live inside Telegram where I already check in daily.
What I built
The 100 HUD is a Telegram Mini App that reads your Oura Ring and turns six metrics into a live scoreboard. The whole interface is organized around a glowing readiness ring — the ring color and the spirit character at its center (called Echo) shift dynamically with your Oura score: red below 70, amber at 70–84, teal at 85 and above. The entire accent system of the UI follows that hue shift.
Six metrics drive the score, called The Six: asleep-by-10 (pulled automatically from Oura), alcohol-free day, lift logged, LinkedIn post shipped, Elle Wednesday block, and a money event. Each appears as a dual-track pace bar — where you are versus where you should be at this point in the 100 days. The design deliberately avoids shame percentages.
The shutdown ritual is the core interaction: each evening the app auto-assembles the day’s activity into a recap. One tap seals it. A 10pm countdown in the interface nudges closure without guilting. The rebound mechanic replaces streak logic — a miss followed by a return within 24 hours counts as a gold rebound and displays its own celebration, framing return as harder and more meaningful than an unbroken run.
Donna AI is accessible via a full chat panel inside the app, with the current day number, Oura readiness score, and scoreboard state injected into context. The Telegram bot also accepts replies at any time — text or voice — and folds them into the nightly journal recap. Cron-triggered Telegram nudges are guilt-free by design: no streak-broken language, ever.
The 100-day arc is visualized as a full 100-cell grid with run, total days, and rebounds displayed alongside it. A rotating Creed line surfaces one identity statement per day, with a closing line on Sundays.
How it’s built
Serverless end to end: Cloudflare Pages hosts the single-file frontend (public/index.html, no build step), a Cloudflare Worker handles all server logic, and Cloudflare KV stores all user state keyed by Telegram user ID. No Supabase, no VPS, no database to maintain.
The frontend is a single 1,309-line HTML file — inline CSS with a full oklch design token system and inline JavaScript. It runs on mock data in any browser without a Worker connection, making it always explorable and testable without credentials.
The 654-line Worker handles seven endpoints: state read (/api/today, which merges KV state with a live Oura API pull on every call), metric toggle (/api/log), day seal (/api/seal which computes run/total/rebound math and awards XP), journal fragment storage, and Donna chat proxied to the Anthropic Messages API so the API key never reaches the client. Two webhook endpoints handle Telegram bot updates and one-time webhook registration.
Four cron triggers run the nudge schedule: morning brief at 07:00 Manila, soft seal nudge at 21:00, hard nudge at 21:45 (only if the day is unsealed), and nightly journal assembly at 22:30 (only if fragments exist). Manila timezone (UTC+8, no DST) is enforced device-independently throughout — the day boundary is computed from string-diffing ISO dates rather than relying on client locale, which was a correctness fix applied during the adversarial review pass before finalizing the build.
Every /api/* endpoint verifies the Telegram initData HMAC server-side. Constant-time comparison is used for the HMAC check. Once ALLOWED_USER_ID is set, writes are locked to a single user.
The build process included a four-agent adversarial review covering correctness, security, Telegram API surface, and design taste. One blocker was caught and fixed (consecutive user turns in the Anthropic message history causing a 400 error), plus approximately sixteen additional issues across timezone handling, HTML injection in journal recap formatting, cron KV race conditions, and accessibility gaps.
The pattern is cloned from a prior project (a gamified app for a younger family member) — the same CF Pages + Worker + KV architecture, adapted for the adult rebuild context.
Why it matters
This is the design philosophy I bring to personal systems: reduce the interaction to its minimum useful surface, make the default behavior do the heavy lifting, and treat the person using it as someone whose nervous system matters. The HUD pulls from Oura automatically so the sleep metric is never something you have to remember to log. The shutdown ritual compresses the end of day to a single tap. The rebound mechanic actively counters the all-or-nothing psychology that kills most habit systems.
Technically, the architecture demonstrates that a fully functional, AI-augmented personal app can be built on Cloudflare’s free tier with zero ongoing infrastructure obligations — no servers, no managed database, no deployment pipeline. The entire backend is a single JavaScript file that deploys in under a minute. The deploy guide in the README takes roughly 15 minutes from zero to live inside Telegram.
The scope was deliberately frozen. The README explicitly states: “If a feature ever needs you to grind, it is mis-specced.” That constraint shaped every design decision.
Want something like this?
That's the kind of thing I build. Tell me about yours.