nexus/.planning/phases/31-puter.js-zero-config-cloud/31-UI-SPEC.md
2026-04-04 03:55:49 +00:00

13 KiB
Raw Blame History

phase slug status shadcn_initialized preset created
31 puter.js-zero-config-cloud draft true new-york / neutral / cssVariables 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, 281283, 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:

<p className="text-sm text-destructive bg-destructive/10 rounded-md px-3 py-2">
  {errorMessage}
</p>

Keyboard and Accessibility

  • All provider option cards are <button type="button"> elements (matching ModeSelector pattern) — keyboard navigable, focus ring via --ring.
  • Risk warning callout uses role="alert" so screen readers announce it immediately when the Google option is selected.
  • Auth buttons have aria-busy="true" during loading states.
  • Skip button has accessible label: "Skip provider setup for now".

Copywriting Contract

Element Copy
Step heading (provider step) "Choose a provider"
Step subheading "No API keys needed for the zero-config path."
Primary CTA — Puter "Continue with Puter"
Primary CTA — Google "Sign in with Google"
Primary CTA — API key "Save API key"
Primary CTA — generic Continue "Continue"
Skip action "Skip for now"
Puter card label "Puter — free, zero-config"
Puter card description "Free AI powered by your Puter.com account. No API key needed."
Puter cost attribution note "Usage is billed to your Puter account, not to Nexus."
Google card label "Google — Gemini free tier"
Google card description "Sign in with Google to access Gemini via your Google account."
Google risk warning heading "Policy risk — read before continuing"
Google risk warning body "Google has suspended accounts that used third-party apps with Gemini credentials. This may affect your Gmail and Workspace access. Use a Google AI Studio API key instead if you want to avoid this risk."
Google safe alternative hint "Safer option: enter a Gemini API key from Google AI Studio below."
API key card label "API key — subscription provider"
API key card description "Use your own OpenAI, Anthropic, or Groq API key."
Puter connected success "Puter connected — Continue"
Google connected success "Google connected — Continue"
Empty state (no provider selected, user tries to continue without skipping) Not applicable — "Skip for now" is always available; no blocking empty state.
Error: Puter popup blocked "Puter sign-in was blocked. Click 'Continue with Puter' directly — do not use keyboard shortcuts."
Error: Puter auth failed "Puter sign-in failed. Check your Puter.com account and try again."
Error: Google auth failed "Google sign-in failed. Try again or use an API key instead."
Error: API key save failed "Could not save API key. Check the key is valid and try again."
Error: generic setup failure "Setup failed. Please try again."
Puter auth button loading "Connecting to Puter…"
Google auth button loading "Signing in…"
API key submit loading "Saving…"
Auto-detected tool badge "{ToolName} detected" (e.g. "Hermes detected", "Claude Code detected")
Step indicator "Step {N} of 4"

Destructive actions: None in this phase. The Google OAuth risk warning is a caution, not a destructive action confirmation (no data is deleted).


Registry Safety

Registry Blocks Used Safety Gate
shadcn official (ui.shadcn.com) button, input, label, skeleton, dialog not required
Third-party none not applicable

No third-party shadcn registry blocks are used in this phase. @heyputer/puter.js is an npm package loaded via CDN script tag at runtime (not a shadcn registry block) — registry vetting gate does not apply.


Notes for Executor

  1. Wizard step count: Update the "Step N of 3" indicator to "Step N of 4" in NexusOnboardingWizard.tsx. The existing step counter is a plain string — a one-line change.

  2. Puter CDN load: Load https://js.puter.com/v2/ dynamically via loadScript() helper only when the user clicks "Continue with Puter" — not on wizard open. This avoids loading a large third-party script unnecessarily.

  3. Google risk warning timing gate: The "Sign in with Google" button must remain disabled for 3 seconds after the Google card is selected to prevent accidental clicks. Use a useEffect with a setTimeout keyed to the selected card state.

  4. Provider card pre-detection: Run agentsApi.probeAdapter() for claude_local, hermes_local, and openclaw_gateway when the wizard opens (parallel, fire-and-forget). Detected tools surface as a text-xs text-primary badge inside the card ("Hermes detected"). Non-detected tools show nothing extra.

  5. Skip-all valid state: When the user skips Step 3 entirely, the wizard must still complete Step 4 (root directory) and create at least one working agent. The existing defaultAdapter probe result handles this — if hermes_local was detected, it's used; otherwise claude_local.

  6. No new shadcn components needed: All required UI elements are covered by the existing component inventory (button, input, label, skeleton). Do not install additional shadcn components for this phase.


Checker Sign-Off

  • Dimension 1 Copywriting: PASS
  • Dimension 2 Visuals: PASS
  • Dimension 3 Color: PASS
  • Dimension 4 Typography: PASS
  • Dimension 5 Spacing: PASS
  • Dimension 6 Registry Safety: PASS

Approval: pending