feat(profile): industry / usage / marketing opt-in (Phase 3) - #14
Merged
Conversation
Adds the three "About you" fields the onboarding PRD §3 carved out:
- Industry (education / finance / ecommerce / gaming / individual /
saas / other, plus "prefer not to say")
- Expected usage (just trying / under 1k daily / 1k-100k daily /
over 100k daily, plus "prefer not to say")
- Marketing emails opt-in (explicit checkbox, defaults to off)
These were intentionally left out of the registration wizard to keep
signup ≤ 3 steps; they live on /profile under "About you (optional)"
where the user can fill them in later — used internally to prioritize
model/channel/docs work for whoever shows up, never for billing or
access. Hence the "prefer not to say" value on each enum + the
marketing-emails default of false (CAN-SPAM / GDPR style explicit
opt-in regardless of whether we ship the email pipeline).
Implementation:
- controller/user.go: extend the partial-PATCH UpdateUserSetting
handler with three new pointer fields (Industry, ExpectedVolume,
MarketingEmails). Same pattern as Persona/BrandPreference/etc
from PR #12 — pointers so a caller can leave any field untouched.
- web/default/src/features/profile/components/profile-extension-card.tsx:
new TitledCard with two Selects + one Checkbox. Each control
saves on change via the partial-PATCH endpoint and shows a
Loader2 spinner during the round trip.
- web/default/src/features/profile/index.tsx: mount under
OnboardingPreferencesCard so both onboarding-derived cards sit
together.
- web/default/src/features/profile/types.ts: extend
UpdateUserSettingsRequest TS type to match.
Verified end-to-end with the now-rebuilt backend:
POST /api/user/register → user with persona=casual
PUT /api/user/setting → {industry:"saas"}
PUT /api/user/setting → {expected_volume:"daily-medium",
marketing_emails:true}
DB row: persona=casual, industry=saas, expected_volume=daily-medium,
marketing_emails=true, sidebar_modules unchanged
Notes on the other Phase 3/4 items deliberately not done here:
- Event instrumentation (Sentry / first-party analytics) — needs
a vendor decision and a privacy stance; not a code-only change.
- A/B testing infra — needs a flag/cohort system; same caveat.
- 7d/30d retention emails and first-topup nudges — depend on an
email pipeline we don't have wired yet. The frontend banner
landed in PR #13 covers the immediate "trial credit low" hint.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the three "About you" fields the onboarding PRD §3 carved out:
These were intentionally not in the registration wizard — that stays ≤ 3 steps. They live on /profile under "About you (optional)" so the user can fill them in later. Used internally to prioritize model/channel/docs work; never for billing or access. Hence the "prefer not to say" value on each enum.
Implementation
controller/user.go: extend partial-PATCHUpdateUserSettingwithIndustry/ExpectedVolume/MarketingEmailspointer fields. Same pattern as Persona/BrandPreference from PR fix(onboarding): hydrate authStore on signup + cover OAuth InsertWithTx #12.web/default/.../profile-extension-card.tsx(new): TitledCard with two Selects + one Checkbox. Save-on-change via partial-PATCH endpoint, Loader2 spinner per row during the round trip.web/default/.../profile/index.tsx: mount card underOnboardingPreferencesCard.web/default/.../profile/types.ts: extendUpdateUserSettingsRequestTS type.End-to-end verified
POST /api/user/register → user persona=casual PUT /api/user/setting {industry:"saas"} PUT /api/user/setting {expected_volume:"daily-medium", marketing_emails:true} # DB: persona=casual, industry=saas, expected_volume=daily-medium, # marketing_emails=true, sidebar_modules unchangedWhat I deliberately did NOT do here
🤖 Generated with Claude Code