ClosedFeaturehigh

Invite Flow Upgrade: Admin Direct Invite, Pre-Signup Questionnaire & Welcome

#30Opened by SALMar 1, 2026, 4:51 PM
S
SAL
23 days ago

## 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`*

Sign in to comment on this issue.

1
vote
Status
Closed
Priority
high
Type
feature
Created
Mar 1, 2026