What it does FocusGuard is a Chrome extension backed by a serverless AWS pipeline that:

Auto-classifies every YouTube video you open using Amazon Bedrock (Claude Haiku 4.5). Educational videos don't count against your time. Entertainment does. Tracks your daily entertainment minutes with a local timer that flushes to DynamoDB on pause / navigation. Pushes real-time alerts at 50% (soft warning toast on the YouTube tab) and 100% (full-screen hard block overlay) via WebSocket — so you get nudged the instant you cross a threshold, not the next time you happen to open the popup. Rewards educational watching with a streak counter (with a 12-hour grace period after one missed day). Shows a live weekly chart of educational vs entertainment time, and emails a weekly summary every Sunday. Lets you customize your daily limit (slider in popup) with a cooldown to prevent rage-raising during a binge. The whole pipeline is live: video metadata → Claude → DynamoDB → DynamoDB Streams → threshold Lambda → WebSocket → extension UI, all in seconds.

How we built it Frontend (Chrome MV3 extension)

content.js — injects into youtube.com/*, watches yt-navigate-finish for SPA navigation, runs the local watch timer, publishes live session seconds to chrome.storage every second for the popup to render background.js — MV3 service worker, manages the WebSocket reconnect loop, routes classify/session API calls, injects the block overlay and toasts into all open YouTube tabs popup.js / popup.html / popup.css — dashboard with smooth 1-second ticker, weekly bar chart, streak badge, limit-adjustment sliders, alert banner Backend (AWS SAM)

10 Lambdas: auth, classify, session-writer, stats, weekly-stats, set-limit, daily-reset, weekly-summary, ws-connect, ws-disconnect, stream-processor 4 DynamoDB tables: fg_users, fg_sessions (with Streams enabled), fg_daily_totals, fg_connections API Gateway HTTP API for REST endpoints + WebSocket API for live push Amazon Bedrock with Claude Haiku 4.5 via cross-region inference profile (us.anthropic.claude-haiku-4-5-20251001-v1:0) EventBridge cron schedules for the daily reset and weekly summary email CodePipeline + CodeBuild + SAM for automatic deploy on every git push Auth

bcrypt password hashing + JWT (30-day expiry) so login state persists across devices Challenges we ran into Bedrock model availability — Claude Haiku 4.5 isn't directly in us-east-2; we had to switch from anthropic.claude-3-haiku-... to the cross-region inference profile us.anthropic.claude-haiku-4-5-... so requests transparently route to a supported region. WebSocket API misconfiguration — our initial SAM template defined the WS API and the Lambda functions but forgot the actual Routes, Integrations, Deployment, and Stage. Connections were silently accepted but never invoked our handler. We had to manually wire $connect / $disconnect routes, lambda permissions, and a prod stage. Manifest V3 host_permissions — Chrome rejected https://.execute-api..amazonaws.com/* because MV3 doesn't allow two wildcards in one pattern. Switched to region-pinned patterns plus separate wss:// permission. Content script not injecting — turned out our matches pattern was /watch* but the URL path matching was inconsistent across Chrome versions. Broadened to /* on youtube.com and the script started running. CodePipeline + SAM packaging — first deploy failed with "CodeUri is not a valid S3 URI" because we forgot sam package between build and deploy. Then again because the artifact bucket wasn't created. Then again because the stage already existed when re-deploying. CloudFormation rollback on every stage rename — switching the stack name from focusguard to watchwise mid-development required surgically aborting rollbacks. DevTools confusion — figuring out that content script logs only appear in the page console, background logs only in the service worker DevTools, and popup logs only when DevTools attaches before you click outside. JWT secret rotation breaking existing tokens — when we moved the secret from SSM Secure Parameter to hardcoded for hackathon speed, every existing token became invalid silently. Git merge conflicts while two of us hacked on the same files simultaneously without a branching strategy. Accomplishments that we're proud of A fully event-driven, serverless real-time pipeline with zero polling on the critical path. Watch a video → DynamoDB Streams fire → threshold Lambda checks → WebSocket push → toast appears on your YouTube tab. End to end in single-digit seconds. Smooth 1-second live ticker in the popup using chrome.storage.onChanged events — no fetching, no polling, just the content script publishing each tick and the popup reading it. The Hard Block overlay genuinely works — full-screen takeover on every open YouTube tab the instant you cross 100%, with the same overlay re-rendering if you try to reload. Bedrock classification is shockingly accurate for music videos and short-form entertainment after we tuned the prompt with explicit category lists. Streak system with grace period — properly handles edge cases (today/yesterday counts, two-days-ago has a 12-hour grace window, then resets). Auto-deploy CI/CD — every git push ships to AWS without us touching the console. What we learned Bedrock cross-region inference profiles vs direct model IDs, and which models require which. API Gateway WebSocket APIs need explicit Routes + Integrations + Deployment + Stage — they're not free with the API resource. DynamoDB Streams as a first-class event bus for fan-out (one session write → daily total update → threshold check → WebSocket push), cleaner than synchronous Lambda chains. Chrome MV3 service worker dies between events — you cannot rely on in-memory state surviving more than a few minutes; everything important goes in chrome.storage. chrome.storage.onChanged is a quietly amazing cross-context event bus between content script ↔ background ↔ popup. The hidden cost of "use the AWS Console for everything" vs writing it in IaC — every console-clicked resource is a snowflake that breaks when you redeploy. JWT auth in pure Lambda (no Cognito) is actually pretty pleasant for a hackathon timeline. What's next for FocusGuard Music as a separate untimed category — many people legitimately study with music on; treating it the same as a vlog feels punitive. User-trained classifier — let the user label the first 10 videos as edu/non-edu and bias the Claude prompt with their personal taste (e.g., one person's tech podcast is another's distraction). Confidence scoring — "probably educational (78%)" instead of binary, with a confirmation modal on close-call videos. Cross-platform support — TikTok, Reddit, Instagram Reels, X all need the same treatment for the system to actually move the needle. Calendar integration — strict mode during scheduled work blocks, lenient outside of them. Cognito migration — replace the DIY JWT flow for production-grade auth + social login. Mobile app — a companion iOS/Android app so the streak and daily total live everywhere you watch. Public leaderboards / study groups — opt-in social accountability with a friend's daily focus score.

Built With

  • typescirpt
Share this project:

Updates