---
phase: 31-puter.js-zero-config-cloud
plan: "03"
type: execute
wave: 2
depends_on: ["31-01", "31-02"]
files_modified:
- ui/src/components/onboarding/ProviderSelectionStep.tsx
- ui/src/components/onboarding/PuterAuthButton.tsx
- ui/src/components/onboarding/GoogleOAuthButton.tsx
- ui/src/components/onboarding/ApiKeyEntryForm.tsx
- ui/src/components/NexusOnboardingWizard.tsx
- ui/src/api/puter-proxy.ts
autonomous: true
requirements: [CLOUD-01, CLOUD-03, CLOUD-04, CLOUD-05]
must_haves:
truths:
- "User sees a Provider Selection step (Step 3 of 4) in the onboarding wizard with Puter, Google, and API Key options"
- "Clicking 'Continue with Puter' triggers Puter auth popup, stores token server-side, and advances wizard"
- "Google option shows policy-risk warning before enabling the Sign in button (3-second gate)"
- "API key option shows inline form with provider dropdown and key input"
- "Skip for now button is always visible and advances to root directory step"
- "Pre-installed tools (Hermes, Claude Code, OpenClaw) show detected badges via adapter probe"
- "Step indicator shows 'Step N of 4' (updated from 3)"
artifacts:
- path: "ui/src/components/onboarding/ProviderSelectionStep.tsx"
provides: "Provider selection UI with three option cards and skip button"
exports: ["ProviderSelectionStep"]
- path: "ui/src/components/onboarding/PuterAuthButton.tsx"
provides: "Puter auth button that loads CDN script, calls signIn, posts token to server"
exports: ["PuterAuthButton"]
- path: "ui/src/components/onboarding/GoogleOAuthButton.tsx"
provides: "Google OAuth button with 3-second risk warning gate"
exports: ["GoogleOAuthButton"]
- path: "ui/src/components/onboarding/ApiKeyEntryForm.tsx"
provides: "API key entry form with provider dropdown"
exports: ["ApiKeyEntryForm"]
- path: "ui/src/api/puter-proxy.ts"
provides: "API client for puter-proxy and oauth endpoints"
exports: ["puterProxyApi"]
- path: "ui/src/components/NexusOnboardingWizard.tsx"
provides: "4-step wizard with provider selection step inserted"
key_links:
- from: "ui/src/components/onboarding/PuterAuthButton.tsx"
to: "POST /api/puter-proxy/token"
via: "fetch call to store Puter token server-side"
pattern: "puter-proxy/token"
- from: "ui/src/components/onboarding/GoogleOAuthButton.tsx"
to: "POST /api/oauth/google/authorize"
via: "fetch call to get auth URL, then window.open"
pattern: "oauth/google/authorize"
- from: "ui/src/components/onboarding/ApiKeyEntryForm.tsx"
to: "POST /api/api-keys/store"
via: "fetch call to store API key"
pattern: "api-keys/store"
- from: "ui/src/components/NexusOnboardingWizard.tsx"
to: "ui/src/components/onboarding/ProviderSelectionStep.tsx"
via: "import and render in step 3"
pattern: "ProviderSelectionStep"
---
Build the Provider Selection step UI components and wire them into the existing 3-step onboarding wizard (making it 4 steps). This includes the Puter auth button, Google OAuth button with risk warning, API key entry form, and adapter auto-detection badges.
Purpose: CLOUD-01 (Puter zero-config UI), CLOUD-03 (Google OAuth UI), CLOUD-04 (auto-detect tools), CLOUD-05 (API key entry UI). This is the user-facing surface for all cloud provider paths.
Output: ProviderSelectionStep, PuterAuthButton, GoogleOAuthButton, ApiKeyEntryForm, updated wizard
@/home/mikkel/.claude/get-shit-done/workflows/execute-plan.md
@/home/mikkel/.claude/get-shit-done/templates/summary.md
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/31-puter.js-zero-config-cloud/31-RESEARCH.md
@.planning/phases/31-puter.js-zero-config-cloud/31-UI-SPEC.md
@.planning/phases/30-hardware-detection-mode-selection/30-02-SUMMARY.md
From ui/src/components/NexusOnboardingWizard.tsx (current state):
```typescript
// 3-step wizard: step 1 = hardware, step 2 = mode, step 3 = root directory
// Step indicator: "Step {step} of 3"
// defaultAdapter state: "claude_local" | "hermes_local"
// probing state for adapter detection
// handleSubmit creates company + agents on step 3 form submit
```
From ui/src/components/onboarding/ModeSelector.tsx (selected state pattern):
```typescript
// Cards use: border-primary bg-primary/5 when selected
// Vertical stack with gap-3
// Each card is a
Task 1: API client + PuterAuthButton + GoogleOAuthButton + ApiKeyEntryForm
ui/src/api/puter-proxy.ts,
ui/src/components/onboarding/PuterAuthButton.tsx,
ui/src/components/onboarding/GoogleOAuthButton.tsx,
ui/src/components/onboarding/ApiKeyEntryForm.tsx
ui/src/api/agents.ts,
ui/src/api/client.ts,
ui/src/components/onboarding/ModeSelector.tsx,
ui/src/components/NexusOnboardingWizard.tsx,
.planning/phases/31-puter.js-zero-config-cloud/31-UI-SPEC.md
**Create ui/src/api/puter-proxy.ts:**
Import `api` from `./client`. Export `puterProxyApi` with:
- `storeToken: (companyId: string, token: string) => api.post("/puter-proxy/token", { companyId, token })`
- `getAuthUrl: (companyId: string) => api.post<{ url: string }>("/oauth/google/authorize", { companyId })`
- `storeApiKey: (companyId: string, provider: string, apiKey: string) => api.post("/api-keys/store", { companyId, provider, apiKey })`
**Create ui/src/components/onboarding/PuterAuthButton.tsx:**
Props: `{ companyId?: string; onSuccess: () => void; onError: (msg: string) => void }`.
State: `loading` boolean.
`loadScript` helper: check if `window.puter` exists; if not, create a `