This commit is contained in:
225
docs/ux-refactor/gap-cards/S12-first-launch.md
Normal file
225
docs/ux-refactor/gap-cards/S12-first-launch.md
Normal file
@@ -0,0 +1,225 @@
|
||||
# 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.ts` — `OnboardingState` (`: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" backbone** —
|
||||
`state.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.ts` — `VALUE_PROPS` (`:111-115`),
|
||||
`fadeSlide` motion preset (`:118-123`), `STEP_NAMES`. Reuse `fadeSlide` for the rework.
|
||||
- `apps/web/src/components/os/overlays/onboarding/types.ts` — `WelcomeStepProps` (`:10-12`).
|
||||
|
||||
### Supporting state already present (REUSE)
|
||||
- `apps/web/src/hooks/useOfflineStatus.ts` — `useOfflineStatus()` 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.
|
||||
Reference in New Issue
Block a user