specs
Guest Profiles

Guest Profiles — House of Legends

Documented: 2026-05-11


Guest Journey

Reservation Made


QR Code Received (via email/WhatsApp)


Guest Arrives → Scan QR at Venue


Profile Created/Linked

      ├──► Reaction (WAVE/CHEERS/HEART other guests)
      ├──► Photo Wall (submit photo, like others)
      ├──► Lucky Spin (win comp items)
      └──► Google Review Challenge (earn rewards)

QR Code & Onboarding

QR Code Content

Each reservation gets a unique QR code containing:

{
  "reservationId": "abc123",
  "token": "guest-token-xyz",
  "showDate": "2026-05-15"
}

Profile Creation Flow

  1. Guest scans QR with phone camera
  2. App opens /profile?token=xxx
  3. If not logged in → Clerk OAuth (Google/Facebook)
  4. Profile created/linked via token
  5. Guest sees: nickname input, mood tags, origin

Tables

guestProfiles: defineTable({
  reservationId: v.optional(v.id("reservations")),
  tableId: v.optional(v.id("tables")),
  token: v.string(),
  googleId: v.optional(v.string()),
  facebookId: v.optional(v.string()),
  email: v.optional(v.string()),
  avatarUrl: v.optional(v.string()),
  nickname: v.string(),
  origin: v.string(),
  moodTags: v.array(v.string()),
  bio: v.optional(v.string()),
  showDate: v.string(),
  checkedIn: v.boolean(),
  createdAt: v.number(),
  updatedAt: v.number(),
})
  .index("by_reservation", ["reservationId"])
  .index("by_show_date", ["showDate"])
  .index("by_token", ["token"]);

Reactions (WAVE/CHEERS/HEART)

Guests can react to other guests (not themselves):

  • WAVE 👋 — Hello/greeting
  • CHEERS 🥂 — Toast/celebration
  • HEART ❤️ — Love/appreciation

Reaction Flow

  1. Guest views other profiles on wall/table
  2. Taps reaction button
  3. Reaction saved to guestReactions
  4. Target guest sees reaction notification

Table

guestReactions: defineTable({
  fromProfileId: v.id("guestProfiles"),
  toProfileId: v.id("guestProfiles"),
  reactionType: v.union(
    v.literal("WAVE"),
    v.literal("CHEERS"),
    v.literal("HEART"),
  ),
  showDate: v.string(),
  createdAt: v.number(),
})
  .index("by_to_profile", ["toProfileId"])
  .index("by_from_profile", ["fromProfileId"])
  .index("by_show_date", ["showDate"]);

Mood Tags

Guests select mood tags during onboarding:

TagDescription
LOOKING_FOR_DATELooking for a date
GET_DRUNKHere to enjoy drinks
FIRST_TIMEFirst time visitor
REGULARReturning guest
CELEBRATINGSpecial occasion
GOOD_FRIENDSOut with friends
SOLOFlying solo
WITH_FAMILYFamily outing

Components

Profile Card

Displays:

  • Avatar (or generated initial)
  • Nickname
  • Origin
  • Mood tags
  • Reaction count (received)

Reaction Button

Three-state button: WAVE / CHEERS / HEART

  • Tapping cycles through reactions
  • Shows count for each type

Onboarding Flow

Step 1: Scan QR → Token validated
Step 2: Login with Google/Facebook (or skip)
Step 3: Enter nickname
Step 4: Select mood tags (multi-select)
Step 5: Select origin (dropdown)
Step 6: Profile created → Redirect to experience

Backend Functions

FunctionPurpose
profiles.createFromReservationCreate profile on check-in
profiles.linkOAuthLink Google/Facebook to profile
profiles.addReactionAdd reaction to another guest
profiles.getReactionsGet reactions for a profile
profiles.updateMoodTagsUpdate mood tags