Files
waggle-os/docs/ux-refactor/gap-cards/S12-first-launch.md
Oleg Maslov 0c3e2ead3b
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled
moving
2026-09-02 10:10:29 +02:00

15 KiB

Gap Card — S12 First Launch (Onboarding Step 1)

Screen S12 of the Waggle OS UX-refactor. PRD source of truth: §12.12 (Onboarding Flow, step 1 "First Launch - promise and privacy"), §13 Journey 1 step 2, §14.1 global states. Blueprint screen spec: _blueprint_extracted.txt:365-372 (PAGE 14, row 12). Mockup (directional only, PRD §24): Waggle_OS_Handoff_Assets/screen_12_first_launch.png. Execution model: in-place incremental refactor of apps/web — KEEP the wizard shell, redesign the welcome step per PRD §20.2.


1. Screen & purpose

The very first thing a fresh-install user sees: a minimal promise + privacy reassurance splash before any setup. It is onboarding step 1 of the 7-step flow (PRD §12.12: First Launch → Who Are You → Tool Discovery → Memory Import → Memory Review → Workspace Creation → Home Cockpit).

Purpose (blueprint S12): "Minimal promise and privacy reassurance." Acceptance (blueprint S12): "No infrastructure overload before user intent" — i.e. no API-key/tier/model questions on this screen; only the brand promise, a privacy note, a language affordance, and a single Continue action.

Mockup content (directional): Waggle "W" logo + wordmark top-left; centered hero logo; Welcome to Waggle; tagline Your work. Your memory. Your agents.; primary Continue → button; a 4-dot progress indicator; footer-left privacy line ("Your data is private. Stored locally."); footer-right language selector showing English (US).


2. Required states (PRD / Blueprint)

Blueprint S12 names exactly four states (_blueprint_extracted.txt:369-370), plus the PRD §14.1 global-state baseline that "every major screen must implement":

State Source What it means on S12
Fresh install Blueprint S12 Default: brand promise + privacy + Continue. The only state the current code renders.
Resumed setup Blueprint S12 User dismissed/closed mid-onboarding and returns; wizard re-opens at the saved step (not necessarily step 0). Resume should land on the persisted step, and First Launch should communicate "picking up where you left off" rather than re-greeting cold.
Offline Blueprint S12 + PRD §14.1 Sidecar unreachable. Screen must still render (it is pre-network) and must not block; surface a non-alarming offline indicator and keep Continue usable (downstream steps degrade, not this one).
Local-only Blueprint S12 + PRD §6/§18.1 (local-first default) Privacy promise must be truthful and visible: "your data is private / stored locally." This is the trust hook the whole onboarding leans on (PRD §12.12 acceptance: "Nothing imports without explicit review/approval").
Interaction: Continue Blueprint S12 Advance to step 2 (Who Are You).
Interaction: Change language Blueprint S12 + mockup A language affordance. No i18n infra exists (see §3) — scope decision required (§9).
Interaction: View privacy note Blueprint S12 + mockup A privacy note / link, inline or expandable.

PRD §14.1 also lists Loading / Error / Permission-denied as universal — for a pre-network welcome splash these collapse to: render immediately (no loading gate), and offline == the only "error-ish" state that matters here.


3. Current state in repo (exact files + what they do)

Disposition: rework (KEEP the wizard shell per PRD §20.2 "Onboarding wizard → simplify"; redesign the step-0 component and add the missing affordances).

The shell (KEEP)

  • apps/web/src/components/os/overlays/OnboardingWizard.tsx — full-screen early-return wizard (OnboardingWizard.tsx:399-576). Holds 8 steps (STEP_NAMES, :35): welcome / why-waggle / tier / memory-import / template / persona / api-key / ready. Step 0 auto-advances after 3 s (:136-141), Escape → Skip (:86-96), a top progress bar + step dots + Back + "Skip setup" chrome (:421-493). Rendered by Desktop.tsx:262-272 when !onboardingState.completed. This shell is the reuse target.
  • apps/web/src/hooks/useOnboarding.tsOnboardingState (:10-19: completed, step, tier?, workspaceId?, apiKeySet?, templateId?, personaId?, tooltipsDismissed?), persisted to localStorage key waggle:onboarding (:21). Auto-completes for returning users via Tauri first-launch flag (:102-131) and a sidecar getWorkspaces().length > 0 check (:139-176). ?forceWizard=true (DEV) forces step 0 (:47-57). This is the "resumed setup" backbonestate.step already persists, so resume is half-built.

The screen itself (REWORK)

  • apps/web/src/components/os/overlays/onboarding/WelcomeStep.tsx — the current step-0 component (54 lines). Renders the Waggle logo, eyebrow Your AI Operating System, Welcome to the Hive, tagline Persistent memory. Workspace-native. Built for knowledge work., a Continue → button (:39-45) + "or click anywhere". Gaps vs S12: copy differs from mockup ("Welcome to the Hive" vs "Welcome to Waggle"; tagline differs); no privacy note, no language selector, no offline/local-only awareness. It is a pure presentational component (props WelcomeStepProps = goToStep + onClickAnywhere, onboarding/types.ts:10-12).
  • apps/web/src/components/os/overlays/onboarding/WhyWaggleStep.tsx (step 1, the current 2nd screen) carries the 3 VALUE_PROPS (constants :111-115) + the "Skip — quick setup" escape hatch. Mentioned because the mockup's tagline-style promise overlaps WelcomeStep/WhyWaggle; the rework should not duplicate value-prop content across both.
  • apps/web/src/components/os/overlays/onboarding/constants.tsVALUE_PROPS (:111-115), fadeSlide motion preset (:118-123), STEP_NAMES. Reuse fadeSlide for the rework.
  • apps/web/src/components/os/overlays/onboarding/types.tsWelcomeStepProps (:10-12).

Supporting state already present (REUSE)

  • apps/web/src/hooks/useOfflineStatus.tsuseOfflineStatus() returns offline:boolean (:36-99, 2-consecutive-failure tolerance). Backs the offline state. Already consumed by Desktop.tsx:112 and StatusBar.tsx; thread it into the welcome step.
  • Privacy/local-only copy: no dedicated component exists, but the claim is true per PRD §6 ("Local-first by default") / §18.1. EraseDataDialog / data-erase surfaces exist elsewhere (overlays/EraseDataDialog.tsx) but there is no reusable "privacy note" primitive — net-new small UI.
  • No i18n infrastructure — grep for i18next | react-i18next | useTranslation | LanguageSelector | changeLanguage | navigator.language over apps/web/src returns 0 matches. All UI copy is hardcoded English. The mockup's English (US) selector has no backing system.

4. Frontend work

Reuse the wizard shell; rework step 0 into a proper First-Launch screen.

Components to create / rework

  1. REWORK WelcomeStep.tsx (or rename to FirstLaunchStep.tsx keeping the same step-0 slot)
    • Align copy to mockup: Welcome to Waggle + tagline Your work. Your memory. Your agents. (PRD §24: mockup is directional — keep current eyebrow/brand voice if it reads better, but the privacy promise + language + Continue affordances are required by blueprint, not optional).
    • Add privacy note (footer-left): short line ("Your data is private. Stored locally.") with a "view privacy note" expand (inline Popover/HoverCard from components/ui/, or a small details disclosure). Maps blueprint interaction "view privacy note" + state "local-only".
    • Add offline awareness: consume useOfflineStatus(); when offline, show a subtle indicator (reuse the StatusBar offline visual language) and keep Continue enabled (this step is pre-network).
    • Add language affordance (footer-right): see §9 open question — recommended v1 = a static, disabled-looking English (US) chip (honest: only English ships) OR a minimal selector wired to a new OnboardingState.locale that only persists the choice. Do not build full i18n in this card's scope.
    • Keep the existing Continue (goToStep(1)) + click-anywhere + autoFocus + keyboard-reachable button (WelcomeStep already satisfies WCAG 2.1.1/2.2.1 — preserve).
  2. (Optional, recommended) reconsider the 3 s auto-advance (OnboardingWizard.tsx:136-141). A privacy-reassurance screen that auto-dismisses in 3 s undercuts the "read the privacy note" intent. Rework: keep auto-advance only when no interaction, or drop it for S12. (Surgical change, one useEffect.)
  3. "Resumed setup" copy hook — when state.step > 0 on mount (returning mid-flow), the shell already restores the step; ensure First Launch isn't re-shown cold. Minimal: the existing state.step restore (OnboardingWizard.tsx:39) already handles navigation; add a one-line "Welcome back — picking up where you left off" variant if state.step was persisted > 0. Low priority; the resume mechanic exists.

Reuse targets

  • Shell: OnboardingWizard.tsx (progress bar, dots, Skip, Back, AnimatePresence step swap).
  • Motion: fadeSlide (constants.ts:118-123).
  • Offline: useOfflineStatus().
  • UI primitives: components/ui/{button,popover,hover-card,badge}.tsx (shadcn set already present).
  • Brand assets: assets/waggle-logo.{png,jpeg} (already imported by WelcomeStep, theme-aware via useIsLightTheme).

Props / state

  • WelcomeStepProps (extend): add offline: boolean (from useOfflineStatus), and — if a language chip is wired — locale?: string + onLocaleChange?: (l: string) => void.
  • OnboardingState (useOnboarding.ts:10-19): optionally add locale?: string (additive, localStorage-only, no backend). Resume already covered by existing step field.

Adapter methods / hooks

  • None new required. This screen is pre-network. useOfflineStatus already wraps the health probe; adapter.trackTelemetry('onboarding_step', …) already fires on step change (OnboardingWizard.tsx:31-33, :132). No new adapter method.

5. Backend work

This screen needs effectively NO backend. It is the pre-intent splash; every interaction is local UI + localStorage. Cross-referenced against backend-routes inventory and backend-map §03c — nothing on S12 maps to a missing PRD §16 endpoint.

Capability needed PRD §16 endpoint Status Note / what to EXTEND vs NET-NEW Substrate / migration
Continue / advance step — (none) EXISTS (client-only) Step state is OnboardingState.step in localStorage (useOnboarding.ts). No server call. none
Offline / local-only state — (no PRD §16 row) EXISTS Reuse GET /api/offline/status (offline.ts) + the health probe already used by useOfflineStatus. No new route. none
Privacy note / local-first claim — (none) EXISTS (static) Truthful per PRD §6/§18.1; copy-only. No endpoint. none
Language change — (none) MISSING (no infra) No i18n/locale backend anywhere (grep-confirmed). If a real selector is wanted, locale persists client-side in OnboardingState.locale (localStorage) — net-new client field, NOT a server route. Could later piggy-back on PUT /api/profile (profile.ts, EXISTS) or PATCH /api/settings (settings.ts, EXISTS) if locale must sync, but that is out of scope for v1. none (no .mind migration)
Returning-user / resume detection — (none) EXISTS useOnboarding already calls adapter.getWorkspaces() (GET /api/workspaces, EXISTS) + Tauri first-launch flag to auto-complete returning users. No change. none

No .mind migration. No net-new route. No substrate touch. S12 is the single cleanest screen in the refactor from a backend standpoint.


6. Shared types needed (PRD §15 vs lib/types.ts)

  • None of the PRD §15.2 unions are touched by S12 (no WorkspaceType/Scope/MemoryKind/etc. on a welcome splash).
  • The only candidate type change is local: add optional locale?: string to OnboardingState (hooks/useOnboarding.ts:10-19) if the language affordance is wired beyond a static chip. This is a frontend-only interface field, not a PRD §15 shared type, and needs no packages/shared change.
  • WelcomeStepProps (onboarding/types.ts:10-12) gains offline (+ optional locale props). Local to the onboarding folder.

7. Dependencies (screens / phases first)

  • Phase placement: PRD Sprint 5 / Release Phase 2 ("Onboarding flow: Welcome, Profile, Tool Discovery, Memory Import, Memory Review"). S12 is the entry of that sequence.
  • Hard dependency: the wizard shell (OnboardingWizard.tsx) must remain the host — already exists, so no blocker. S12 can be reworked independently of the later steps.
  • Sibling screens that share the shell (do these in the same sprint to keep the rework coherent): S13 Who Are You, S14 Tool Discovery, S15 Memory Import, S16 Memory Review, S17 Create Workspace. S12 should land first because it sets the privacy/local-first framing the rest rely on.
  • No dependency on Home Cockpit / Workspace Desktop / Command Center backend work — S12 is pre-workspace and pre-network.
  • Decision dependency: the language-selector scope question (§9) should be answered before implementation so the footer affordance isn't built twice.

8. Effort

S — Single presentational component rework inside an existing, working shell; reuse useOfflineStatus + existing motion/UI primitives; zero backend, zero migration, zero shared-type churn. The only thing that could push it toward M is electing to build a real (even minimal) language selector + locale plumbing instead of a static English (US) chip.


9. Open questions

  1. Language selector — real or honest-stub? No i18n exists (grep-confirmed: 0 matches for i18next/useTranslation/etc.). Options: (a) static disabled English (US) chip (truthful, S effort, recommended v1); (b) minimal selector that persists OnboardingState.locale but only English is wired (cosmetic); (c) defer the affordance entirely. PRD §24 lets us treat the mockup as directional, and PRD §4.4 lists native/i18n work as out-of-first-phase scope — so (a) or (c) align with the PRD. Recommend (a). Confirm before building.
  2. Keep the 3 s auto-advance on a privacy screen? Current step-0 auto-advances after 3 s (OnboardingWizard.tsx:136-141), which fights the "read the privacy note" intent. Drop it for S12, or keep-but-pause-on-interaction?
  3. Copy alignment: mockup says "Welcome to Waggle" / "Your work. Your memory. Your agents."; current ships "Welcome to the Hive" / "Persistent memory. Workspace-native…". Which brand voice wins? (PRD §24: pixels don't, but the privacy promise must be present either way.)
  4. "Resumed setup" UX: the step is restored from localStorage already — is a distinct "welcome back" treatment on First Launch wanted, or is silent step-restore sufficient?
  5. Privacy note content: inline expandable text vs link to a privacy doc/URL? No privacy-policy route or doc is wired today — needs copy + destination decided.