Skip to content

Profile, Settings & Onboarding — reconciliation brief for Claude Designs

The prototype already has prototype/onboarding/Onboarding.dc.html, prototype/mobile-console/Profile.dc.html, and a desktop ui_kits/merchant-console-v2/profile.html. This brief exists because those screens were designed without the real profiles schema in front of them, and a codebase sweep (2026-07-19, for ADR-0006 / ADR-0001) found both missing fields and live bugs where the UI collects a value the backend silently drops.

How to use

Paste the fenced block below into Claude Designs with the PDPR and Screen Coverage Mandate. It uses the exact profiles column names — do not rename them. Field names here are the contract; the labels in quotes are the human-facing text.

Ground truth

Every field below is a real column on public.profiles (baseline 20260710134136_…:1328) or a real Edge-Function action (manage-profile, manage-settings, manage-account, validate-user-input). Do not invent fields, and do not add a business_name or display_name column — brand_name is the business name and full_name is the person's name (ADR-0001 D3).

Global rules for this module (apply the PDPR too)

markdown
# PROFILE, SETTINGS & ONBOARDING — RECONCILIATION BRIEF FOR CLAUDE DESIGNS

You are UPDATING three existing screens to match the real backend, not inventing a new module:
- prototype/onboarding/Onboarding.dc.html
- prototype/mobile-console/Profile.dc.html  (and desktop ui_kits/merchant-console-v2/profile.html / modules.jsx)
- the Settings surface (add one if the console lacks a dedicated Settings screen; it exists in the app today)

Use the EXACT field names below (they are real database columns). The quoted text is the human label.

=====================================================================
PART 0 — THE REAL FIELD SET (public.profiles) — use these names verbatim
=====================================================================

Identity / person:
- full_name (text) — label "Full Name" in onboarding, "Owner Name" in Profile. The individual/owner.
- email (text) — from auth; shown read-only in Profile header; changed only via Settings > Security.
- mobile_number (text, 10 digits) — a country_code selector may sit beside it in the UI, but note there is NO
  country_code column; if you keep the selector, treat it as display-only OR store it inside mobile_number.
- avatar_url / avatar_path (image) — uploaded via manage-profile action:'upload_avatar'.

Business / brand:
- brand_name (text) — label "Brand Name". THIS IS THE BUSINESS NAME. Do not add business_name.
- business_domain_id (integer → business_domains) — label "Business Industry". Options come from the
  business_domains table (id, name, slug, description). Selecting one also sets business_type to the domain slug.
- gstin (varchar 15, GSTIN-format CHECK) — label "GSTIN". India tax id, optional.
- country (varchar, NOT NULL, default 'India') · state (text) · city (text) · pin_code (text, 6 digits)
- business_hours (jsonb) — per-day { open, close, is_closed } for monday..sunday.
- social_media_links (jsonb) — keys: whatsapp, instagram, facebook, youtube, twitter, linkedin, telegram,
  google_business.
- planned_holidays_ooo (jsonb array) — items { title, startDate, endDate }.
- slug (varchar) — the public URL handle (qrsetu.com/<slug>), chosen at onboarding, validated for uniqueness.

Preferences / account (Settings):
- default_currency (text, default 'INR') — options INR/USD/EUR/GBP.
- language (varchar, CHECK en/mr/hi) — options English / मराठी / हिंदी.
- show_ads (boolean, default true) — whether ad placements show for this account.
- subscription_tier (read-only here; managed by billing) — show as a badge, link to plan/billing.

Do NOT surface in these screens (they are not user-editable identity): role, permissions, is_demo_account,
status, is_published, version, template_id, name (the generic public-page name), reminder_* fields,
tier_expires_at, attributes.

=====================================================================
PART 1 — ONBOARDING (update Onboarding.dc.html)
=====================================================================

QRSETU serves TWO audiences (locked product decision): businesses AND individuals. The current flow forces every
user to enter a brand name + industry, which is wrong for an individual. Add an account-type fork as Step 1.

Step 0/1 — "How will you use QRSETU?" : a two-choice selector — "For my business" or "For myself / personal".
This choice drives which later steps appear. (It maps to whether brand_name/business fields are collected; an
individual should never be forced to enter a brand_name.)

Then, in order:
1. "What should we call you?" — full_name (2+ chars, letters/spaces) + mobile_number (10 digits, with the
   country-code selector). BOTH audiences.
2. "Tell us about your brand" — brand_name (2+ chars). BUSINESS ONLY (skip for individuals).
3. "What's your industry?" — business_domain_id from business_domains. BUSINESS ONLY (skip for individuals).
4. "Where are you based?" — country (required), and optionally state / city / pin_code.
5. "Choose your unique URL" — slug (3–30 chars, ^[a-z0-9-]+$), auto-suggested from brand_name (business) or
   full_name (individual). Show live availability (there is a validate-user-input check for slug).
Finish — a celebratory completion screen; on finish, onboarding_completed becomes true.

Design the individual path as visibly shorter (Steps 2–3 removed), not the business path with fields greyed out.

=====================================================================
PART 2 — PROFILE (update Profile.dc.html + desktop)
=====================================================================

Keep the existing tabbed structure; make the fields match Part 0. For an INDIVIDUAL account, the Business Details
tab collapses to just location (no brand_name/industry/GSTIN/hours) — mirror the onboarding fork.

Tab "Basic Information" (editable): full_name (label "Owner Name" for business, "Your Name" for individual),
mobile_number. Header shows avatar, brand_name (business) or full_name (individual), the subscription_tier badge,
and email (read-only).

Tab "Business Details" (BUSINESS ONLY): brand_name, business_domain_id ("Business Industry"), gstin ("GSTIN"),
country, state, city, pin_code.

Tab "Business Hours" (BUSINESS ONLY): the business_hours per-day editor (open / close / is_closed per weekday),
plus the planned_holidays_ooo list (add/remove a holiday with title + date range).

Tab "Social Media" (BOTH): the eight social_media_links keys as labelled inputs (whatsapp, instagram, facebook,
youtube, twitter, linkedin, telegram, google_business).

Avatar upload with the standard image picker (crop optional), wired to the upload action.

=====================================================================
PART 3 — SETTINGS (create/align a Settings screen)
=====================================================================

Three sections, matching the app's real capabilities:

General: default_currency (INR/USD/EUR/GBP), language (English/मराठी/हिंदी), and a show_ads toggle
("Show partner offers and sponsored content"). These auto-save on change.

Security: change email, change password (current + new). Standard forms with validation states.

Danger Zone: delete account — a destructive, confirm-guarded action (soft-delete), with a plain-language
explanation of what happens to the user's public page and data.

=====================================================================
PART 4 — WHAT NOT TO INVENT (flag instead)
=====================================================================

1. Do not add a business_name or display_name field — brand_name and full_name already cover these.
2. Do not add a country_code column to the data model — it has none; keep the selector display-only or fold it
   into mobile_number, and flag the choice.
3. Do not add profile fields beyond Part 0 (no "bio", "website", "tagline", etc. unless told — they are not
   columns today). If a screen seems to need one, flag it as a proposed new column, do not silently design it.
4. Do not surface role / permissions / is_demo_account in the user Profile or Settings — those are
   platform/admin concerns (see ADR-0006), not user-editable identity.
5. The individual-vs-business fork is required, but the exact copy and where the choice is later changeable
   (Settings? not at all?) is open — design the fork and flag the "can they switch later?" question.

Why this shape

It reconciles the design to the schema that already exists rather than growing either side speculatively, and it encodes two locked decisions: the dual-audience fork (individuals aren't forced a business identity) and ADR-0001 D3 (business name = brand_name, member name = full_name, no new name column). The live data-loss bugs it exposes (slug / gstin / language / onboarding_completed silently dropped by Edge-Function allow-lists) are logged separately in the tracker — those are backend fixes (widen the allow-lists), not design fixes, and must land alongside this UI work or the new fields will look editable but won't persist.

After this ships in Claude Designs

Review the regenerated Onboarding / Profile / Settings screens the same way as every other screen: read the actual files, check field names against Part 0 and the fork against Parts 1–2, then log findings under design-system/screen-reviews/ and request revalidation.