1. Role-Based Access Control (RBAC)
Three Roles
Default role on registration.
- ✓ Book appointments
- ✓ View own bookings
- ✓ Subscribe to memberships
- ✓ Process payments
- ✓ Leave reviews (via survey)
- ✗ Cannot view other users' data
- ✗ Cannot access admin or artist panels
Assigned by admin. Has artistId in JWT.
- ✓ View assigned bookings
- ✓ View earnings/stats
- ✓ Manage own artist page
- ✓ Create membership plans
- ✓ Connect Square for payments
- ✓ Request instant transfers
- ✗ Cannot see other artists' data
Full platform access.
- ✓ View all bookings
- ✓ View all stats & revenue
- ✓ Manage service area waitlist
- ✓ Refresh Square tokens
- ✓ Access all artist/customer data
- ✓ Override role restrictions
Middleware Route Guard Matrix
Enforced by proxy.ts middleware. JWT verified on every request, user info injected into headers.
| Route Pattern | Customer | Artist | Admin | Guest |
|---|---|---|---|---|
| / | ✓ | ✓ | ✓ | ✓ |
| /book | ✓ | ✓ | ✓ | ✓ |
| /memberships | ✓ | ✓ | ✓ | ✓ |
| /artist/[slug] | ✓ | ✓ | ✓ | ✓ |
| /login, /register | ↩ | ↩ | ↩ | ✓ |
| /dashboard | ✓ | ✓ | ✓ | 🔒 |
| /artist | 🚫 | ✓ | ✓ | 🔒 |
| /admin | 🚫 | 🚫 | ✓ | 🔒 |
2. Authentication Flow
Architecture
Technology
- Token: JWT (HS256) via
jose - Expiry: 7 days
- Storage: HttpOnly cookie (
auth-token) - Hashing: bcrypt, 12 salt rounds
- Validation: Zod schemas in
lib/validations/
JWT Payload
{
sub: "user-uuid",
email: "user@example.com",
role: "customer|artist|admin",
firstName: "Jane",
lastName: "Doe",
artistId?: "artist-uuid",
iat: 1709942400,
exp: 1710547200
}Login Flow
- User submits email + password on
/login POST /api/auth/loginvalidates via Zod, queries DB- Password verified with bcrypt
- JWT created with role, user ID, and optional
artistId - Token set as HttpOnly cookie (7-day expiry)
- Client redirects based on role:
- Customer →
/dashboard - Artist →
/artist - Admin →
/admin
- Customer →
Registration Flow
- User fills first name, last name, email, password, phone on
/register POST /api/auth/registervalidates, checks email uniqueness- Password hashed with bcrypt (12 rounds)
- User record created with default role
customer - JWT created, cookie set → redirect to
/dashboard
3. Membership System
Platform Membership Tiers
| Tier | Price | Tans/Month | Discount | Priority |
|---|---|---|---|---|
| Bronze Glow | $65 | 1 | 10% | ✓ |
| Gold Glow ⭐ | $120 | 2 | 15% | ✓ |
| Platinum Glow | $175 | Unlimited | 20% | ✓ |
Artist-Created Membership Plans
Artists can create their own membership plans for their clients. Plans are stored in artist_membership_plans and managed via the artist portal.
Plan Properties
- • Name & description
- • Monthly price
- • Tans included per period
- • Add-on discount percentage
- • Priority booking flag
- • Active/inactive toggle
Subscription Flow
- Customer selects plan on artist page
- Enters payment via Square Web SDK
- Square customer + card-on-file created
- First month charged with platform fee
- Membership record created in DB
- Usage tracked per billing period
Payment Architecture (Square)
Split-payment model: Each payment is split between platform fee and artist earnings via Square's appFeeMoney.
Booking Payment
Customer pays → platform fee deducted → artist receives remainder
Membership Payment
Monthly charge to card-on-file → platform fee → artist credited
Instant Transfer
Artist requests payout → 1.5% transfer fee → funds sent to bank
4. Sitemap & Page Index
Public Pages (No Auth)
/Home / Landing Page
Hero, services, spray parties, service area banner, footer
/bookBooking Wizard (6-step)
Address → services → date/time → survey → phone → review
/book/confirmationBooking Confirmation
Confirmation number, prep instructions, booking summary
/membershipsMembership Plans
3-tier pricing cards (Bronze/Gold/Platinum), FAQ
/artist/[slug]Artist Public Profile
Bio, gallery, reviews, plans, services, book CTA
/loginLogin
Email + password form, role-based redirect
/registerRegister
5-field form, auto-login on success
Customer Portal (Auth Required)
/dashboardCustomer Dashboard
Upcoming/past bookings, membership card, quick-book CTA
Artist Portal (Artist/Admin Only)
/artistArtist Dashboard
Today's schedule, upcoming bookings, earnings stats, confirm/decline
Admin Panel (Admin Only)
/adminAdmin Dashboard
Stats grid, recent bookings, waitlist requests, add artist
5. API Route Reference
| Endpoint | Method | Auth | Purpose |
|---|---|---|---|
| Auth | |||
| /api/auth/register | POST | Public | Create new customer account |
| /api/auth/login | POST | Public | Login, set JWT cookie |
| /api/auth/logout | POST | Any | Clear auth cookie |
| /api/auth/me | GET | Any | Get current user from JWT |
| Bookings | |||
| /api/bookings | GET | Customer | List user's bookings |
| /api/bookings | POST | Customer | Create new booking |
| /api/availability | GET | Public | Check artist time slots |
| Memberships | |||
| /api/memberships/my | GET | Customer | User's active memberships + usage |
| /api/memberships/subscribe | POST | Customer | Subscribe to artist plan via Square |
| Payments | |||
| /api/payments/process | POST | Customer | Process booking payment via Square |
| /api/payments/instant-transfer | GET/POST | Artist | View balance / request instant payout |
| Artist | |||
| /api/artist/bookings | GET | Artist | Today + upcoming bookings |
| /api/artist/stats | GET | Artist | Earnings & performance stats |
| /api/artists/[id]/page | PUT | Artist | Update artist public page |
| /api/artists/[id]/membership-plans | GET/POST | Public/Artist | List / create membership plans |
| /api/artists/by-slug/[slug] | GET | Public | Public artist page data |
| Admin | |||
| /api/admin/stats | GET | Admin | Platform-wide statistics |
| /api/admin/bookings | GET | Admin | All bookings (paginated) |
| /api/admin/waitlist | GET | Admin | Service area waitlist requests |
| Infrastructure | |||
| /api/ably/token | POST | Any user | Generate Ably real-time token |
| /api/geocode/reverse | GET | Public | Lat/lng → city/state |
| /api/service-area/check | GET | Public | Check if location is served |
| /api/service-area/waitlist | POST | Public | Join coverage waitlist |
| /api/square/oauth/* | GET | Artist | Square OAuth connect flow |
| /api/webhooks/square | POST | Webhook | Square payment/subscription events |
6. Forms & User Flows
Booking Flow (6-Step Wizard)
Step 1: Address
Google Places autocomplete → lat/lng → service area check → nearest artist assignment → travel fee calculation
Step 2: Services
Select from: Signature Glow ($75), Rapid Glow ($50), Bridal Glow ($150), Competition Glow ($200). Multi-quantity with group discount.
Step 3: Date & Time
Calendar date picker → fetch artist availability → morning/afternoon/evening slot selection
Step 4: Skin Survey
Skin type, tan history, allergies, medications, pregnant/nursing flag, desired shade, special event
Step 5: Contact
Phone number input + SMS consent checkbox
Step 6: Review
Full summary → submit → POST /api/bookings → redirect to /book/confirmation
Other Forms
Login Form
Path: /login
- • Email (required, validated)
- • Password (required, show/hide toggle)
- • Remember me checkbox
- • Forgot password link
Registration Form
Path: /register
- • First name (required)
- • Last name (required)
- • Email (required, unique check)
- • Password (min 8 chars, strength meter)
- • Phone (optional)
Waitlist Form
Path: / (service area banner)
- • Email (required)
- • Phone (optional)
- • City (required)
- • State (required)
Artist Page Editor
Path: /artist portal
- • Page slug, headline, bio
- • Profile image, gallery (up to 12)
- • Social links (Instagram, TikTok, Facebook)
- • SEO title & description
- • Publish toggle
Square OAuth Connect Flow (Artist)
- Artist clicks "Connect Square" in portal
GET /api/square/oauth/authorizegenerates CSRF state, redirects to Square- Artist authorizes GGS on Square's consent screen
- Square redirects to
/api/square/oauth/callback - Callback verifies state, exchanges code for access + refresh tokens
- Tokens encrypted (AES-256-GCM) and stored in DB
- Artist redirected to portal with success message