Invite Flow Upgrade: Admin Direct Invite, Pre-Signup Questionnaire & Welcome
## Summary
Upgrade the invite flow to remove friction for admins, pre-fill invited user details, collect artistic profile data during signup, and deliver a personalized welcome experience on first login.
## Current vs. Planned
| | Current | Planned |
|---|---|---|
| Admin invite | 3 steps (request → approve → send email) | 1 step (enter email → done) |
| Email on signup | User types it manually | Pre-filled and locked from invite |
| Signup questions | None (email/username/password only) | + artistic practice, website, social link |
| First dashboard visit | Generic empty state | Personalized welcome banner |
---
## A. Admin Direct Invite
**New endpoint:** `POST /api/admin/invite`
Accepts `{ email, firstName? }`. In one step:
1. Validates caller is admin
2. Creates `invite_requests` row with `status: approved`, `source: admin_direct`, `invited_by: admin_user_id`
3. Generates invite code
4. Sends invite email with link `/auth/signup?invite=CODE`
The existing request → approve → send flow stays intact for organic signups.
**Database changes:**
```sql
ALTER TABLE invite_requests
ADD COLUMN invited_by UUID REFERENCES user_profiles(id),
ADD COLUMN source TEXT DEFAULT 'request';
-- Values: request, admin_direct, user_referral (future)
```
---
## B. Pre-filled Email on Signup
When an invited user clicks `/auth/signup?invite=CODE`, the email is pre-filled from the invite record.
**New RPC function:** `get_invite_by_code(code)` — returns the invite row including email.
**Signup page:** Fetches invite details server-side, passes `inviteEmail` to AuthForm. Email field rendered as read-only: "Invited as maria@example.com".
**Security:** On submit, verify signup email matches the invite record email.
---
## C. Pre-Signup Questionnaire
Two-step signup flow. Step 1: credentials (email, username, password → Continue). Step 2: three questions (→ Create Account).
### Question 1: Artistic Practice (required, multi-select chips)
| | | | |
|---|---|---|---|
| Photography | Illustration | Painting | Graphic Design |
| Architecture | Fashion | Film & Video | Sculpture |
| Digital Art | Mixed Media | Typography | Animation |
| Music | Writing | Crafts | Other |
Selecting "Other" shows a freetext input.
### Question 2: Website Link (optional)
Text input. Placeholder: `https://your-portfolio.com`
### Question 3: Social Link (optional)
Text input. Placeholder: `https://instagram.com/yourusername`
Platform auto-detected from URL (instagram.com → instagram field, twitter.com → twitter field, etc.)
### Data Flow
Questionnaire answers stored in `user_metadata` during the `signUp()` call. After email verification, the auth callback syncs metadata to `user_profiles`:
- `artistic_practice` → new `TEXT[]` column
- website → existing `website` column
- social link → parsed to appropriate social column
**Database changes:**
```sql
ALTER TABLE user_profiles
ADD COLUMN artistic_practice TEXT[];
```
---
## D. Post-Signup Welcome
After email verification, redirect to `/{username}/dashboard?welcome=true`.
**New component:** `WelcomeBanner` — shows above the empty dashboard bento grid:
- "Welcome to Salon.io, Maria!"
- If artistic practice known: "We're thrilled to have a fellow photographer on board."
- Dismiss button removes the `?welcome=true` param
---
## E. Terms of Service Acceptance
Currently there is no ToS acceptance anywhere in the signup flow. This must be added before public launch (March 13).
### Placement
The ToS checkbox goes on Step 2 (questionnaire), right above the "Create Account" button:
```
Step 2: About You
┌─────────────────────────────────────┐
│ What do you create? [chips...] │
│ Website link [________] │
│ Social link [________] │
│ │
│ ☐ I agree to the Terms of Service │
│ and Privacy Policy │
│ │
│ [Create Account] │
└─────────────────────────────────────┘
```
- Checkbox is **unchecked by default** (GDPR requirement — no pre-checked consent)
- "Create Account" button disabled until checkbox is checked
- "Terms of Service" and "Privacy Policy" are links to `/terms` and `/privacy`
- Not a pre-checked box — must be an affirmative action by the user
### What Gets Stored
On signup, the acceptance timestamp is included in `user_metadata`:
```typescript
options: {
data: {
username,
artistic_practice: [...],
tos_accepted_at: new Date().toISOString(), // ISO 8601
tos_version: "2026-03-13", // Version of ToS accepted
}
}
```
After email verification, synced to `user_profiles`:
```sql
ALTER TABLE user_profiles
ADD COLUMN tos_accepted_at TIMESTAMPTZ,
ADD COLUMN tos_version TEXT;
```
### Why This Moment
The ToS acceptance happens before account creation — before the user receives any value (the 100 SLN signup bonus from the SLN Ledger spec is credited on email confirmation, which comes after). This sequence ensures:
1. User agrees to terms (Step 2, checkbox)
2. Account is created (Supabase signUp)
3. User verifies email (confirmation link)
4. SLN bonus credited (+100 SLN)
5. User lands on dashboard (welcome banner)
Legal consent is captured before any credits, subscriptions, or platform features are accessible.
### Legal Requirements (EU/GDPR)
| Requirement | How we meet it |
|---|---|
| Affirmative consent | Unchecked checkbox, user must click |
| Informed consent | Links to full ToS and Privacy Policy |
| Proof of consent | `tos_accepted_at` timestamp + `tos_version` stored |
| Version tracking | `tos_version` field tracks which version was accepted |
| Re-consent on changes | When ToS version changes, prompt existing users to re-accept |
---
## New Files
| File | Purpose |
|---|---|
| `app/api/admin/invite/route.ts` | Admin direct invite endpoint |
| `src/components/SignupQuestionnaire.tsx` | Questionnaire UI (chips + inputs) |
| `src/components/dashboard/WelcomeBanner.tsx` | Personalized welcome banner |
| `src/config/artistic-practices.ts` | Category list constant |
| `src/utils/social-link-parser.ts` | Detect platform from URL |
| `supabase/migrations/YYYYMMDD_invite_flow_upgrade.sql` | Schema + RPC changes |
## Modified Files
| File | Change |
|---|---|
| `src/components/AuthForm.tsx` | Two-step flow, `inviteEmail` prop, questionnaire integration |
| `app/auth/signup/page.tsx` | Server-side invite lookup, pass email |
| `app/auth/callback/page.tsx` | Sync metadata to profile, `?welcome=true` redirect |
| `src/hooks/use-auth.ts` | Extend `signUp()` with questionnaire metadata |
| `src/components/dashboard/EmptyDashboard.tsx` | Integrate WelcomeBanner |
---
## Implementation Sequence
1. Database migration (columns + RPC)
2. Config and utilities
3. Admin invite API
4. Signup page (server-side invite lookup)
5. AuthForm two-step flow + SignupQuestionnaire
6. use-auth hook extension
7. Auth callback (profile sync + welcome redirect)
8. WelcomeBanner component
9. Email template updates
*Full spec: `new-salon-app/docs/ongoing/INVITE-FLOW-UPGRADE.md`*
- Status
- Closed
- Priority
- high
- Type
- feature
- Created
- Mar 1, 2026