The Morning Brief.
The capstone every cohort builds. Sources collapse into one short ping plus one full write-up. A daily brief lands in your inbox or on your phone, a deployed dashboard at your own Vercel URL renders the full write-up, and the whole loop fires while you sleep. Built across a half day to a full day.
- A live, auth-gated dashboard at your own Vercel URL that renders today's brief, your source registry, and your delivery log.
- A Supabase backend with three tables (briefs, sources, delivery_logs) storing every brief you generate. RLS enabled, open read, service-role writes.
- A daily delivery to your phone or inbox (Telegram, email, or both) plus a dated markdown file in your Obsidian vault as the local fallback.
Build this with Claude.
Hand the guide off to Claude in one paste. Claude reads the blueprint, then walks you through each step, pausing for your confirmation between steps.
How this fits in the OS.
Every prior stage. Your CLAUDE.md (Stage 01), your Gmail and Calendar MCPs (Stage 02, Claude Desktop calls these connectors), the /build-morning-brief skill and sub-agents (Stage 04), the cron pattern (Stage 05), and Infisical for secrets (Stage 01).
Vercel for the deployed dashboard, Supabase for the backend, Telegram or email for delivery, your Obsidian vault as the local fallback. Optional 8D extensions add EXA, Firecrawl, and richer source connectors.
The deployment pattern transfers. Once you've shipped the Morning Brief, the same Vercel + Supabase + cron pattern applies to every other Stage 06 build you tackle.
Watch for the shape.
Sources come in. Claude compiles the brief. The short ping goes to a channel. The full write-up lives somewhere readable. Tomorrow morning, the whole loop fires again. Source, compile, store, ping, inspect, rerun. That is what compounds.
This is not a single agent. It is the first instance of a pattern that, once shipped, you will instantiate again and again. The deployment infrastructure is the lesson, not the brief.
The capstone is not a demo. It is a blueprint you can run tomorrow. Every other concept the workshop teaches feeds into this build: your CLAUDE.md gives the agent your context, your MCPs give it your data, your skills give it your shape, your sub-agents give it parallelism, your scheduling gives it autonomy. Morning Brief is where the layers come together.
What changes for you.
The artifact is the easy part. The bigger thing is what shifts internally the first morning the brief is already on your phone when you reach for it. Three changes, in order of how soon you'll feel them:
- You stop opening five apps to figure out the shape of your day. The day comes to you, not the other way around.
- You stop carrying the "what am I forgetting" tax. The mental cost of trying to hold every commitment in your head goes away when something else is holding it for you.
- You start trusting that your agents work without you. Not as a metaphor. The brief lands at 6:30am whether you are at your computer or not. Every later build assumes you have felt this once. You earn the trust by watching one work.
This is the moment the workshop stops being a class and starts being an operating system you live in.
Before you start.
Four things specific to this build
- A Vercel account. Free tier covers everything in this build.
- A Supabase account. Free for new signups. Existing paid Supabase accounts pay about $10 a month for a new project.
- Your Gmail and Calendar MCPs (Claude Desktop calls these connectors) wired from Stage 02. Check by running
/mcpin Claude Code. - A delivery channel chosen ahead of time. Telegram, email, or both. You do not have to pick both.
Vercel and Supabase free tiers cost zero dollars. The whole capstone is on the house.
The build.
Ten steps. Supabase first because Vercel needs the Supabase URL and service-role key as environment variables at deploy time. Each step has a duration and a recovery line. If anything fails, the recovery line tells you the most common cause.
The skill handles the mechanical work. The clicks you do yourself are the ones that touch your accounts or your phone: creating the Telegram bot, approving an OAuth flow, typing a value into Infisical. Everything else is Claude running the skill and sub-agents, waiting on your confirmation between steps.
Pull the latest course updates
3 minOpen Claude Code in your local workshop folder. Onboarding wired up your remotes: upstream points at the AI Build Lab course repo (read-only), origin points at your own private GitHub repo. Course updates flow IN from upstream. Your work flows OUT to origin.
/update-course
/update-course isn't recognized? Something in onboarding didn't land. Ask Claude: "Check my git remotes and tell me which one is missing." If origin or upstream isn't set, Claude can walk you through wiring it up.
Confirm your connectors are alive
2 minThe brief needs your Gmail and Calendar connected. You wired these in Stage 02, but a five-second check now beats a confusing failure later.
/mcp
Gmail and Calendar should both show green. If either is red or missing, the brief will start with empty source data and the rest of the build wastes your time.
Create your Supabase project
10 minThis is the backend that stores your briefs, source registry, and delivery log. Vercel will read from this in Step 07, so it has to exist first.
- Sign up at
supabase.comif you haven't (free for new accounts). Signing up gives you an organization automatically. - Recommended (Supabase connector): if you've connected the Supabase connector, Claude creates the
morning-briefproject and runs the schema (0001_morning_brief.sql) for you, then confirms the tables exist. No SQL Editor, no database password to set by hand. - By hand (no connector, or to learn it): create the project yourself at supabase.com, then open the SQL Editor, paste the contents of
apps/morning-brief/supabase/migrations/0001_morning_brief.sql, and Run. You should see "Success. No rows returned."
Set up my Supabase database for Morning Brief. Recommended path: if I have the Supabase connector connected, create my morning-brief project and run the schema (apps/morning-brief/supabase/migrations/0001_morning_brief.sql) through the connector, then confirm the tables exist, so I never touch the SQL Editor. If I don't have the connector, or I'd rather do it by hand to learn it, walk me through creating the project at supabase.com and running that schema in the SQL Editor myself. My part is a free Supabase account and signing in when asked. Don't ask me to paste any Supabase keys into chat.
Either way, the agent helps. With the Supabase connector, Claude creates the project and runs the schema directly, so you skip the SQL Editor. Without the connector, you do those two steps yourself in the Supabase website and Claude tells you exactly what to paste. Your only must-do is a free Supabase account and signing in when asked.
Save your Supabase credentials safely
8 minYour API URL is public (not a secret), so Claude sets its two URL placeholders for you directly. Your two keys are secret, so Claude creates them as PASTE_HERE and you fill them in yourself, across three placeholders (the anon key under two names, service_role under one). You first paste Claude your Infisical project ID (an identifier from the URL, not a secret). You will never paste your real Supabase keys into this chat with Claude.
If Claude offers to enter a real key for you, say no. The API URL is public, so it's fine for Claude to set that one, but every real key you type yourself in Infisical. Do not create a project .env or .env.local with real values.
Use Infisical for this step. First check the CLI is installed (don't run infisical whoami, it doesn't exist, and don't print any token). Have me confirm I have an Infisical project and paste you its project ID from the URL (an identifier, not a secret). My API URL is public, not a secret, and you know it from the connector, so set its two entries directly to the real value: infisical secrets set SUPABASE_URL=https://<my-ref>.supabase.co --projectId=<my id> --env=dev, and the same value for NEXT_PUBLIC_SUPABASE_URL. Tell me briefly why that's okay: the URL is public, my keys are secrets I type myself. Then create the three KEY entries as PASTE_HERE (SUPABASE_ANON_KEY, NEXT_PUBLIC_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY); I fill those in the Infisical web UI myself. The public API URL is the only value you set for real. Don't use 1Password unless I say workshop staff moved me there. Never put a real key value in a command, this chat, or a project .env file.
After Claude finishes, fill in just the two keys yourself in the Infisical web UI (your API URL is already set). Open Supabase, Settings, then API Keys, on the Legacy API keys tab (not the default Publishable/Secret tab):
- The API URL is already set for you in both
SUPABASE_URLandNEXT_PUBLIC_SUPABASE_URL, so you can skip it. - Copy the
anonpublic key into bothSUPABASE_ANON_KEYandNEXT_PUBLIC_SUPABASE_ANON_KEY. - Copy the
service_rolesecret key intoSUPABASE_SERVICE_ROLE_KEY. Treat this one with extra care, it bypasses row-level security.
Set up your delivery channel
7 minPick Telegram, email, or both. The brief will fire to whichever channels you wire up. Most students do Telegram. Some do email-only. Some do both. If you've already shipped a Stage 03 build like iMessage Status Check or Email Reply Queue, the channel pattern is the same one at smaller scope.
If you want Telegram:
- Open Telegram. Search
@BotFather. Tap Start. - Send
/newbot. Pick a display name. Pick a username ending inbot(for example,your_morning_brief_bot). - BotFather replies with a token. Save that token to Infisical as
TELEGRAM_BOT_TOKEN. - Send your bot any message first. Bots cannot start conversations, you have to message it first or it cannot reach you. Type
hi, anything. - In a browser, open
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates. Findresult[0].message.chat.id. That number is your chat ID. Save it asTELEGRAM_CHAT_ID.
If you want email:
- The brief sends via the Gmail MCP you already wired in Stage 02. No new setup needed.
- Tell Claude the email address to send to. Yours, usually.
getUpdates returns an empty result? You did not actually message the bot first. Open the bot in Telegram, send hi, then retry the URL.
getUpdates URL is the canonical way to grab your chat ID regardless of the flow.
Run the brief skill
15 minThis is where the sub-agents wake up. /build-morning-brief reads the blueprint, asks you a handful of setup questions, then spawns sub-agents to scaffold the project, generate the brief compiler, and wire your sources.
/build-morning-brief gmail,calendar,obsidian
The skill walks you through:
- Picking your sources (Gmail, Calendar, manual notes, Obsidian vault, optional official Exa setup for 8D)
- Choosing your delivery channel (matches what you set up in Step 05)
- Choosing where the markdown fallback lands (your Obsidian Inbox folder is the recommended pick)
- Confirming a cost ceiling so the agent does not loop on expensive calls
The agent does this for you. The skill produces a compiled brief from today's sources and writes it to a dated markdown file. It also stages the Vercel project structure under apps/morning-brief/. You will not see the deployed dashboard yet, that comes in Step 07.
/update-course from Step 01.
Deploy to Vercel
15 minThis is where the dashboard goes live. Important: it must be auth-gated, so only you can see your brief.
- If you have not already, confirm
originpoints to your own private repo named<your-username>/agent-native-os-private. Push your work toorigin:git add . && git commit -m "wire morning brief" && git push. Your real secrets are in Infisical, not committed files. - In Vercel → Add New Project, choose the free Hobby plan and import your own private repo (
<your-username>/agent-native-os-private), not the AI Build Lab /aibuild-laborg repo. - Set the Project Root to
apps/morning-brief. Vercel asks during import. If you skip this, the build fails. - Framework preset auto-detects as Next.js.
- Expand Environment Variables. Add every required value from Infisical into Vercel for Production, Preview, and Development:
SUPABASE_URL,SUPABASE_ANON_KEY,SUPABASE_SERVICE_ROLE_KEY,NEXT_PUBLIC_SUPABASE_URL,NEXT_PUBLIC_SUPABASE_ANON_KEY, plusTELEGRAM_BOT_TOKENandTELEGRAM_CHAT_IDif you wired Telegram. - Click Deploy. Wait about two minutes.
- Once it deploys, enable Vercel password protection on the project (or wire Supabase magic-link auth in front of the read view). The brief contains your private data, do not leave the URL publicly readable.
agent-native-os-private repo on Hobby deploys free and stays yours.
--legacy-peer-deps, then redeploy.
Smoke test the whole loop
7 minRun the brief skill one more time end to end:
/build-morning-brief gmail,calendar,obsidian
You should see five things in order:
- The skill completes without errors.
- A new dated markdown file appears in your Obsidian vault at
~/Documents/Obsidian/Inbox/morning-brief-YYYY-MM-DD.md. - Your Vercel URL renders today's brief (you log in first if the auth gate is on).
- The Telegram ping lands on your phone (or the email lands in your inbox) with the brief headline and your top priority.
- Refresh the Vercel dashboard. The delivery log shows the new entry.
Confirm Supabase captured the run
3 minOpen Supabase. Table editor, then the briefs table. There should be a row dated today with the compiled brief. Look at delivery_logs, you should see a row for the ping that just fired. This is your audit trail.
The reason this matters: tomorrow, when the cron fires while you are asleep, this is where you'll check that it actually ran.
briefs table. Open read, service-role writes is the pattern.
Schedule the cron
10 minThe final step. The brief is built. The dashboard is live. Now you wire the cron that fires it before you wake up.
Tell Claude that you want to set this up on a cron job that will wake a Claude Code session to go do all of that autonomously. Pick the time you want it to run, like 6:30am so it lands by 7. Walk me through wiring the cron in configs/claude-code/, confirming the schedule, and documenting the kill switch in case something goes wrong overnight.
The agent does this for you. Claude generates the cron entry, configures the headless Claude Code session, sets the time, and writes a one-line kill switch you can run from your phone if the brief starts going sideways.
The pattern you just shipped.
The steps from here forward are the deployment pattern that works for any agent, not just this one. Supabase first for state and auth, Vercel for the dashboard, env vars from Infisical, and a cron on your Claude subscription that fires the loop while you sleep. Once you've shipped one, the moves transfer.
Stage 06's other cards apply the same pattern to different shapes of agent. The Ship Anything Autonomous reference walks through the pattern abstracted from any specific build, for when you want to deploy something that isn't a Morning Brief.
When it works.
You'll know the capstone is real when five things happen in order, on a morning you did not trigger anything:
- The cron fires at the time you scheduled. Headless Claude Code wakes up, the skill runs.
- Today's brief writes to Supabase. A new row in the
briefstable dated today. - The Vercel dashboard updates. Open the URL on your phone, the new brief is rendered.
- The delivery ping lands. Telegram or email, with the headline and your top priority.
- You did not touch your computer. The whole loop ran while you were asleep.
If you get all five tomorrow morning, the capstone is real. Run it for three mornings. The fact that it keeps working is what proves the architecture is yours.
If you get stuck.
Common failure modes, ranked by how often they bit students in the live workshop:
- Telegram BotFather flow. The bot does not auto-reply when you send
/start. You have to send a message to the bot, then hit thegetUpdatesURL in a browser to grab your chat ID. This trips up almost everyone. - Deploy failed and you need to redeploy. You deploy through the Vercel web UI, not a CLI. Open the dashboard, click into the project, go to the Deployments tab, and use Redeploy. If the build fails with "Missing SUPABASE_URL", you skipped the env vars, so add them under Project Settings, Environment Variables, then Redeploy.
- First Vercel build fails on next.js prerender or peer-dep conflicts. Retry with
--legacy-peer-depsor have Claude search the exact error message and patch the install command. - Cron does not fire on macOS. Lid-closed sleep mode blocks the runtime. Enable "Keep computer awake" in Claude Desktop, or use
caffeinatewhile plugged in. - Supabase row never writes. RLS is blocking the service-role key. Ask Claude to dump and verify the policies on the
briefstable. Open read, service-role writes is the pattern. - Vercel deploy went public. Anyone with the URL can read your private brief. Turn on Vercel password protection or wire Supabase magic-link auth before anything sensitive lands in the brief.
- Supabase costs $10 a month on an existing paid account. Free for first-time signups. Plan accordingly.
Still stuck? Post a screenshot, the prompt you ran, and what Claude said in the workshop Slack. Someone on the team has hit the same thing.
Where to go next.
Your Morning Brief is the foundation for the production-grade stage. The deployment pattern transfers everywhere. Here's what builds on it.