Overview
Members can change their nickname from Account settings using the same confirm-by-email pattern as email changes. The nickname does not update until they click a 24-hour link sent to their current address. After a change is applied, they must wait 60 days before changing again. Old /@nickname URLs (including albums and photos) 301 to the new nickname for one year via nickname_redirects and proxy middleware.
Database
Migration 20260312000006_nickname_change_support.sql:
profiles.nickname_changed_at— set by trigger when a nickname is changed (not on first onboarding set).nickname_redirects— mapsold_nickname→profile_idwithexpires_atone year out.auth_tokens.new_nickname+nickname_changetoken type for pending confirmations.handle_profile_nickname_changetrigger enforces cooldown, writes redirects, and allows reclaiming your own old name.resolve_nickname_redirect(p_nickname)— used by proxy for 301s.is_nickname_available(p_nickname, p_user_id)— checks profiles, active redirects, and pending tokens.
API & verification
- POST
/api/account/change-nickname— validates nickname, cooldown, availability; stores token; emails confirmation. - GET
/auth/verify-nickname-change— applies nickname via admin client (trigger runs); revalidates old and new profile caches; redirects to/account?nickname_changed=true.
UI
ChangeNicknameModal— mirrorsChangeEmailModal(Send confirmation → Check your inbox).ProfileSection— disabled nickname field + Change button; cooldown messaging.useAccountForm— handlesnickname_changedquery param and exposes cooldown end date.
Routing
src/lib/nicknameRedirect.ts + proxy.ts:
/@old/...→/@current/...(301) when an unexpired redirect exists.- Bare
/old/...falls through to redirect table if not a live profile nickname.
All Modified Files
New:
supabase/migrations/20260312000006_nickname_change_support.sqlsrc/app/api/account/change-nickname/route.tssrc/app/auth/verify-nickname-change/route.tssrc/components/account/ChangeNicknameModal.tsxsrc/emails/auth/change-nickname.tsxsrc/lib/nicknameRedirect.tssrc/utils/nickname.tssrc/utils/nickname.test.ts
Modified:
src/app/account/page.tsxsrc/app/api/cron/cleanup-deleted-content/route.tssrc/app/email/[template]/page.tsxsrc/app/onboarding/OnboardingClient.tsxsrc/components/account/ProfileSection.tsxsrc/content/help/account.tsxsrc/content/help/getting-started.tsxsrc/database.types.tssrc/hooks/useAccountForm.tssrc/proxy.ts