---
phase: 31-puter.js-zero-config-cloud
plan: "03"
subsystem: ui
tags: [react, puter, google-oauth, api-key, onboarding, shadcn, lucide-react]

# Dependency graph
requires:
  - phase: 31-puter.js-zero-config-cloud/31-01
    provides: puterProxyService and routes (POST /api/puter-proxy/token, /api/puter-proxy/chat)
  - phase: 31-puter.js-zero-config-cloud/31-02
    provides: Google OAuth PKCE routes (authorize, callback, claim) and api-keys/store endpoint
  - phase: 30-hardware-detection-mode-selection/30-02
    provides: NexusOnboardingWizard 3-step structure and ModeSelector card pattern
provides:
  - ProviderSelectionStep component (Step 3 of 4) with Puter/Google/API key cards
  - PuterAuthButton: loads Puter CDN, triggers signIn popup, captures token in React state
  - GoogleOAuthButton: 3-second risk warning gate, opens OAuth popup, captures stateId
  - ApiKeyEntryForm: provider dropdown (OpenAI/Anthropic/Groq) + password input
  - puterProxyApi client: storeToken, getAuthUrl, claimGoogleTokens, storeApiKey
  - NexusOnboardingWizard updated to 4-step flow with credential storage after company creation
affects: [31-04, 33-personal-ai-assistant, future-onboarding-phases]

# Tech tracking
tech-stack:
  added: []
  patterns:
    - "Provider card interaction: <button type=button> with border-primary bg-primary/5 on selection, matches ModeSelector"
    - "Credential capture: React state stores token/stateId/apiKey during wizard; posted server-side after company creation"
    - "CDN script injection: loadScript() helper creates <script> tag on demand (Puter SDK only loaded on click)"
    - "Google risk gate: 3-second setTimeout before enabling Sign in button (anti-accidental-click UX pattern)"
    - "Non-blocking credential storage: all provider API calls wrapped in .catch(() => {}) post company creation"

key-files:
  created:
    - 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/components/onboarding/ProviderSelectionStep.tsx
  modified:
    - ui/src/components/NexusOnboardingWizard.tsx

key-decisions:
  - "Heading 'Choose a provider' in wizard wrapper, not ProviderSelectionStep — matches existing pattern where step wrapper owns heading"
  - "Adapter badges on Puter card only (hermes/claude/openclaw are local adapters, not Google/API key alternatives)"
  - "Pre-existing AgentConfigForm.tsx TS error (detectModel) left as out-of-scope — pre-dated this plan"

patterns-established:
  - "Provider auth pattern: capture credentials in React state during wizard, POST to server only after company creation"
  - "Risk warning timing gate: useEffect + setTimeout(fn, 3000) for anti-accidental-click on destructive/risky actions"

requirements-completed: [CLOUD-01, CLOUD-03, CLOUD-04, CLOUD-05]

# Metrics
duration: 5min
completed: 2026-04-03
---

# Phase 31 Plan 03: Provider Selection UI Summary

**4-step onboarding wizard with Puter/Google/API-key provider cards, adapter auto-detection badges, and post-company-creation credential storage**

## Performance

- **Duration:** ~5 min
- **Started:** 2026-04-03T00:38:48Z
- **Completed:** 2026-04-03T00:43:18Z
- **Tasks:** 2
- **Files modified:** 6

## Accomplishments

- Created `puterProxyApi` client covering all 4 server endpoints (puter-proxy/token, oauth/google/authorize, oauth/google/claim, api-keys/store)
- Built `PuterAuthButton` with dynamic Puter CDN loading, popup sign-in, and multi-path token extraction
- Built `GoogleOAuthButton` with always-visible policy-risk callout and 3-second gate before enabling sign-in
- Built `ApiKeyEntryForm` with OpenAI/Anthropic/Groq dropdown and password input
- Built `ProviderSelectionStep` with three option cards matching ModeSelector visual pattern, adapter detection badges, and skip button
- Extended `NexusOnboardingWizard` from 3 to 4 steps; parallel adapter probes for hermes/claude/openclaw; credentials stored after company creation

## Task Commits

1. **Task 1: API client + PuterAuthButton + GoogleOAuthButton + ApiKeyEntryForm** - `3796de84` (feat)
2. **Task 2: ProviderSelectionStep + wire 4-step wizard** - `cdea714d` (feat)

## Files Created/Modified

- `ui/src/api/puter-proxy.ts` — API client: storeToken, getAuthUrl, claimGoogleTokens, storeApiKey
- `ui/src/components/onboarding/PuterAuthButton.tsx` — Loads Puter CDN, triggers signIn popup, captures token
- `ui/src/components/onboarding/GoogleOAuthButton.tsx` — 3-second risk warning gate, opens OAuth popup, captures stateId
- `ui/src/components/onboarding/ApiKeyEntryForm.tsx` — Provider dropdown (OpenAI/Anthropic/Groq) + password input
- `ui/src/components/onboarding/ProviderSelectionStep.tsx` — Three provider cards with adapter badges and skip button
- `ui/src/components/NexusOnboardingWizard.tsx` — 4-step wizard: added Step 3 (provider selection), credential storage in handleSubmit

## Decisions Made

- Heading "Choose a provider" lives in wizard wrapper (step 3 block), not inside ProviderSelectionStep — consistent with how ModeSelector heading lives in the wizard wrapper
- Adapter badges (Hermes/Claude Code/OpenClaw detected) shown on the Puter card since these are the pre-installed local adapters that are Puter-compatible; Google and API key cards don't show badges
- Pre-existing TypeScript error in `AgentConfigForm.tsx` (`detectModel` missing from agentsApi) is out of scope — it existed before this plan. Logged to deferred items.

## Deviations from Plan

None - plan executed exactly as written.

## Issues Encountered

- Pre-existing TypeScript compilation error in `AgentConfigForm.tsx(351)`: `Property 'detectModel' does not exist on type...` — this error existed before this plan. My new files compile cleanly (only one TS error in the build, and it's in an unrelated file). Logged for deferred fix.

## Known Stubs

None. All provider auth components pass real tokens/stateIds to the wizard which stores them post-company-creation. No hardcoded empty values or placeholder data flows to UI rendering.

## User Setup Required

None - no external service configuration required for the UI components. Server-side OAuth/proxy routes were established in plans 31-01 and 31-02.

## Next Phase Readiness

- Provider Selection step UI is complete; Step 3 of 4 is fully functional
- Puter token → stored via `POST /api/puter-proxy/token` after company creation
- Google stateId → claimed via `POST /api/oauth/google/claim` after company creation
- API keys → stored via `POST /api/api-keys/store` after company creation
- Ready for plan 31-04 (final integration / summary screen)

---
*Phase: 31-puter.js-zero-config-cloud*
*Completed: 2026-04-03*
