Design preview · not yet built

Connects — from catalog to connected

Connects is the catalog, then the connect flow, then health.

SizePortrait scrolls 375 · sideways is a slide deckNotes
Design brief — overview · scope · journey (closed)

Apps your assistants run on — browse what's connectable, connect it (OAuth or a pasted key), see it healthy, and know the moment it needs you.

catalog grid = sanctioned exemptionpicker = vertical-first referenceReconnect / Pending — only verbsamber = user- or provider-owned wait

The widths drawn here are samples of a fluid continuum, not the only states that exist — content (spacing, type, gaps, card/column widths) scales continuously between them, each clamp reading a named container. Structure (rail, row↔stack, grid columns) steps only at sm 640 · md 768 · lg 1024; radius, hairlines, and pills never scale. Kit: design-canon.md U8.

Reading order in this document: § Desktop journey first — every desktop (and 768 tablet) frame, full flow, journey order — then § Mobile journey — 375 below it — every 375 frame, same order, laid out side by side as a wrapping grid (never a tall single-file column of phone screens). Two sections, never interleaved — a review-document convention only (this repo's design-canon.md § Mockup review reading order). Mobile 375 is still designed and scored FIRST in the /design ritual (kit canon U5/U8) — the two rules never conflate.

Part I · Active — build now
List
MystFlo Platform Preview
· Peyton
Workspace
Support
Account
Connects

Connect an app once; every assistant that needs it can use it. Amber = needs your attention.

Connected · 5
4 healthy·1 needs attention

MystFlo AI

IncludedPlatform AI zero setup Healthy
Connected

MystFlo Storage

IncludedWhere your records live zero setup Healthy
Connected

Google

peyton@uglywoo.com Connected Jul 18 Healthy Used by 2 assistants
Connected

WhatsApp Business

+60 12-345 6789 Connected Jun 02 Access token expires in 3 days
Reconnect

Stripe

Uglywoo Retreats Connected May 21 Healthy
Connected
Available connections
Browse and connect the apps your assistants run on
All Messaging Email senders Storage Payments Other
Sl
Slack
Send run alerts and human-handoff messages to your team.
+ Connect
R
Resend
Sends broadcast and receipt emails from your own domain.
+ Connect
Su
Supabase
Postgres you own — pick it as storage when activating.
✓ Connected
Ai
Soon
Airtable
We're working on Airtable as a storage option.
Connect
C7 — Catalog · ConnectsPage.tsx
  • Connected apps = flat hairline rows, no boxed card; health line states why — the pill carries the verb.
  • Superseded 2026-08-11 (Peyton): MystFlo AI and MystFlo Storage lead Connected as the two built-in rows, each carrying the quiet Included chip PLUS the exact same ConnectionStatusButton control every real app row uses — one control species everywhere. Their menus open the same as any connected row's; Disconnect (and, for AI, Switch account) render GREYED with a signed reason instead of being omitted or drawn as a dead chevron-less chip — the earlier "no status pill, no Reconnect/Disconnect" note above is retired.
  • States not drawn (canonical copy, Peyton 2026-08-11 — same convention as the detail slide-over): the two built-in menus are the S2 contract. MystFlo AI — Disconnect greyed: "MystFlo AI is built in — there's nothing to disconnect." Switch account… greyed: "MystFlo AI is the default option at the moment." MystFlo Storage — Disconnect greyed: "MystFlo Storage is where your records live — there's nothing to disconnect." Storage has no Switch account item (no signed reason exists). Wizard Storage (assistant-lifecycle.html#sec-5b) draws the Storage menu; this C7 note is the Connects-page source for all three lines. Pixel evidence: worktree .claude/tmp/s2-screenshots/s2-ai-menu-* and s2-storage-menu-*.
  • "Use your own key" swap is HIDDEN while BYOK_AI_HIDDEN (#2514) — no live BYOK-swap entry point yet; lives inside the AI row's own menu as a greyed "Switch account…" item ("MystFlo AI is the default option at the moment.") rather than a separate action, and returns live the moment the flag flips (corrected 2026-08-11).
  • "Used by N assistants" (when N > 0) is quiet meta text appended to the row's existing account/date/health line — never its own pill (the oversized badge-label--info pill is retired, see the Google row above for the reference instance).
  • Catalog grid below = the sanctioned grid exemption (browse-and-connect, like Explore).
  • Category chips = real filter set: All / Messaging / Email senders / Storage / Payments / Other.
  • No standalone AI-provider cards or AI filter — BYOK_AI_HIDDEN (#2514) + C7 sanction only the MystFlo AI + MystFlo Storage built-in rows + quiet BYOK swap.
MystFlo Platform Preview
· Peyton
Workspace
Support
Account
Connects
Available connections
Browse and connect the apps your assistants run on
All AI Messaging Storage
Sl
Slack
Send run alerts and human-handoff messages to your team.
+ Connect
R
Resend
Sends broadcast and receipt emails from your own domain.
+ Connect
Su
Supabase
Postgres you own — pick it as storage when activating.
✓ Connected
Catalog search
  • Sits above the category filter chips; filters the browse-and-connect grid by name.
  • Narrows the catalog only — the Connected list above is unaffected.
  • "AI" chip contradicts C7 / BYOK_AI_HIDDEN (frame 5) — pending pixel fix, out of scope this pass.
  • Drawn in place on the full Connects page — the search bar previously existed only as a bare 480px snippet with no shell (canon "full screen, not a component snippet", retrofit 2026-08-06).
768 not yet drawn for this flow. Desktop and 375 are the contract.
Connects

Connect an app once; every assistant that needs it can use it.

Connected · 5
4 healthy·1 needs attention

MystFlo AI

IncludedHealthy
Connected

MystFlo Storage

IncludedHealthy
Connected

Google

Healthy
Connected

WhatsApp

Token expires in 3 days
Reconnect

Stripe

Healthy
Connected
Available
All Storage
Sl
Slack
Send run alerts and human-handoff messages to your team.
+ Connect
  • Mobile: catalog grid collapses to one column — the exemption holds, just single-file.
Connect
Every connectable app maps to one of these shapes via supportedMethods in config/connections.ts — OAuth, API key, or WhatsApp's own embedded-signup + manual-fallback pair. Each shape draws ONE real exemplar (the actual shipped copy, not placeholder text) and lists every app that shares it — active and coming-soon — instead of redrawing near-identical forms per app.
Manual fallback — ApiKeyForm · PROVIDER_GUIDES.whatsapp
  • Reached by switching to the Manual tab of the same sheet as 3a — the tab strip is always rendered, so this is a sibling of 3a, not a separate screen. The "Easier path: connect through Meta instead" cross-link at the top sends founders back to 3a, and is shown only while Embedded Signup is live (never invite a founder off a working rail onto one that can't complete).
  • WhatsApp is the one provider with a MULTI-field form (Meta's API needs all four values) — every other manual-only provider (3d) uses this exact shell with a single field.
  • Numbered guide with copyable values above the fields; same sheet chrome as OAuth — header visible, no centered popup.
  • #3030/#3040 corrections (grafted in at merge, 2026-08-01): tabs self-describe (subtitle per tab) · 7-item prerequisite gate BEFORE any credential field ("No Facebook Page needed" + guide link) · token copy = System User with expiration set to Never, temporary tokens are 24h testing-only — the earlier "System User token (valid 60 days)" line was a Meta-fact error and is gone · duplicate number = inline 409 error rendered on Phone Number ID.
  • #3061 corrections (2026-08-02): "how-to" steps re-verified against live Meta screenshots — Meta moved API Setup behind Use cases → Customize (was a top-level nav item); the guide now leads founders to the real System User token path (Business Settings → Users → System Users) instead of only the temporary token API Setup shows by default.
  • Space fix (/design, 2026-08-02): the two always-open guide boxes were eating ~450–500px before any field was visible on a 375px sheet. Desktop now splits reference (guide) LEFT / active-work (fields) RIGHT via contentWidth="wide"; mobile collapses the how-to steps behind a tap (prereq list stays open — that visibility is the point of #3030).
WhatsApp connect — desktop (sheet standard: full-width band, centered work column)
MystFlo Platform
Connect WhatsApp Business
One connection — every assistant that messages customers uses it
Auto
Through Meta — about 2 minutes
Manual
Paste credentials from Meta's developer portal — about 30 minutes
Desktop splits (/design, #3061 follow-up, 2026-08-02) — mobile stays stacked
  • Full-width sticky band (title 16px + one-line subtitle, hairline, 44×44 ✕ at the page gutter) — never a hand-rolled second header.
  • contentWidth="wide" (sheet-slide-panel.md #2193/#2194 — sanctioned for "split form+preview") drops the 1120px reading-column cap so the sheet body runs to ~920px. Body splits reference LEFT 38% / active-work RIGHT, matching the locked split axis (2026-07-26: LEFT = reference/page pane, RIGHT = active work). This is NOT the AssistantModalShell page-slide mechanic — no separate real page renders, it's a plain two-column body inside one `ModalWrapper` sheet.
  • The "How to get your API key" steps collapse behind a native <details> disclosure (closed by default) — matches 3 existing call sites (MetaSetupChecklistStep, DataPrivacySection, AssistantSummaryCard.post). The "Before you start" prereq list stays always-open — that visibility is the #3030 audit's specific fix, not something to re-hide.
  • Below lg (mobile), the split collapses to a single stacked column — no room for two columns (2026-06-14 lock, applies to every 60/40 usage in this codebase) — same collapsed-how-to treatment carries over.
  • Top reveal gap keeps the dimmed page peeking through — no centered popup.
  • Healthy state drawn (no 409) — the duplicate-number error state is its own frame directly below (#3113): field-scoped red border + inline message on Phone Number ID, plus the ErrorDisplayWithAI card.
WhatsApp connect — desktop · duplicate number (409) (same sheet, submitted with a number another MystFlo account already owns)
MystFlo Platform
Connect WhatsApp Business
One connection — every assistant that messages customers uses it
Auto
Through Meta — about 2 minutes
Manual
Paste credentials from Meta's developer portal — about 30 minutes
Easier path: connect through Meta instead
Before you start, you'll need:
Facebook account
Meta developer registration
Meta Business Portfolio
Meta App with WhatsApp added
Phone number not active on personal WhatsApp (moving it to the API is one-way)
Payment method on the WABA
Business verification (needed past 250 outbound conversations/day — replies to customers don't count)
No Facebook Page needed. See the full setup guide ↗
Meta Developer Portal ↗
  1. Open your app in Meta Developer Portal
  2. Go to WhatsApp > API Setup
  3. Copy your System User Access Token (use a temporary token for testing only)
  4. Copy the Phone Number ID from the "From" section
  5. Copy the WhatsApp Business Account ID from the top of the page
  6. Paste all four values below
For production, create a System User token with expiration set to Never (Business Settings → Users → System Users). Temporary tokens expire in 24 hours — testing only.
+1 555-123-4567
••••••••••••••EAA
1234567890
This number is already connected to another MystFlo account.
1234567890
!
Number already connected
This number is already connected to another MystFlo account.
How to fix:
  1. Disconnect it from the other account first, then reconnect here — one WhatsApp number stays paired with one MystFlo account, so your messages never split across two places.
Message us
409 duplicate number — field-scoped error + ErrorDisplayWithAI · PR #3103 / issue #3113
  • ONLY Phone Number ID carries the red border + inline message (errorFieldId === 'phone_number_id' in ApiKeyForm.tsx) — number, token, and WABA ID keep their normal borders. Before #3103 every field read the shared error string and went red together; that all-red state was the bug — never draw or build it.
  • The card below the fields is ErrorDisplayWithAI with the form's friendlyOverride: title "Number already connected", the same one-line message, one "How to fix" step, and — because supportContact: true — the "Message us" link (opens WhatsApp and auto-sends structured error context to the team) with its explainer line. "Try Again" renders because the form passes onRetry; it clears the error and re-submits.
  • All copy is verbatim from the shipped code — don't re-word it here.
  • Mobile is the same stack, drawn in full: f3b-m draws both the inline-field half AND the ErrorDisplayWithAI card, directly under the fields — identical to desktop, not just annotated.
Apps in this category
WhatsApp Business Mailchimp · soon
OAuth — OAuthForm.tsx · AUTO_METHOD_LABELS
  • Single CTA to the provider's own consent screen — no manual fallback exists for OAuth-only providers, so the Manual tab renders disabled (supportedMethods.apiKey: falsehasManual false). The Auto tab is always the default.
  • One consent checkbox, scopes up front, single CTA — MystFlo never collects the provider's credentials itself.
  • Bottom sheet over the dimmed content area; app header stays fully visible (C1) — never a centered dialog.
MystFloPlatform
Connects

Connect Google

MystFlo will be able to read and edit only the Sheets and Docs you create or pick — never your whole Drive.

Sheets Docs Drive (picked files)
  • Desktop — same sheet chrome, wider background page; content column stays capped, never stretches full width.
Apps in this category
Google Slack Airtable · soon Twitter/X · soon Discord · soon Gmail · soon
768 not yet drawn for this flow. Desktop and 375 are the contract.
3aUnique — WhatsApp Embedded Signup (its own state machine; nothing else works like this)
Embedded Signup — EmbeddedSignupForm.tsx
  • WhatsApp's PRIMARY connect path since Embedded Signup shipped — one click into Meta's own popup, not a form. Undrawn in this artifact until now; the manual 4-field form (3b) is the fallback, not the default.
  • 7 real states: idle → loading-sdk → waiting-popup → exchanging → success, with two off-ramps — error (retry / switch to manual / Meta's own onboarding page) and ineligible (Meta's 7-day WhatsApp-Business-App activity requirement not met yet).
  • Auto and Manual are peer tabs — ConnectionModal.tsx always renders the tab strip (lit-underline idiom, Auto default with a quiet "· Recommended"), one self-describing subtitle per tab. The form's own "Prefer manual setup?" link is suppressed in this host (hideManualFallback), so the tab is the only way across. Corrected against shipped code at merge time — the pre-merge draft of this frame claimed the tabs had been replaced by a text link, which was never true of the shipped modal.
  • Desktop uses the identical sheet chrome for every state (only the background page widens) — not redrawn per state; the desktop pairing is drawn once in 3b (WhatsApp) and once in 3c (OAuth).
WhatsApp connect — user flow (Embedded Signup LIVE 2026-07-31) — the routing map for the 3a ↔ 3b pair: which tab a founder lands on, and where each branch ends. The phone frames draw the individual states; this draws the paths between them.
                 Connects → "Connect" on the WhatsApp card
                                │
                    sheet opens — AUTO tab is default
                                │
      ┌────────── AUTO (3a) ────┴────────── MANUAL (3b) ─────────┐
      ▼                                                          ▼
 has a Facebook account?                          7-item prerequisite gate
  no → "Create one free"                          (before any fields — incl.
      │ yes                                       System User token / Never)
      ▼                                                          │
 [Connect with Meta] ──► Meta popup                              ▼
  Business Portfolio, WABA, and                   paste 4 credentials → Save
  number can be CREATED in-popup                                 │
  (coexistence offered if number                  live Graph validation
  is on the WhatsApp Business app)                (EF whatsapp?action=connect)
      │                                        ┌────────────┼─────────────┐
      ▼                                        ▼            ▼             ▼
 auth code → server-side exchange         409 number    400 invalid    success
  (same EF, action=connect)               already       credentials       │
      │                                   connected         │             │
      ▼                                   inline field  error state +     ▼
  Connected ✓                             error         retry         Connected ✓
Connects

Connect WhatsApp Business

Auto
Through Meta — about 2 minutes
Manual
Paste credentials from Meta's developer portal — about 30 minutes
Connect WhatsApp in one click

Meta's Embedded Signup handles everything — no manual setup needed

Set up in under 2 minutes
Keep replying from your phone — AI handles the rest
Secure — encrypted end-to-end
Want to keep using the WhatsApp Business app on your phone too? Start there first, then connect here. A number already moved to API-only can't add the app back afterward.

Requires a Facebook account. Don't have one? Create one free

idle WhatsApp — Auto (Embedded Signup, EmbeddedSignupForm.tsx)
  • LIVE (2026-07-31). Facebook login must pre-exist; Business Portfolio, WABA, and number are all creatable inside Meta's popup — coexistence offered when the number is already on the WhatsApp Business app.
  • Pre-flight note warns the one-way API migration BEFORE the popup, not after failure.
  • Default state — always clickable (Meta allows 10 test users pre-app-review).
  • States after CTA: waiting-popup → exchanging (server-side code exchange) → success. Popup failure offers retry, manual switch, or Meta's hosted onboarding page.
Connects
Complete setup in the Meta popup

Follow the steps in the popup to connect your WhatsApp Business account

🛡Secured by Meta
waiting-popup
  • Also stands in for loading-sdk/exchanging — same spinner shell, only the headline text changes ("Preparing Meta login…" / "Connecting your WhatsApp account…").
Connects
WhatsApp Connected
Your WhatsApp Business account is now connected
success
Connects
!

Something went wrong. Please try again.

Or enter credentials manually

Or use Meta's onboarding page ↗

error
  • The two "manually" off-ramps here and on ineligible are the form's own escape hatches (they survive hideManualFallback, which only hides the idle-state link) — both land on 3b.
Connects
Your number needs a bit more history

Meta requires your WhatsApp Business App number to have at least 7 days of real conversations before it can connect to platforms like MystFlo. This is a Meta security requirement — not a MystFlo limitation.

How to get eligible
01Use the WhatsApp Business App on your phone for at least 7 days
02Send and receive real messages with customers or contacts
03Come back to MystFlo and try connecting again
What you get once connected
AI handles customer messages automatically
Keep replying manually from your phone too
One number for both — no second phone needed

Already have API credentials? Enter them manually

ineligible
  • Meta's 7-day WhatsApp-Business-App activity gate — the founder-facing framing is deliberately "not a MystFlo limitation."
3bManual fallback — WhatsApp, duplicate-number (409) state
Connects

Connect WhatsApp Business

Auto
Through Meta — about 2 minutes
Manual
Paste credentials from Meta's developer portal — about 30 minutes
Before you start, you'll need:
Facebook account
Meta developer registration
Meta Business Portfolio
Meta App with WhatsApp added
Phone number not active on personal WhatsApp (moving it to the API is one-way)
Payment method on the WABA
Business verification (needed past 250 outbound conversations/day — replies to customers don't count)
No Facebook Page needed. See the full setup guide ↗
How to get your API key Open Use cases → your WhatsApp use case → API Setup ↗
  1. Copy the Phone Number ID and WhatsApp Business Account ID shown under Step 1 (they have their own copy icons)
  2. For the access token: Business Settings → Users → System Users → add or select one → assign Full control on your WhatsApp Business Account → Generate New Token, expiration set to Never
  3. Paste all four values below
The token shown directly on API Setup is temporary and expires in 24 hours — testing only.
+1 555-123-4567
••••••••••••••EAA
1234567890
This number is already connected to another MystFlo account.
1234567890
!
Number already connected
This number is already connected to another MystFlo account.
How to fix:
  1. Disconnect it from the other account first, then reconnect here — one WhatsApp number stays paired with one MystFlo account, so your messages never split across two places.
Message us
  • Drawn in its 409 state — the duplicate-number error is inline on Phone Number ID (red border + message) AND the ErrorDisplayWithAI card below the fields, identical stack to desktop f3b (#3113). The healthy state is the same frame without .fld.err/.err-card; see the desktop frame below.
3cAuto only — OAuth (exemplar: Google), consent sheet
Connects

Connect Google

MystFlo will be able to read and edit only the Sheets and Docs you create or pick — never your whole Drive.

Sheets Docs Drive (picked files)
idle
3cAuto only — OAuth, success confirmation
Connects
Connected successfully
Google is now connected and available across all assistants.
success
  • Replaces the form ~1.5s, then the sheet closes and the toast fires underneath.
3dManual only — API key (exemplar: Stripe)
API key — PROVIDER_GUIDES.stripe
  • Same shell as 3b's guide-box + fields, but ONE field instead of four — this is the shape every other manual-only provider shares (Anthropic, OpenAI, Gemini, Resend, MailerLite, Kit, Supabase all follow this exact structure with their own PROVIDER_GUIDES entry — only the URL, steps, warning, and key format differ).
Connects

Connect Stripe

Stripe API Keys ↗

You'll need a Stripe account. Sign up or log in first.

  1. Go to Developers → API keys in your Stripe Dashboard
  2. Click "Create restricted key" for better security
  3. Name your key: mystflo-stripe-key
  4. Set permissions: Read for resources you want to automate
  5. Click "Create key" and copy the secret key
  6. Paste the key below (starts with rk_live_ or rk_test_)
For testing, use test mode keys. Switch to live keys when ready for production.
••••••••••••••••rk_l
  • Single field — the shape 8 of the 11 active providers share.
Apps in this category
Stripe Anthropic OpenAI Gemini Resend MailerLite Kit Supabase Telegram · soon Klaviyo · soon Brevo · soon
6Connection detail — slide-over from the row
Health
MystFlo Platform Preview
· Peyton
Workspace
Support
Account
Connects

Connect an app once; every assistant that needs it can use it. Amber = needs your attention.

Connected · 5
4 healthy·1 needs attention

MystFlo AI

IncludedPlatform AI zero setup Healthy
Connected

MystFlo Storage

IncludedWhere your records live zero setup Healthy
Connected

Google

peyton@uglywoo.com Connected Jul 18 at 2:30 PM Healthy
Sheets Docs Drive
Connected

WhatsApp Business

+60 12-345 6789 Connected Jun 02 Access token expires in 3 days
Reconnect

Stripe

Uglywoo Retreats Connected May 21 Healthy
Connected
Healthy row
  • Emerald "Connected" pill (C12: connected/healthy is a sanctioned emerald carrier, matches live ConnectionStatusButton + T336's trigger-color invariant — corrected 2026-07-23, was previously drawn monochrome here); dropdown holds only Disconnect.
  • Granted scopes = small check chips underneath (getGoogleScopeLabels()) — no colored badge.
  • Drawn in place in the Connected list, full shell — the scopes-shown state was previously a bare row snippet with no page context (canon "full screen, not a component snippet", retrofit 2026-08-06).
  • Relationship to an assistant's own Connect tab (2026-08-06): this page lists connections by APP, account-wide, connect-once ("every assistant that needs it can use it" — see the caption above). An assistant's own Connect tab (assistant-flows/assistant-lifecycle.html sec-5b/sec-9d) lists the SAME underlying connections by ROLE instead (Communication / Payment / Storage / AI Model), scoped to what that one assistant uses — its badge is the picker for role-level choices (which provider, which resource), while R35's split-doorway sends any "fix this app" action (Reconnect, or — post-activation — "use a different account") HERE, to this exact row. The two surfaces never duplicate each other's job: role vs. resource choice lives on the assistant; account-level health, scopes, and disconnect live here.
MystFlo Platform Preview
· Peyton
Workspace
Support
Account
Connects

Connect an app once; every assistant that needs it can use it. Amber = needs your attention.

Connected · 4
2 healthy·2 need attention

Google

peyton@uglywoo.com Connected Jul 18 Healthy
Connected

WhatsApp Business

+60 12-345 6789 Connected Jun 02 Access token expires in 3 days
Reconnect

WhatsApp Business

+60 19-888 2211 Requested Jul 15 Meta is reviewing your Business account
Pending

Stripe

Uglywoo Retreats Connected May 21 Healthy
Connected
Reconnect · Pending — the only two verbs
  • Reconnect = founder can act now (token expiring, scopes stale, payment missing); reopens the connect form pre-filled.
  • Pending = waiting on the provider's own review queue; row states what's awaited, nothing to click.
  • Same amber tone, two reasons — never Verify / Recheck / Check / Refresh / Validate / Test / Manage.
  • Drawn in place in the Connected list, full shell — the Pending row previously existed only as a bare two-row snippet with no page context (canon "full screen, not a component snippet", retrofit 2026-08-06).
MystFlo Platform
Connects
← Connects · Google — connection details
Account
Signed in aspeyton@uglywoo.com
ConnectedJul 18, 2026 at 2:30 PM
Used by
Retreat DMs — On-Brand Support#4K2active
July Cohort — Retreat Booking#7N1active
Tap to return
  • Desktop mirrors mobile: masthead stripped inside the panel, dimmed peek edge of Connects on the right = return affordance.
  • Corrected 2026-07-23 (chief-designer, Wave 2 review): the panel runs FULL-WIDTH minus the 64px peek — the shared DrillOver shell Billing already ships (760px centered content column) — matching this frame's own "mirrors mobile exactly" note and the canon "slide-over as the real page" rule; the earlier drawn 560px panel cap was a drawing artifact, not a spec.
MystFlo Platform Preview
· Peyton
Workspace
Support
Account
Connects
Connected · 4

Google

peyton@uglywoo.com Connected Jul 18 Healthy
Connected

WhatsApp Business

+60 12-345 6789 Connected Jun 02 Access token expires in 3 days
Reconnect
Alert banners — RECOVERY_MESSAGES · OAUTH_ERROR_MESSAGES · Continue-Activation block, ConnectsPage.tsx
  • Stack above the Connected list, most-recent-cause first; never all three at once in real use (shown together for coverage only).
  • Flat tinted strip per severity, no glass card — locked .banner pattern (pulse.html).
  • Recovery (amber): fires from email deep-link (?focus=whatsapp&reason=credential_expired) or failed-run redirect; page auto-scrolls to the named row and rings it ~10s (amber inset + tint, not a boxed card).
  • OAuth error (red): the round-trip itself failed (state mismatch, provider denied, token exchange); dismissible, no target row to ring.
  • Continue Activation (emerald): after a mid-activation reconnect — one-tap back into the wizard, auto-dismisses 15s. Emerald is the locked call (canon C12: green = success, incl. positive-outcome banners).
  • Drive-scope reconnect (amber, T347 · DriveFileScopeBanner): pre-T340 Google connections hold legacy Drive scopes but not drive.file — every picker pick would silently 403. Same .banner.warn strip as the others; NO Dismiss at any width (functional gate, PRD §2.4). Detail in 7b below.
7b · Drive-scope reconnect (T347) — 768 tier here; the desktop rendering rides the stack above; the 375 twin sits in § Mobile journey
Connects
Connected · 4

Google

peyton@uglywoo.com Connected Jul 18 Healthy
Connected
  • ≥sm: one line — glyph · copy block · trailing CTA, vertically centered; identical at desktop (stack above). Content scales on the U8 continuum; structure steps only at sm 640.
7b — Drive-scope reconnect · DriveFileScopeBanner.tsx (shipped, restyle target)
  • Story — As a founder connected before the May-2026 Drive migration, I'm asked to reconnect Google before my next file pick silently fails, so I never hit an unexplained error.
  • AcceptanceAC-CONNECTS-12 ↗ — the adjacent Google row still renders the single ConnectionStatusButton; the banner never replaces or duplicates it. · NEW (PRD debt) — banner renders iff a status=connected Google row exists AND its stored scopes lack drive.file (googleScopes.ts:66 googleNeedsDriveFileReconnect). A legacy Drive scope is NOT required: hasDriveFileScope returns false for null/empty/absent scopes, so an unpopulated row also shows the banner — fail-loud by design, since we cannot confirm coverage. Post-T340 connections never see it. · NEW (PRD debt) — non-dismissible: no dismiss affordance at any tier; unmounts only when useGoogleScopeStatus re-checks after a successful reconnect. · NEW (PRD debt) — copy is context-keyed to exactly three strings (connects / wizard / knowledge), verbatim from the component; no fourth context without a PRD row.
  • CTA ruling (this pass, #2889): the CTA is the .banner .cta treatment (amber tint, verb Reconnect Google) — NOT an embedded ConnectionStatusButton. REQ-C2-01 scopes itself to connection ROWS (Connections row, Wizard Step 1, detail-modal Connect tab); §2.4's T347 carve-out sanctions the banner as an alert surface with "a single 'Reconnect Google' CTA". Embedding the primitive would put two status controls for one connection on one page (the row below already carries it) — the "three signals for one thing" bug §2.3.1 exists to kill — and would drag in the primitive's dropdown/label contract (REQ-C2-03/04), both wrong inside a banner. The two-verb ledger still binds the CTA label: Reconnect + provider name, exactly §2.4's own copy.
  • One treatment, three surfaces: this same .banner.warn strip renders on Brain (brain.html f26, context knowledge: "Reconnect Google to link existing documents") and in the wizard Personalize step (context wizard: "Reconnect Google to continue activation"). The wizard's artifact (assistant-flows) does not yet depict this state — flagged as mockup debt, not silently skipped. The old boxed card (rounded-xl amber glass + 40px AlertTriangle tile + outlined button) is RETIRED — this frame is the contract.
  • CTA opens IncrementalScopeModal (state #9 flow), requesting DRIVE_FILE_SCOPE. Correction (this pass, #2889): PRD §2.3.7 / REQ-C2 table say this modal's button keeps the verb "Grant access" — the shipped component (IncrementalScopeModal.tsx:190) actually renders "Allow access". Genuine spec/code drift, not a typo here: the mockup below draws the shipped text; the PRD row is stale and should be corrected to match code, not the reverse. Full sheet + hand-off sequence: 7c below.
7c · At rest — 768, then desktop; the 375 twin sits in § Mobile journey. Buttons stack on mobile, sit side-by-side from sm up
Connects

Permission needed for File selection

We need one more permission from Google to enable this feature.

Permission needed

Google Drive
Create and manage files that MystFlo opens on your behalf

This permission will be added to your existing Google connection. You can revoke access anytime from your Connects page.

  • ≥sm — actions sit side-by-side, equal width; content column caps at 480px inside the sheet (short body, doesn't need the full 720px reading cap the family uses for longer sheets).
MystFlo Platform
Workspace
Connects
Connected · 4

Google

Healthy
Connected

Permission needed for File selection

We need one more permission from Google to enable this feature.

Permission needed

Google Drive
Create and manage files that MystFlo opens on your behalf

This permission will be added to your existing Google connection. You can revoke access anytime from your Connects page.

  • Desktop — same bottom sheet, wider background page; content column stays capped, never stretches to the page's full width (overlays.html frame 2: "same sheet, both viewports").
7c/7d/7e — the permission sheet, hand-off, and return · IncrementalScopeModal.tsx (shipped, not previously drawn anywhere)
  • Story — As a founder who tapped "Reconnect Google," I'm shown exactly which permission I'm granting and one clear button to start it, so I never click into an unexplained redirect.
  • AcceptanceAC-CONNECTS-12 ↗ — the Google row keeps rendering the single ConnectionStatusButton throughout this whole flow, unaffected by the modal or the redirect. · NEW (PRD debt) — sheet presentation, title Permission needed for {featureName}, one row per requested scope (this call site always exactly one: DRIVE_FILE_SCOPE). · NEW (PRD debt) — confirming state disables both actions and swaps the primary to a spinner + "Connecting…"; no PRD row specifies this UI, only the underlying OAuth mechanics (§7). · NEW (PRD debt) — "Allow access" is a full top-level redirect, never a popup; §7 step 2/3 confirm the mechanism, no AC covers the UI presentation of the hand-off. · NEW (PRD debt) — return path is a page reload via oauth-callback → /connects?status=success, not the component's own onGranted prop (never invoked inside IncrementalScopeModal's own success path — it exists on the interface but this call site's redirect bypasses it).
  • Reuses the shared .flow-card.sheet-card/.flow-head/.flow-body chrome already established in frame 3's Connect-flow sheet — never a new sheet shape for this frame.
  • The hand-off is annotated, not drawn — Google's own consent screen is out of scope for this artifact; the mockup shows only the moment of departure and the moment of return.
  • One component, three contexts (connects / wizard / knowledge) sharing this exact body — this frame documents the connects-context copy only ("File selection"); the knowledge context is drawn in brain.html f26b, verbatim from DriveFileScopeBanner.tsx's own string tables. Wizard context artifact remains mockup debt per 7b.
768 not yet drawn for this flow. Desktop and 375 are the contract.
← Connects · Google — connection details
Account
Signed in aspeyton@uglywoo.com
ConnectedJul 18, 2026 at 2:30 PM
StatusHealthy
Permissions granted
Sheets Docs Drive (picked files)

MystFlo can only see files it creates, or files you pick — never your whole Drive.

Used by
Retreat DMs — On-Brand Support#4K2active
July Cohort — Retreat Booking#7N1active
Launch Waitlist — Waitlist + Launch#2P8active
Disconnect
3 assistants need this connection — swap the account instead of disconnecting Disconnect
Tap to return
Detail slide-over
  • Tapping the row's name (not the status pill) opens detail as a real page sliding in from the left — same choreography as "Edit in Brain" / "Invoicing details".
  • Disconnect lives here, with the in-use warning ("N assistants need this connection — swap the account instead of disconnecting") — the server-side guard (connection-removal-guard.ts) always refuses to disconnect while an active/paused/error instance requires the app, so the copy previews that outcome rather than promising a pause that can never happen. Dropped "active" from the label deliberately (2026-07-24) — the used-by list includes paused/error instances too (BLOCKING_INSTANCE_STATES), so calling all of them "active" would be inaccurate on its own panel.
  • Same warning ships on the pre-activation detail modal's disconnect confirm too (AssistantDetailModal.pre.tsx, T415 — "mirrors ConnectsPage pattern") — one promise, kept consistent across both surfaces that can trigger a disconnect.
  • States not drawn (canonical copy): used-by loading = "Checking which assistants use this…"; used-by empty = "No assistants use this connection yet." with the Disconnect line reading "No assistants depend on this connection".
  • Instance-id chip (#4K2): gated on OPEN #2590 — the build ships the plain status chip until that discriminator is decided; the drawn chip is the target state, not current drift.
7bDrive-scope reconnect banner (T347)
Connects
Connected · 4

Google

Healthy
Connected
  • 375: CTA wraps under the copy as its own 44px-min tap target, indented to the copy edge; glyph + headline stay one line. No dismiss control at any width.
  • The Google row below stays emerald Connected — the token is healthy; the missing per-file scope is surfaced by the banner alone (it isn't a §2.3.6 health signal).
7cReconnect permission sheet — at rest
Connects

Permission needed for File selection

We need one more permission from Google to enable this feature.

Permission needed

Google Drive
Create and manage files that MystFlo opens on your behalf

This permission will be added to your existing Google connection. You can revoke access anytime from your Connects page.

  • 375 — actions stacked full-width, Allow access below Not now, both ≥44px tall (flex-col sm:flex-row). Close ✕ sits top-right of the title row (the shipped ModalWrapper band, simplified here to the title row — no separate sticky band drawn at this scale).
  • Exactly one scope row for this flow (requiredScopes=[DRIVE_FILE_SCOPE]) — the list is variable-length in the component (this is why it's a sheet, not a dialog) but every Drive-reconnect call site requests the single drive.file scope.
  • The banner behind stays mounted and unchanged while the sheet is open — it isn't dismissed by opening the modal, only by a successful reconnect (7b).
7dConfirming, then the hand-off — the same tap fires both, back-to-back

Permission needed for File selection

We need one more permission from Google to enable this feature.

Permission needed

Google Drive
Create and manage files that MystFlo opens on your behalf

This permission will be added to your existing Google connection. You can revoke access anytime from your Connects page.

opens accounts.google.com
Google's own consent screen renders here — a full top-level navigation (window.location.href), not a MystFlo surface. Out of scope for this artifact.
  • "Connecting…" and the redirect are effectively simultaneous — handleRequestPermission calls setIsRequesting(true), then window.location.href = authorizationUrl in the same handler; no popup is ever attempted, no server round-trip is shown. Both buttons disable together; the primary swaps to the Shield glyph (drawn here with the shared .step-ic spinner idiom) + "Connecting…". Holds identically at every tier drawn in 7c — only the button layout (stacked vs row) differs across breakpoints, not this state.
  • The founder is now fully outside MystFlo — on Google's own domain — until Google redirects back to oauth-callback. That screen is Google's product surface, not MystFlo's; it isn't drawn here on purpose.
7eBack on /connects — the banner is gone, nothing else moved
Connects
Connected · 4

Google

Healthy
Connected
  • oauth-callback redirects to /connects?status=success; the page remounts, useGoogleScopeStatus re-checks, finds drive.file present, and the banner unmounts. The Google row does not change — it was already emerald Connected before the reconnect (the missing scope only broke file-picker calls, never the row's own health signal, frame 7).
Manual/BYOK AI provider selection (Anthropic API key, OpenAI, Google Gemini) is gated post-launch — see AUTO-Only AI Launch (playbook §"External Costs Messaging", 2026-07-19): AUTO (the platform AI wallet) is the only founder-facing AI path today. Reopens once OpenAI/Gemini actually function in the manual model chain and output quality is evaluated per model.
Provider picker — ProviderPickerModal
  • Moved out of Active 2026-07-31 (Peyton, live-screenshot review) — this multi-provider picker implies OpenAI/Google BYOK are choosable today, contradicting the AUTO-only launch gate. MystFlo AI stays the only real row until BYOK reopens.
  • Once reopened: opens from Activation "Choose AI provider" or any category chooser.
  • One radio-semantics vertical list — never a tile grid; ProviderPickerList row shape shared with ConnectionModal step 1.
  • Trailing pill = exact ConnectionStatusButton verbs: Connected (dropdown only) · Connect.
  • Rises as a bottom sheet over the dimmed content area; app header stays fully visible (C1) — never a centered dialog.
MystFlo Platform
Activate — Personalize

Behind the picker: the wizard's app-role list.

Choose AI provider

Select the AI model for your assistant

MystFlo AI Included
Platform AI — zero setup, pay-per-use. The default for every assistant.
Use your own key
Anthropic Recommended
Claude — best quality. Pay-per-use API rates.
Connected
OpenAI
Strong quality. Good fallback if you already have a key.
Connect
Google
Gemini — ~250 generations/day free. Tight for high-volume use.
Connect
You can switch providers anytime from your connected apps.
  • Desktop: same sheet chrome, one row per provider — never a 3-tile row.
Activate — Personalize

Choose AI provider

Select the AI model for your assistant

MystFlo AI Included
Platform AI — zero setup.
Use your own key
Anthropic Recommended
Claude — best quality.
Connected
OpenAI
Good fallback.
Connect
Switch providers anytime.
  • Mobile: full-width bottom sheet — a selection list is not a short confirm, so never a centered dialog.