Build your own Morning Brief
The demo next door runs on fictional emails. The real thing reads your actual Gmail every weekday morning and lands in your claude.ai — no code, no API keys, no server. Just a Claude subscription and about ten minutes of setup. Your first brief arrives tomorrow.
1Connect Gmail
In claude.ai, open Settings → Connectors, find Gmail, and click Connect. Google will ask you to approve read access for Claude.
Privacy: your email is read inside your own Claude account, by your own scheduled task. Nothing is shared, and nothing touches this site — everything you saw on the demo page is fictional.
2Create a scheduled task
In claude.ai, create a new scheduled task and set it to run every weekday at whatever time you want the brief waiting for you — 7:00 AM is a good default. Name it “Morning Brief”.
Prefer a weekly digest instead? Set the schedule to Monday mornings and change “the last day” in the prompt to “the last 7 days”. Everything else works as-is.
3Paste this prompt
This is the whole app. It tells Claude how to gather, how to triage, and exactly how to render — the template inside is the same design as the demo, pixel for pixel.
Read my unread Gmail and build my Morning Brief — one beautiful HTML artifact I can read in about 90 seconds.
== STEP 1 · GATHER ==
1. Using the Gmail connector, search my unread email from the last day. On Mondays, cover the whole weekend.
2. For anything important or ambiguous — a real person, a deadline, money, an appointment — open the FULL thread and read the complete body before judging it. Snippets lie: dates, amounts, and scary "action required" subject lines often turn out routine (or worse) once you read the actual email. Snippets are fine for obvious newsletters, receipts, and notifications you are only listing.
== STEP 2 · TRIAGE ==
Every unread email lands in exactly one bucket.
URGENT — "Needs response or action". Only things with real consequences: hard deadlines, direct questions from real people, money owed, anything expiring. For each item give me:
- the sender (Name · Company)
- a short due-chip like "Due Wed", "Reply today", "5 days overdue"
- the subject, lightly rewritten for clarity
- one calm line on WHY it needs me and what happens if I ignore it
- if a one-line reply would close it out, a suggested reply in my voice: warm, casual, brief
THE REST — sort into these five fixed categories, skipping any that are empty today:
📰 Newsletters — the TL;DR names the ONE worth reading and why; one dismissive line each for the rest.
📣 Sales & pitches — cold outreach and promos. The TL;DR is usually "safe to ignore both".
💸 Money — receipts, payouts, invoices, statements. Always include amounts; flag anything unusual.
🔔 Tool notifications — deploys, analytics, sign-in alerts. Tell me if everything is green.
💛 People — real humans writing to me with nothing I need to do. Keep these warm.
Tone: honest and calm, never alarmist. A routine "your statement is ready" is Money, not urgent — only real consequences earn the red zone. If nothing is urgent, say so and celebrate it.
== STEP 3 · RENDER ==
Create one HTML artifact from the template below. Rules:
- Keep the CSS exactly as written. It IS the design — do not restyle, "improve", or add to it.
- The date line is today's date. The greeting is 1–2 warm sentences that summarize the whole morning.
- The stat pills must add up to the items actually shown below them.
- Repeat the blocks marked REPEAT as many times as needed. Delete categories with no email today.
- If there are ZERO urgent items, replace the whole urgent-section div with:
<p class="signoff">Nothing needs you today — a rare perfect morning. 🎉</p>
- Every email must be clickable. Use the real Gmail thread id in links like
https://mail.google.com/mail/u/0/#inbox/THREAD_ID
Urgent items get the "Open email →" link; category bullets link the sender's name.
(If I use more than one Google account in this browser, u/0 is the first account I signed into — I'll tell you to switch to u/1, u/2, etc. if links open the wrong inbox.)
- End with a one-line italic sign-off that is different every day.
- The whole brief should read in ~90 seconds. When in doubt, cut.
== TEMPLATE ==
<style>
:root {
--bg: #EFF5FC;
--bg-glow: linear-gradient(180deg, #BEDCF8 0%, #EFF5FC 70%);
--card: #FFFFFF;
--ink: #29313B;
--muted: #74808D;
--line: #E3E9F0;
--pill: #F1F5FA;
--sun: #FFB020;
--sun-deep: #DE8A06;
--sun-soft: #FFF1CE;
--urgent: #E4472E;
--urgent-deep: #C33517;
--urgent-soft: #FFEDE8;
--cat-sales: #D64B8A; --cat-sales-soft: #FCE9F2;
--cat-news: #7A5AE0; --cat-news-soft: #F0EBFD;
--cat-money: #1E9E6A; --cat-money-soft: #E4F6EE;
--cat-tools: #2E86D6; --cat-tools-soft: #E7F2FC;
--cat-people: #E8930C; --cat-people-soft: #FFF1CE;
--serif: "Iowan Old Style", Palatino, "Palatino Linotype", Georgia, serif;
--mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
--sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #101823;
--bg-glow: linear-gradient(180deg, #1C2C42 0%, #101823 70%);
--card: #1A2430;
--ink: #EFF3F8;
--muted: #9FACBC;
--line: #2C3949;
--pill: #232F3D;
--sun: #FFB829;
--sun-deep: #FFC85C;
--sun-soft: #3D3111;
--urgent: #FF6B4A;
--urgent-deep: #FF8A6E;
--urgent-soft: #43231B;
--cat-sales: #F27DB4; --cat-sales-soft: #3D2231;
--cat-news: #A78BFF; --cat-news-soft: #2C2745;
--cat-money: #4CC998; --cat-money-soft: #1C382C;
--cat-tools: #6AB4F5; --cat-tools-soft: #1E3247;
--cat-people: #FFC85C; --cat-people-soft: #3D3111;
}
}
:root[data-theme="light"] {
--bg: #EFF5FC; --bg-glow: linear-gradient(180deg, #BEDCF8 0%, #EFF5FC 70%);
--card: #FFFFFF; --ink: #29313B; --muted: #74808D; --line: #E3E9F0; --pill: #F1F5FA;
--sun: #FFB020; --sun-deep: #DE8A06; --sun-soft: #FFF1CE;
--urgent: #E4472E; --urgent-deep: #C33517; --urgent-soft: #FFEDE8;
--cat-sales: #D64B8A; --cat-sales-soft: #FCE9F2;
--cat-news: #7A5AE0; --cat-news-soft: #F0EBFD;
--cat-money: #1E9E6A; --cat-money-soft: #E4F6EE;
--cat-tools: #2E86D6; --cat-tools-soft: #E7F2FC;
--cat-people: #E8930C; --cat-people-soft: #FFF1CE;
}
:root[data-theme="dark"] {
--bg: #101823; --bg-glow: linear-gradient(180deg, #1C2C42 0%, #101823 70%);
--card: #1A2430; --ink: #EFF3F8; --muted: #9FACBC; --line: #2C3949; --pill: #232F3D;
--sun: #FFB829; --sun-deep: #FFC85C; --sun-soft: #3D3111;
--urgent: #FF6B4A; --urgent-deep: #FF8A6E; --urgent-soft: #43231B;
--cat-sales: #F27DB4; --cat-sales-soft: #3D2231;
--cat-news: #A78BFF; --cat-news-soft: #2C2745;
--cat-money: #4CC998; --cat-money-soft: #1C382C;
--cat-tools: #6AB4F5; --cat-tools-soft: #1E3247;
--cat-people: #FFC85C; --cat-people-soft: #3D3111;
}
body {
background: var(--bg);
color: var(--ink);
font-family: var(--sans);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
padding: 0 16px 56px;
}
.sky {
background: var(--bg-glow);
margin: 0 -16px;
padding: 40px 16px 72px;
}
.sky-inner { max-width: 640px; margin: 0 auto; }
.sunrise {
width: 52px; height: 52px;
border-radius: 50%;
background: radial-gradient(circle at 38% 34%, #FFD968, var(--sun) 70%);
box-shadow: 0 0 0 10px rgba(255, 209, 92, 0.28), 0 0 48px rgba(255, 186, 46, 0.6);
margin-bottom: 18px;
}
.brief {
max-width: 640px;
margin: -48px auto 0;
background: var(--card);
border: 1px solid var(--line);
border-radius: 20px;
box-shadow: 0 18px 40px -24px rgba(38, 68, 105, 0.4);
overflow: hidden;
}
/* ---------- Masthead ---------- */
.masthead { padding: 26px 28px 18px; }
.masthead-top {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 12px;
}
.wordmark {
font-size: 14px;
font-weight: 800;
letter-spacing: 0.01em;
color: var(--sun-deep);
}
.sample-chip {
font-size: 11px;
font-weight: 600;
color: var(--sun-deep);
background: var(--sun-soft);
border-radius: 999px;
padding: 4px 11px;
white-space: nowrap;
}
.date {
font-family: var(--serif);
font-size: clamp(28px, 6vw, 38px);
line-height: 1.1;
font-weight: 600;
text-wrap: balance;
margin: 0 0 6px;
}
.greeting { font-size: 15.5px; color: var(--muted); margin: 0; }
/* ---------- Stat pills ---------- */
.stats {
display: flex;
flex-wrap: wrap;
gap: 8px;
padding: 4px 28px 20px;
font-size: 12.5px;
font-variant-numeric: tabular-nums;
}
.stat-pill {
display: inline-flex;
align-items: center;
gap: 6px;
background: var(--pill);
border: 1px solid var(--line);
border-radius: 999px;
padding: 5px 12px;
color: var(--muted);
}
.stat-pill b { color: var(--ink); font-weight: 700; }
.stat-pill.hot {
background: var(--urgent-soft);
border-color: color-mix(in srgb, var(--urgent) 30%, transparent);
color: var(--urgent-deep);
}
.stat-pill.hot b { color: var(--urgent-deep); }
/* ---------- Section headers (friendly serif) ---------- */
.section-label {
font-family: var(--serif);
font-size: 19px;
font-weight: 600;
letter-spacing: 0;
display: flex;
align-items: center;
gap: 9px;
margin: 0 0 14px;
}
.count-pill {
font-family: var(--sans);
font-size: 12px;
font-weight: 700;
border-radius: 999px;
padding: 2px 10px;
font-variant-numeric: tabular-nums;
background: var(--pill);
border: 1px solid var(--line);
color: var(--muted);
}
section { padding: 22px 28px 6px; }
/* ---------- Urgent section ---------- */
.urgent-section {
margin: 0 20px 4px;
padding: 18px 12px 4px;
background: var(--urgent-soft);
border: 1px solid color-mix(in srgb, var(--urgent) 28%, transparent);
border-radius: 16px;
}
.urgent-section .section-label { color: var(--urgent-deep); padding: 0 4px; }
.urgent-section .count-pill { background: var(--urgent); border-color: var(--urgent); color: #fff; }
.pulse {
width: 9px; height: 9px; border-radius: 50%;
background: var(--urgent);
flex: none;
}
@media (prefers-reduced-motion: no-preference) {
.pulse { animation: pulse 1.6s ease-in-out infinite; }
@keyframes pulse {
0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--urgent) 45%, transparent); }
50% { box-shadow: 0 0 0 6px transparent; }
}
}
.urgent-items { display: flex; flex-direction: column; gap: 10px; padding-bottom: 14px; }
.u-item {
background: var(--card);
border-radius: 12px;
padding: 14px 16px;
border-left: 4px solid var(--urgent);
box-shadow: 0 2px 8px -4px rgba(120, 40, 10, 0.25);
}
.u-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
flex-wrap: wrap;
margin-bottom: 2px;
}
.sender { font-weight: 700; font-size: 14.5px; }
.due-chip {
font-family: var(--sans);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.02em;
color: #fff;
background: var(--urgent);
border-radius: 999px;
padding: 3px 10px;
white-space: nowrap;
}
.due-chip.softer {
background: var(--urgent-soft);
color: var(--urgent-deep);
border: 1px solid color-mix(in srgb, var(--urgent) 35%, transparent);
}
.subject { font-size: 14px; margin: 1px 0 3px; }
.why { font-size: 13px; color: var(--muted); margin: 0; }
.open-link {
display: inline-block;
margin-top: 8px;
font-size: 12.5px;
font-weight: 600;
color: var(--urgent-deep);
text-decoration: none;
}
.open-link:hover, .open-link:focus-visible { text-decoration: underline; }
.open-link:focus-visible { outline: 2px solid var(--urgent); outline-offset: 2px; border-radius: 4px; }
.reply {
margin-top: 10px;
background: var(--sun-soft);
border-radius: 10px;
padding: 10px 12px;
}
.reply-label {
font-size: 11px;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--sun-deep);
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 4px;
}
.reply-label button {
font-family: var(--sans);
font-size: 11px;
font-weight: 600;
color: var(--sun-deep);
background: none;
border: 1px solid currentColor;
border-radius: 999px;
padding: 2px 10px;
cursor: pointer;
}
.reply-label button:focus-visible { outline: 2px solid var(--sun); outline-offset: 2px; }
.reply p { font-family: var(--serif); font-style: italic; font-size: 14px; margin: 0; }
/* ---------- Category cards ---------- */
.cats { display: flex; flex-direction: column; gap: 12px; padding-bottom: 18px; }
.cat {
border: 1px solid var(--line);
border-radius: 14px;
padding: 14px 16px;
}
.cat-head {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
.cat-emoji {
width: 30px; height: 30px;
border-radius: 9px;
display: grid;
place-items: center;
font-size: 15px;
flex: none;
}
.cat-name { font-weight: 700; font-size: 14px; flex: 1; }
.cat-count {
font-size: 11.5px;
font-weight: 700;
border-radius: 999px;
padding: 2px 10px;
font-variant-numeric: tabular-nums;
}
.cat-tldr { font-size: 13.5px; color: var(--muted); margin: 0 0 8px; }
.cat-tldr b { color: var(--ink); font-weight: 600; }
.tldr-tag {
font-size: 10.5px;
font-weight: 800;
letter-spacing: 0.06em;
border-radius: 999px;
padding: 1px 8px;
margin-right: 6px;
}
.cat-list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 5px;
}
.cat-list li {
font-size: 13px;
color: var(--muted);
display: flex;
gap: 9px;
align-items: baseline;
}
.cat-list li::before {
content: "";
width: 6px; height: 6px;
border-radius: 50%;
flex: none;
transform: translateY(-1px);
}
.cat-list b { color: var(--ink); font-weight: 600; }
.mail-link {
color: var(--ink);
font-weight: 600;
text-decoration: underline;
text-decoration-thickness: 1.5px;
text-underline-offset: 2px;
}
.mail-link:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; border-radius: 3px; }
.cat.sales .mail-link { text-decoration-color: color-mix(in srgb, var(--cat-sales) 45%, transparent); }
.cat.sales .mail-link:hover { color: var(--cat-sales); }
.cat.news .mail-link { text-decoration-color: color-mix(in srgb, var(--cat-news) 45%, transparent); }
.cat.news .mail-link:hover { color: var(--cat-news); }
.cat.money .mail-link { text-decoration-color: color-mix(in srgb, var(--cat-money) 45%, transparent); }
.cat.money .mail-link:hover { color: var(--cat-money); }
.cat.tools .mail-link { text-decoration-color: color-mix(in srgb, var(--cat-tools) 45%, transparent); }
.cat.tools .mail-link:hover { color: var(--cat-tools); }
.cat.people .mail-link { text-decoration-color: color-mix(in srgb, var(--cat-people) 45%, transparent); }
.cat.people .mail-link:hover { color: var(--cat-people); }
.cat.sales .cat-emoji, .cat.sales .cat-count, .cat.sales .tldr-tag { background: var(--cat-sales-soft); color: var(--cat-sales); }
.cat.sales .cat-list li::before { background: var(--cat-sales); }
.cat.news .cat-emoji, .cat.news .cat-count, .cat.news .tldr-tag { background: var(--cat-news-soft); color: var(--cat-news); }
.cat.news .cat-list li::before { background: var(--cat-news); }
.cat.money .cat-emoji, .cat.money .cat-count, .cat.money .tldr-tag { background: var(--cat-money-soft); color: var(--cat-money); }
.cat.money .cat-list li::before { background: var(--cat-money); }
.cat.tools .cat-emoji, .cat.tools .cat-count, .cat.tools .tldr-tag { background: var(--cat-tools-soft); color: var(--cat-tools); }
.cat.tools .cat-list li::before { background: var(--cat-tools); }
.cat.people .cat-emoji, .cat.people .cat-count, .cat.people .tldr-tag { background: var(--cat-people-soft); color: var(--cat-people); }
.cat.people .cat-list li::before { background: var(--cat-people); }
/* ---------- Sign-off & footer ---------- */
.signoff {
font-family: var(--serif);
font-style: italic;
font-size: 15.5px;
color: var(--muted);
text-align: center;
padding: 4px 28px 22px;
margin: 0;
}
footer {
border-top: 1px solid var(--line);
padding: 13px 28px 17px;
font-size: 12px;
color: var(--muted);
display: flex;
flex-wrap: wrap;
gap: 4px 8px;
}
footer .sep { opacity: 0.5; }
@media (prefers-reduced-motion: no-preference) {
.brief { animation: rise 0.5s ease-out; }
@keyframes rise {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: none; }
}
}
</style>
<div class="sky"><div class="sky-inner"><div class="sunrise"></div></div></div>
<div class="brief">
<header class="masthead">
<div class="masthead-top">
<span class="wordmark">☀️ Morning Brief</span>
<span class="sample-chip">UNREAD_COUNT unread → sorted</span>
</div>
<h1 class="date">WEEKDAY, MONTH DAY</h1>
<p class="greeting">GREETING — 1–2 warm sentences that summarize the whole morning.</p>
</header>
<div class="stats">
<span class="stat-pill hot"><b>N</b> need action</span>
<span class="stat-pill"><b>N</b> unread sorted</span>
<span class="stat-pill"><b>N</b> replies drafted</span>
<span class="stat-pill"><b>~90s</b> read</span>
</div>
<div class="urgent-section">
<h2 class="section-label"><span class="pulse"></span>Needs response or action <span class="count-pill">N</span></h2>
<div class="urgent-items">
<!-- REPEAT this u-item block for each urgent email -->
<div class="u-item">
<div class="u-head"><span class="sender">SENDER · COMPANY</span><span class="due-chip">DUE CHIP</span></div>
<p class="subject">SUBJECT, lightly rewritten for clarity</p>
<p class="why">WHY it needs me, and what happens if I ignore it.</p>
<!-- Include this reply block only when a one-line reply would close it out -->
<div class="reply">
<div class="reply-label"><span>Suggested reply</span><button type="button">Copy</button></div>
<p>"SUGGESTED REPLY IN MY VOICE"</p>
</div>
<a class="open-link" href="https://mail.google.com/mail/u/0/#inbox/THREAD_ID">Open email →</a>
</div>
</div>
</div>
<section>
<h2 class="section-label">The rest, sorted <span class="count-pill">N</span></h2>
<div class="cats">
<!-- REPEAT this cat card for each non-empty category. The class name on
.cat picks the color. The five pairs are:
news 📰 Newsletters · sales 📣 Sales & pitches · money 💸 Money ·
tools 🔔 Tool notifications · people 💛 People -->
<div class="cat news">
<div class="cat-head">
<span class="cat-emoji">📰</span>
<span class="cat-name">Newsletters</span>
<span class="cat-count">N</span>
</div>
<p class="cat-tldr"><span class="tldr-tag">TL;DR</span>One-sentence verdict for the category — <b>bold</b> the part that matters.</p>
<ul class="cat-list">
<!-- REPEAT one li per email; link the sender's name -->
<li><span><a class="mail-link" href="https://mail.google.com/mail/u/0/#inbox/THREAD_ID">SENDER</a> — one-line note on what it is and whether it's worth my time.</span></li>
</ul>
</div>
</div>
</section>
<p class="signoff">SIGN-OFF — one warm italic line, different every day. ☀️</p>
<footer>
<span>Generated at TIME</span><span class="sep">·</span>
<span>runs weekdays via a claude.ai scheduled task</span><span class="sep">·</span>
<span>Gmail connector</span>
</footer>
</div>
<script>
document.querySelectorAll('.reply-label button').forEach(function (btn) {
btn.addEventListener('click', function () {
var text = btn.closest('.reply').querySelector('p').textContent.replace(/^"|"$/g, '');
navigator.clipboard && navigator.clipboard.writeText(text);
btn.textContent = 'Copied';
setTimeout(function () { btn.textContent = 'Copy'; }, 1500);
});
});
</script>
4Tomorrow morning
When the task runs, it produces an artifact — your brief — and claude.ai notifies you that the task finished. Open it, skim the red zone first, and click any email to jump straight to it in Gmail. On your phone, it arrives in the Claude app the same way.
The first run may ask you to confirm Claude is allowed to read your inbox. Approve it once and the morning runs are hands-off.
Troubleshooting
The Gmail connector isn’t showing up
Connectors live on paid Claude plans, and Gmail must be enabled in Settings → Connectors before a task can use it. If it was connected but the task reports the connection is invalid, disconnect and reconnect it in the same settings screen — the Google authorization occasionally lapses.
Email links open the wrong Google account
Gmail links contain /u/0/, which means “the first account signed into this browser”. If you use several Google accounts, tell the task which slot is yours — add “use u/1 in Gmail links” (or u/2, …) to the prompt.
I want to change when or how often it runs
Edit the schedule on the task itself in claude.ai — the prompt doesn’t need to change unless you also want it to cover a longer window (e.g. weekly: search the last 7 days instead of the last day).
Can it do more — calendar, drafts, other inboxes?
Yes — this prompt is deliberately the simple version. Once it runs, you can ask for more in plain English: add the Google Calendar connector and a “today’s schedule” section, have it draft the suggested replies in Gmail, or run one task per inbox. There’s also a power path — a live dashboard built with Claude Code that re-reads your inbox on demand — but start here first.
Built by trainedonvibes — vibe-coded tools, honestly labeled. See the demo brief →