Back to Library
Capstone build / Stage 06

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.

What you'll have
  • 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.
4D Capstone
Build time ~half day to full day
Track 4D required, 8D extensions optional
Touches CLAUDE.md · MCPs · Sub-agents · Vercel · Supabase · Telegram or Email
Source blueprints/morning-brief/
One-click start

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.

Depends on

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).

Uses

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.

Unlocks

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.

Why this is the capstone

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 /mcp in Claude Code.
  • A delivery channel chosen ahead of time. Telegram, email, or both. You do not have to pick both.
Cost

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.

Step 01

Pull the latest course updates

3 min

Open 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.

Paste into Claude Code /update-course
Claude says the remotes look wrong, or /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.
Step 02

Confirm your connectors are alive

2 min

The brief needs your Gmail and Calendar connected. You wired these in Stage 02, but a five-second check now beats a confusing failure later.

Paste into Claude Code /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.

MCP shows red? Jump back to Stage 02 and re-run the connector flow. Five minutes there saves an hour here.
Step 03

Create your Supabase project

10 min

This 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.com if 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-brief project 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."
Paste into Claude Code

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.

SQL Editor returns errors? The database is still provisioning. Wait two minutes and retry.
Adding the project to an existing paid Supabase account? Supabase charges around $10 a month for a new project on a paid account. First-time signups stay on the free tier.
Step 04

Save your Supabase credentials safely

8 min

Your 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.

Paste into Claude Code

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_URL and NEXT_PUBLIC_SUPABASE_URL, so you can skip it.
  • Copy the anon public key into both SUPABASE_ANON_KEY and NEXT_PUBLIC_SUPABASE_ANON_KEY.
  • Copy the service_role secret key into SUPABASE_SERVICE_ROLE_KEY. Treat this one with extra care, it bypasses row-level security.
Step 05

Set up your delivery channel

7 min

Pick 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 in bot (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. Find result[0].message.chat.id. That number is your chat ID. Save it as TELEGRAM_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.
Telegram getUpdates returns an empty result? You did not actually message the bot first. Open the bot in Telegram, send hi, then retry the URL.
BotFather flow looks different than what's described? Telegram updated the bot creation flow recently. The getUpdates URL is the canonical way to grab your chat ID regardless of the flow.
Step 06

Run the brief skill

15 min

This 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.

Paste into Claude Code /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.

Skill not found? Your repo is out of date. Re-run /update-course from Step 01.
Step 07

Deploy to Vercel

15 min

This 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 origin points to your own private repo named <your-username>/agent-native-os-private. Push your work to origin: 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-lab org 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, plus TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID if 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.
Don't import the shared AI Build Lab repo. Importing an org repo forces Vercel Pro ($20) and auto-adds the instructors to your project. Your own agent-native-os-private repo on Hobby deploys free and stays yours.
Build fails with "Missing SUPABASE_URL"? You forgot to add the env vars. Project Settings, Environment Variables, add them, then Redeploy.
Deploy failed or you need to redeploy? Open the Vercel dashboard, click into your project, go to the Deployments tab, and use Redeploy. If the build failed with "Missing SUPABASE_URL", your env vars were skipped. Go to Project Settings, Environment Variables, add them, then Redeploy.
First Vercel build fails on next.js prerender or peer deps? Common. Ask Claude to retry the install with --legacy-peer-deps, then redeploy.
Step 08

Smoke test the whole loop

7 min

Run the brief skill one more time end to end:

Paste into Claude Code /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.
If all five showed up, you have a working capstone. Take a screenshot of the Telegram ping or the email, and the live Vercel dashboard. Post both in the workshop Slack so the team can see your capstone shipped.
Step 09

Confirm Supabase captured the run

3 min

Open 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.

The row didn't write? RLS is blocking the service role. Ask Claude to verify the policies on the briefs table. Open read, service-role writes is the pattern.
Step 10

Schedule the cron

10 min

The final step. The brief is built. The dashboard is live. Now you wire the cron that fires it before you wake up.

Paste into Claude Code

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.

You're on macOS and the cron never fires? Lid-closed sleep blocks the runtime. Enable "Keep computer awake when display is off" in Claude Desktop settings, or plug into power with caffeinate running.
Tomorrow morning, the brief lands without you touching anything. That's the moment to feel. Every later Stage 06 build inherits this pattern.

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:

  1. The cron fires at the time you scheduled. Headless Claude Code wakes up, the skill runs.
  2. Today's brief writes to Supabase. A new row in the briefs table dated today.
  3. The Vercel dashboard updates. Open the URL on your phone, the new brief is rendered.
  4. The delivery ping lands. Telegram or email, with the headline and your top priority.
  5. 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 the getUpdates URL 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-deps or 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 caffeinate while plugged in.
  • Supabase row never writes. RLS is blocking the service-role key. Ask Claude to dump and verify the policies on the briefs table. 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.

Back to the Library