## What
Fixes two bugs reported by a customer (Plain T-1289) using the Supermemory browser extension.
### Bug 1 — extension sign-in loop
When a user logs out of the _extension_ but is still authenticated in the _web app_, the extension's Sign-in button opens `/login`, which short-circuited via a bare `router.replace("/")`. That path never carried the `extension-auth-success` flag the dashboard waits on before `postMessage`\-ing the session token to the extension content script — so the extension never received a token and stayed stuck on "Sign in" indefinitely.
Now the already-authenticated redirect carries `?extension-auth-success=true`, matching the existing fresh-login callback behavior (no new token exposure).
### Bug 2 — stale / deleted spaces
The extension's stored default space (`local:sm-default-project`) was only set when none existed, never reconciled. After renaming/deleting spaces in the web app, the popup kept showing save buttons pointing at dead spaces. Now the popup reconciles the stored default against the freshly-fetched live list: resets to the first space if the stored one was deleted, and refreshes the cached copy (label/containerTag) if it was renamed.
The onboarding rework moved the flow to app/(app)/onboarding and dropped the funnel tracking, so onboarding_completed stopped firing on 2026-05-02.
- Wire onboarding_step_viewed across idle/processing/done/error transitions
- Fire onboarding_completed on real completion (status=done) with source + memories_count
- onboarding_profile_submitted now carries { source }
- Add onboarding_skipped { from_step }
- Remove dead onboardingCompleted() from InitialHeader and unused name/relatable helpers
- Rebuild the integrations catalog as horizontally-scrollable category rails
(MCP, Plugins, Knowledge bases, Apps & extensions) with header chevrons
- Add an auto-rotating Featured hero with problem-led headlines, backdrop
imagery and a gradient FEATURED badge
- Surface all 9 MCP clients as individual cards that open a setup modal
styled like the plugin connect flow (reuses MCPSteps embedded variant)
- Align MCP setup steps and the Claude Desktop timeline to the design system
- Merge the Integrations and Connections settings tabs into one entry
Consolidate login routes, add animated tool context visualization on the hero panel, and polish loading states across onboarding, settings, and workspace bootstrap.
- Replace the top-left logo menu with an org switcher (Switch brain): lists organizations with avatar monograms, brand-blue active row, and the active org name (sans "Organization") shown above the supermemory wordmark.
- Switching an org persists the active org and reloads so all data re-scopes.
- Show each org's plan badge in the switcher, reusing the account settings badge (extracted OrgPlanBadge + resolveOrgPlan to a shared component).
- Match the profile dropdown to the same design (rows, hover/focus, border).
- Remove the 'Be part of the next supermemory app' research CTA card.
- Add hideCount prop to SpaceSelector; hide the space count in chat input.
Add shrink-0 to file queue rows so flexbox stops squishing them into
the max-height box (which clipped filenames via overflow-hidden), and
raise the list cap to 360px so the queue uses available modal space.
Middleware now reconstructs public URLs from portless forwarded headers and recognizes better-auth-dev session cookies so OAuth sign-in works with local API + worktree dev URLs.
The home dashboard suggestion cards routed Notion/Google Drive clicks through setViewMode("notion"|"google-drive"), but those values aren't in viewLiterals, so nuqs rejected them and silently fell back to the dashboard view — the click did nothing.
Route those two providers to the connect modal (setAddDoc("connect")), matching the Integrations 'Connections' card, and widen IntegrationParamValue to include them.
Drive-ingested PDFs persist a raw googleapis.com URL that the browser can't fetch directly (403). Detect googleapis.com hostnames in PdfViewer and rewrite to `/v3/drive-proxy/<documentId>` with credentials. R2-hosted PDFs are unaffected.
Use /v3/auth/org-summaries for per-org plan tiers in settings (same as console v2).
Extract chat empty state, add space-aware subtitle, and use AutoSpaceIcon in selectors.
- Keep home Recently saved and suggestions in a stable two-column layout
- Show skeleton while recents load and empty state when none exist
- Cap org switcher dropdown height with scroll for long org lists
- Show plan tier badges on all orgs, sorted by plan rank
This PR fixes a bug in auto scroll after the first msg auto scroll was not working properly it is fixed now
It also tightens Support & Help on small screens: slightly reduced card/title spacing and stacked-button gaps, and replaces fixed-height pills with responsive vertical padding so label text is not flush with the pill edges on mobile devices
## Before
<img width="382" height="232" alt="Screenshot 2026-05-18 at 6 56 48 PM" src="https://github.com/user-attachments/assets/62c583a2-2417-44b6-8502-d6a7950eb136" />
## After
<img width="396" height="267" alt="Screenshot 2026-05-18 at 6 57 04 PM" src="https://github.com/user-attachments/assets/919dbf50-664a-44ec-aa95-287ca13fd77a" />
Pairs with the API change that populates sourceDocumentId. The dashboard reads memory-of-day from localStorage first, so without a cache-key bump users would keep seeing the stale null-sourceDocument response for the rest of today. Bumping to :v2: forces a refetch on next load.
- Replace hand-rolled motion.div sheet with Drawer from @ui/components
- Use insideOut Button for primary CTA; standardize close button with INSET shadow recipe
- Wrap content in recessed card (bg-#14161A + chrome-detail inset shadow)
- Replace 3 generic feature pills with 2x2 Check-list of honest PWA benefits
- Steps now use connected numbered circles with title + description (matches install-steps.tsx)
- Swap GradientLogo for actual app icon (/android-chrome-512x512.png)
- Add safe-area padding so CTA clears the home indicator
- Parallel noun-phrase copy: Instant launch / Full-screen mode / Native-app feel / Stays signed in
- Fix `authClient.apiKey.create()` returning undefined: better-auth resolves to `{ data, error }`, not the key directly. Use `res.data.key` (with `res.error` handling) in both `RaycastDetail` and `settings/integrations.tsx`.
- Extract `RaycastSetupModal` and reuse it across the nova home Raycast card and the Settings → Integrations Raycast modal. The new modal matches the plugins-connect design system (icon box, pill close, inset card with shared `InstallSteps`, install pill).
- Add `/settings/integrations` redirect page so `app.supermemory.ai/settings/integrations?q=raycast` lands on the Integrations tab and auto-opens the Raycast modal (the `?q=raycast` auto-trigger logic already existed; the route was the missing piece).
Nova mobile pass
- viewport: viewportFit cover for iOS safe-area-inset
- safe-area utilities (pb-safe, pt-safe, bottom-safe-5, scroll-fade-x) in globals.css
- chat FAB pinned above iPhone home indicator; chat sidebar widths responsive across sm/md/lg with min() clamps
- chat input CoT panel max-h capped via min(60dvh, 420px)
- header tab strip swapped from visible scrollbar to scroll-fade-x mask + snap-x
- nova empty state uses svh on mobile, dvh from sm up
Add-memory modal rebuilt for mobile
- mobile shell switched from fullscreen Dialog to vaul Drawer at 85svh with swipe-down dismissal and scaled background
- in-modal header removed; tabs moved to the bottom of the sheet for thumb reach
- four tab compactLabels: Note, Links, Files, Connections
- desktop tabs now render only when !isMobile (no DOM duplication)
- note/link content state lifted to parent so switching tabs preserves typed input
- NoteContent snapshots initialContent via lazy useState so the editor isn't reset on every keystroke
- shared Drawer base uses rounded-t-xl
- removed legacy pt-4 on tab content for mobile
Connections — replace expiresAt with sync-run health
- new useConnectionHealth hook reads the latest sync run and matches auth-failure patterns; backend errorKind field still needed (TODO)
- regex tightened so 401/403 require co-occurring auth/token/grant context; refresh_token requires expired/revoked/invalid/missing qualifier
- badge label changed Disconnected -> Needs reauth
- Reconnect button replaces the sync action when needsReauth, kicks off the same OAuth flow
- per-row reconnect tracking via mutation.variables instead of a single shared id (no race when multiple rows clicked)
- fallback toast when authLink is missing so the spinner can't get stuck
- sync history panel timeline capped at max-h-260 with internal scroll
- useSyncRuns no longer refetches on mount; cache (30s) actually applies, cutting N requests per modal open