Calendar — butter docs Skip to content
Widgets / The day

Calendar

Today's agenda from Google Calendar — next-meeting countdown, one-click join, and on Pro, an AI-written brief that ties the next meeting to your recent PRs and Linear issues.

Open a new tab, see what's next. The Calendar widget shows your day's events from Google Calendar with a live countdown to the next meeting, one-click join buttons for Meet / Zoom / Teams parsed from the event description, and on Pro a one-sentence AI brief tying the meeting to the PRs and issues it likely concerns.

Free (agenda) Pro (AI brief) Requires Google Calendar OAuth 2-minute cache
Calendar
Next
PR review with Sarah
in 14 min · 2:00 – 2:30 pm
Join Meet

Sarah is reviewing the billing refactor — waiting on your sign-off before the migration.

PR #427 — refactor billing ALG-892 — Subscription v3
  • 11:00 am Standup
  • 2:00 pm PR review with Sarah
  • 3:30 pm Design sync
  • 4:30 pm 1:1 with Maria

Connect Google Calendar

Drop the widget in and you'll see a Connect Google Calendar button. Click it once — butter walks you through Google's OAuth flow with the calendar.readonly scope, and you're done. You don't register your own Google Cloud project; a small butter-operated worker holds the client secret so you don't have to.

Where the token lives: the worker brokers the handshake, then hands the access token (and refresh token) to your browser and forgets it — no persistent storage on our side. From there the token sits in chrome.storage.local on your device, and every API call goes directly from your browser to googleapis.com. We don't see what's on your calendar.

To disconnect, revoke the connection from your Google account permissions — the widget will catch the next 401 and show a Reconnect pill at the top of the card.

Note that "Connect Google Calendar" is a separate consent from "Sign in to butter with Google." Sign-in only asks for your email and profile — never your calendar. Granting calendar access is an explicit second step on the widget itself.

Add it to your dashboard

Press E to enter edit mode, A to add, pick Calendar. It drops in at four-wide, five-tall — enough height for the next-up card plus four or five agenda rows. Drag wider if you have a busy day; shorter if you only care about the next meeting.

How the data flows

  • One API call, today only. The widget fetches /calendars/primary/events with a time window covering today in your local timezone, expanded into individual instances (singleEvents=true) so recurring meetings appear once each. Cancelled events, working-location events, and birthdays are filtered out client-side.
  • Join links are parsed from the event. The widget looks at conferenceData first (Google's structured field), then hangoutLink (legacy Meet), then sweeps the description and location for Zoom / Teams / Webex / Whereby URLs. First match wins.
  • 2-minute cache. The fetched events are cached locally for two minutes, keyed in chrome.storage.local. The countdown ticks live every five seconds when the next event is within two minutes, every thirty seconds otherwise — without re-hitting Google.
  • Today's window is local. The widget uses your machine's timezone for the today range, so a 9 PM event still counts as today even when UTC has rolled over. No timezone setting needed.

The AI brief (Pro)

On Pro the next-up card grows a one-sentence brief under the event metadata. The brief is generated by passing the event (title, description, attendees, time) plus your recent GitHub PRs and Linear issues to a Supabase Edge Function that calls an LLM. The result reads like "Sarah is reviewing the billing refactor — waiting on your sign-off before the migration." with up to three chips below linking the PRs and issues the brief references.

Things to know about the brief:

  • Only the next event auto-generates. The brief runs once per upcoming event and is cached on-device for two hours, so reopening a new tab doesn't re-bill the model. Click the refresh icon on the brief to force a regeneration.
  • References are sourced from your widgets. If you have the GitHub and/or Linear widgets configured, their cached data feeds the brief. If neither is connected, the brief is generated from the event alone — usually still useful for context.
  • The payload is minimal. Event title, description, attendee names and emails, time window — plus the titles and identifiers of your recent PRs and issues. Never full PR diffs, never full issue bodies, never your tokens. No retention on OpenAI's side under their API terms, no training. See the privacy doc for the exact payload.

Settings

Setting Type Default
24-hour clock

Off renders event times in 12-hour format (2:00 pm – 2:30 pm). On switches to 24-hour (14:00 – 14:30). Affects the next-event card and the agenda list.

toggle off
Show declined events

Off hides events you've declined — usually the right default since declined meetings are noise. On surfaces them with an italic title so they're visible but visually deprioritised.

toggle off

Small things you might miss

  • Past events fade. Earlier events stay in the list at reduced opacity so you can see what's already happened today without them dominating the visual field.
  • "Starting" beats "now". When the next event is within the last ten seconds before kickoff the countdown reads starting — a clearer cue than "now" for the drop-everything moment.
  • Brief copy avoids identifier names. The brief itself says things like "the billing refactor" rather than "PR #427" — the chips below carry the identifiers, so the prose stays readable.
  • One Google account at a time. The widget shows the connected account's email in the toolbar so you can confirm which Google account is feeding it. Disconnect and reconnect to switch.

Heads up

  • Primary calendar only for now. The widget reads your primary Google calendar; secondary calendars (shared team calendars, a separate personal account) aren't pulled in yet.
  • Google only. Outlook / Microsoft 365 support is on the list but not shipped. Apple Calendar via CalDAV isn't planned because it doesn't have a workable hosted OAuth story for an extension.
  • The brief lags the data by up to two minutes. The event cache TTL is two minutes, so a meeting created just-now might not appear in the brief until the next fetch. Hit the toolbar refresh to force a re-pull.
  • Token revocation is detected, not predicted. If you revoke calendar access from Google's permissions page mid-session, the widget will keep showing cached events until the next fetch attempt — at which point it'll catch the 401 and switch to Reconnect.