Skip to content

feat(signup): post-signup welcome wizard + auto-login (PRD §4) - #8

Merged
hades217 merged 1 commit into
mainfrom
feat/signup-wizard
May 16, 2026
Merged

feat(signup): post-signup welcome wizard + auto-login (PRD §4)#8
hades217 merged 1 commit into
mainfrom
feat/signup-wizard

Conversation

@hades217

Copy link
Copy Markdown

Summary

实现 `docs/tasks/onboarding-prd.md` 里的注册 wizard,不动现有 431 行 sign-up 表单(turnstile / WeChat / OAuth / 邮箱验证一大堆集成不动)。

混合架构

  • Step 1 = 现有 /sign-up 表单(一字不改)
  • 后端 Register 现在自动 set session cookie + 返回 default_token / trial_quota / next 路由
  • /welcome 新路由:Welcome banner(试用额度 + 默认 Key)+ 内联 3 步选择(persona / brand / client)+ Continue → PUT /api/user/setting + 跳目标

关键点

Backend (`controller/user.go`):

  • 新 RegisterRequest DTO(9 个字段全部可选)
  • Register 处理器重构:build dto.UserSetting,OnboardingCompletedAt 只在用户选了 persona AND client 时打 timestamp
  • 默认 Key(upstream 已经在创建)现在绑 SimpleBrand from wizard → "deeprouter" 虚拟 model 第一天就路由对
  • 自动 sign-in:同 Login 一样 session.Set + Save,砍掉 /sign-in 二次登录
  • 响应里包含 default_token(一次性显示)+ trial_quota + next 路由提示

Setting JSON (`dto/user_settings.go`):

  • 9 个新 string/bool 字段,全部在已有 setting JSON 列,零 migration
  • TS 镜像同步更新

Frontend:

  • 新 `features/welcome/` + `/welcome` 路由
  • auth/lib/storage 新增 setWelcomeHandoff/takeWelcomeHandoff(sessionStorage 一次性)+ captureAcquisitionMeta/readAcquisitionMeta(UTM + referrer 快照)
  • sign-up 表单:`redirectToLogin()` → `navigate({to: '/welcome'})` 一行替换;mount 时静默捕获 acquisition meta;register payload 加 acquisition_channel + timezone

兼容性

文件

Backend:

  • `controller/user.go` — RegisterRequest + Register 重构 + 自动 sign-in
  • `dto/user_settings.go` — +9 个字段

Frontend 新增:

  • `features/welcome/index.tsx` — Welcome banner + 3 步 inline wizard
  • `routes/welcome.tsx` — TanStack Router 路由

Frontend 修改:

  • `features/auth/sign-up/components/sign-up-form.tsx` — 跳 /welcome + 捕获 acquisition
  • `features/auth/lib/storage.ts` — 4 个新 helper
  • `features/auth/types.ts` — RegisterPayload + RegisterResponseData
  • `features/profile/types.ts` — UserSettings 镜像
  • `i18n/locales/{en,zh}.json` — 31 keys

Test plan

  • `bun run typecheck` 通过
  • `bunx eslint` 通过
  • 注册新账号 → 不再跳 /sign-in → 直接跳 /welcome
  • /welcome 展示 default token(仅一次)+ "≈ 200 次免费试聊" 副标题
  • 选 persona = Casual → 推荐 client 自动选 Cherry Studio
  • 选完点 Continue → 跳 /onboarding/cherry-studio
  • 点 "Skip — set this later" → 跳 /dashboard,persona = dev
  • 关浏览器刷新 /welcome:因为 sessionStorage 已被读取,handoff 为空 → 跳 dashboard
  • OAuth 登录路径不受影响(仍走原 callback)
  • 老账号登录:不走 /welcome,体验完全一样

🤖 Generated with Claude Code

Implements the onboarding wizard described in docs/tasks/onboarding-prd.md
without rewriting the existing /sign-up form (which is 431 lines of
turnstile / WeChat / OAuth / email verification integrations we don't
want to risk breaking).

Architecture (hybrid):
- Step 1 = existing /sign-up form, untouched
- Backend Register handler now auto-creates the session (set cookie)
  and returns the one-time default token + trial quota + suggested
  landing route
- Signup form navigates to new /welcome route with the response stashed
  in sessionStorage
- /welcome renders Welcome banner (trial credit + default token) +
  Step 2/3/4 inline (persona / brand / client) + Continue → calls
  /api/user/setting and lands on the chosen route

Backend (controller/user.go):
- New RegisterRequest DTO with Persona/BrandPreference/PreferredClient/
  AcquisitionChannel/Timezone fields (all optional, all in setting JSON)
- Register handler refactored: builds dto.UserSetting from request,
  stamps OnboardingCompletedAt only if user picked persona AND client
- Default token (already auto-created) now binds SimpleBrand from the
  wizard so "deeprouter" virtual model resolves to the right provider
  from day 1
- Auto sign-in: same session.Set/Save calls as Login. Skips the
  /sign-in detour entirely.
- Response includes default_token (one-time reveal) + trial_quota +
  next route hint based on preferred_client

Shared types (dto/user_settings.go):
- 9 new optional fields on UserSetting JSON. Zero schema migration
  (all in existing `setting` column). Frontend types mirror.

Frontend:
- New features/welcome/ feature + /welcome route (TanStack Router)
- New auth/lib/storage helpers: setWelcomeHandoff / takeWelcomeHandoff
  (sessionStorage one-shot for register response) + captureAcquisition
  Meta / readAcquisitionMeta (utm + referrer snapshot)
- Sign-up form: replaces redirectToLogin() with navigate({to: '/welcome'})
  after register. Acquisition meta captured on mount, included in
  register payload.

Compatibility:
- Wizard fully skippable: "Skip — set this later" link → setting saved
  with persona='dev' (legacy default), lands on /dashboard
- Skipping any single step keeps persona='unset' / brand='' / client=''
  → dashboard picker (PR #3) fallback still triggers as designed
- /welcome accessed directly (no handoff): redirect to /sign-in or
  /dashboard depending on session state
- All existing OAuth / WeChat / email-verification flows untouched

i18n: 31 new en + zh keys.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant