--- phase: 31 slug: puter.js-zero-config-cloud status: draft shadcn_initialized: true preset: new-york / neutral / cssVariables created: 2026-04-02 --- # Phase 31 — UI Design Contract > Visual and interaction contract for Phase 31: Puter.js Zero-Config Cloud. > Generated by gsd-ui-researcher. Verified by gsd-ui-checker. --- ## Design System | Property | Value | |----------|-------| | Tool | shadcn | | Preset | new-york, baseColor: neutral, cssVariables: true, style: new-york | | Component library | Radix UI (via shadcn) | | Icon library | lucide-react | | Font | System UI (inherited from body; no custom font declared in index.css) | Source: `/opt/nexus/ui/components.json` + `/opt/nexus/ui/src/index.css` --- ## Spacing Scale Declared values (must be multiples of 4): | Token | Value | Usage | |-------|-------|-------| | xs | 4px | Icon gaps (`gap-1`), inline badge padding | | sm | 8px | Compact element spacing (`gap-2`), within-form row gaps | | md | 16px | Default element spacing (`gap-4`), form field gaps | | lg | 24px | Section padding (`p-6`), card interior padding | | xl | 32px | Layout gaps (`p-8`) — matches existing wizard card `p-8` | | 2xl | 48px | Major section breaks — not used in wizard context | | 3xl | 64px | Page-level spacing — not used in wizard context | Exceptions: - Touch targets: `min-height: 44px` enforced globally via `@media (pointer: coarse)` in `index.css` — no per-component override required. - Provider option cards: `p-4` (16px) interior padding, matching `ModeSelector` card pattern. - Warning callout (Google OAuth risk): `px-3 py-2` (12px/8px) — compact inline alert pattern matching existing error state style. Source: existing `NexusOnboardingWizard.tsx` uses `p-8`, `gap-6`, `gap-4`, `gap-2`. ModeSelector uses `p-4`, `gap-3`, `gap-1`. --- ## Typography | Role | Size | Weight | Line Height | |------|------|--------|-------------| | Body | 14px (0.875rem) | 400 | 1.5 | | Heading | 24px (1.5rem / text-2xl) | 600 | 1.2 | | Caption / muted | 12px (0.75rem / text-xs) | 400 | 1.4 | Notes: - Heading size matches existing wizard `h1` (`text-2xl font-semibold`) — locked by Phase 30 component pattern. - Label size matches existing form label pattern (`text-sm font-medium`). - Body size matches existing paragraph + description pattern (`text-sm`). - Caption is used for step indicator (`text-xs text-muted-foreground`), provider descriptions, and warning footnotes. - No display-size text (>24px) is needed in this phase — the wizard card is constrained to `max-w-md`. Source: `NexusOnboardingWizard.tsx` lines 214, 245, 281–283, 294. --- ## Color All values are shadcn CSS custom properties resolved from `/opt/nexus/ui/src/index.css`. Both light (Catppuccin Latte) and dark (Catppuccin Mocha) themes are supported. | Role | Light value | Dark value | Usage | |------|-------------|------------|-------| | Dominant (60%) | `--background` (#eff1f5) | `--background` (#1e1e2e) | Wizard backdrop, page background | | Secondary (30%) | `--card` (#e6e9ef) | `--card` (#181825) | Wizard card surface, provider option cards | | Accent (10%) | `--primary` (#1e66f5) | `--primary` (#89b4fa) | Selected provider card border + tint, primary CTA button | | Destructive | `--destructive` (#d20f39) | `--destructive` (#f38ba8) | Google OAuth policy-risk warning text; error state text | Accent reserved for: 1. The currently selected provider option card border (`border-primary`) and tint (`bg-primary/5`) 2. The primary CTA button ("Continue with Puter", "Continue", "Get Started") 3. The focus ring on interactive inputs and buttons (`--ring`) Do NOT use accent on: provider logos, status badges, neutral labels, section headings. Source: `index.css` CSS custom properties; `ModeSelector.tsx` selected-state pattern (`border-primary bg-primary/5`). --- ## Component Inventory New components introduced in this phase: | Component | File | Reuses | |-----------|------|--------| | `ProviderSelectionStep` | `ui/src/components/onboarding/ProviderSelectionStep.tsx` | `Button`, `cn`, NexusOnboardingWizard card patterns | | `PuterAuthButton` | `ui/src/components/onboarding/PuterAuthButton.tsx` | `Button` (variant default), lucide `LogIn` icon | | `GoogleOAuthButton` | `ui/src/components/onboarding/GoogleOAuthButton.tsx` | `Button` (variant outline), lucide `AlertTriangle` icon for warning | | `ApiKeyEntryForm` | `ui/src/components/onboarding/ApiKeyEntryForm.tsx` | `Input`, `Label`, `Button` | | `ProviderRiskWarning` | inline in `GoogleOAuthButton` | styled `div` with `text-destructive` + `bg-destructive/10` — matches existing error block | Existing components consumed without modification: | Component | Source | |-----------|--------| | `Button` | `@/components/ui/button` | | `Input` | `@/components/ui/input` | | `Label` | `@/components/ui/label` | | `Skeleton` | `@/components/ui/skeleton` | | `NexusOnboardingWizard` | `@/components/NexusOnboardingWizard` — extended with new Step 4 | --- ## Interaction Contract ### Wizard Step Extension The existing 3-step wizard becomes a 4-step wizard for users without a detected local adapter: ``` Step 1: Hardware Detection → Step 2: Mode Selection → Step 3: Provider Selection (NEW) → Step 4: Root Directory ``` For users with a detected local adapter (hermes_local or claude_local), Step 3 is shown but pre-populated with the detected provider highlighted and a "Continue" shortcut. Step indicator text: "Step {N} of 4" (updated from current "Step {N} of 3"). ### Provider Selection Step Layout Three option cards in a vertical stack (matching `ModeSelector` grid pattern): 1. **Puter (free, zero-config)** — primary recommendation when no local AI and no API key - Card border: `border-primary bg-primary/5` when selected - Action: "Continue with Puter" button appears below cards when Puter is selected - Auth state: button shows spinner during `puter.auth.signIn()` popup - Post-auth state: button label changes to "Puter connected — Continue", icon: `CheckCircle` (lucide), border stays `border-primary` 2. **Google (Gemini free tier)** — shown with risk callout - Risk callout: amber/destructive inline alert (see Copywriting section) rendered inside the card when this option is selected — always visible before the "Sign in with Google" button is enabled - Action: "Sign in with Google" (disabled until risk callout has been displayed for 3 seconds — anti-accidental-click gate) - Post-auth state: "Google connected — Continue" 3. **API Key (subscription providers)** — manual entry - When selected: inline form expands below card (no new page) with provider select dropdown + API key input - Supported providers listed in dropdown: OpenAI, Anthropic, Groq (extensible) 4. **Skip for now** — ghost button below the three cards, always visible - Does not require a selection; proceeds to Step 4 with the probed default adapter ### Loading States | State | Treatment | |-------|-----------| | Puter auth popup in progress | Button disabled, spinner icon (h-4 w-4 animate-spin), label "Connecting to Puter…" | | Google OAuth in progress | Button disabled, spinner, label "Signing in…" | | API key saving | Submit button disabled, spinner, label "Saving…" | | Adapter probe in progress | Provider cards render with `Skeleton` placeholders where pre-detected tool badges would appear; probe is fire-and-forget (cards still interactive) | ### Error States All errors render inline below the triggering element using the existing error block pattern: ```
{errorMessage}
``` ### Keyboard and Accessibility - All provider option cards are `