Skip to main content

Collections Overview

The database consists of the following main collections:
  1. artist-clients - Manages relationships between artists and their clients
  2. availability - Stores availability schedules and time slots
  3. bookings - Contains booking/appointment information
  4. conversations - Stores messaging and communication data
  5. customerPaymentInfo - Manages customer payment-related information
  6. user-notifications - Handles user notification settings and data
  7. user-onboarding - Stores user onboarding progress and related data
  8. users - Contains core user profile information and details

Database Diagram

Database Schema Diagram

The diagram above shows the main collections in our Firebase database and how they relate to each other. Each connection line represents a relationship between collections, typically through document references.

Collection Schemas

artist-clients

The artist-clients collection uses a nested structure to manage the relationship between artists and their clients:
// Top level document is the artist's user ID
artist-clients/{artistId}/

// Contains a subcollection of clients
artist-clients/{artistId}/clients/{clientId}/ {
  bookingIds: string[],        // Array of booking IDs associated with this client
  clientId: string,            // Reference to the client's user ID
  firstBookingDate: number,    // Timestamp of first booking
  notes: string,              // Artist's notes about the client
  totalSpent: number          // Total amount spent by client with this artist
}

Key Details:

  • The collection uses a nested structure for efficient querying of artist-client relationships
  • Each artist’s document contains a subcollection of their clients
  • Client documents track booking history, spending, and artist notes
  • The bookingIds array enables quick access to all bookings between the artist and client
  • firstBookingDate is stored as a timestamp for chronological ordering

bookings

The bookings collection stores all booking information between artists and clients. Each booking document goes through various states in its lifecycle:
bookings/{bookingId} {
  // Base fields (present in all booking states)
  id: string,                  // Unique booking identifier
  createdAt: number,           // Timestamp of booking creation
  lastUpdatedAt: number,       // Timestamp of last update
  status: BookingStatusEnum,   // Current status of the booking
  customerUserId: string,      // Reference to the customer's user ID
  artistUserId: string,        // Reference to the artist's user ID
  conversationId: string,      // Reference to associated conversation
  referenceNumber: string,     // Human-readable booking reference

  // Tattoo Information
  bookingTattooInfo: {
    requestType: "Flash" | "Custom",
    description: string,
    isCoverUp: boolean,
    color: string,
    length: number,
    width: number,
    tattooPlacement: string[],
    tattooStyle: string[],
    images: string[],          // URLs to reference images
    links?: string[],          // Optional additional reference links
    selectedDates: number[],   // Preferred dates
    desiredTimeOfDay: "Morning" | "Afternoon" | "Either",
    medicalConditions?: string,
    isOver18: boolean
  },

  // Booking Details (optional until confirmed)
  location?: string,           // Tattoo location/studio
  dateTimestamp?: number,      // Confirmed date
  startTime?: number,          // Start time
  endTime?: number,           // End time
  totalFee?: string,          // Total cost
  depositFee?: string,        // Required deposit amount
  notes?: string,             // Additional booking notes
  reviewId?: string          // Reference to review (only for completed bookings)
}

Booking Status Lifecycle:

The booking goes through different states, tracked by the status field:
  • REQUESTED: Initial state when client submits booking request
  • AWAITING_DEPOSIT: Artist has accepted and waiting for client’s deposit
  • CONFIRMED: Deposit received and booking is confirmed
  • COMPLETED: Tattoo session completed
  • CANCELLED: Booking was cancelled

Key Details:

  • Each booking document contains all necessary information about the tattoo request
  • The status field determines which fields are required/optional
  • Images and links are stored as URLs, with actual files in Firebase Storage
  • Timestamps are stored as numbers for efficient querying
  • The booking maintains references to both the artist and client
  • A conversation is automatically created and linked to each booking

conversations

The conversations collection manages messaging between users, with a nested structure for messages:
conversations/{conversationId} {
  id: string,                    // Unique conversation identifier
  artistId: string,              // Reference to the artist
  clientId: string,              // Reference to the client
  lastMessageText: string,       // Preview of the most recent message
  lastMessageTimestamp: number,  // Timestamp of the most recent message
  unreadCounts: {               // Tracks unread messages for each participant
    [userId: string]: number
  },
  bookingIds: string[],          // Array of associated booking IDs
  createdAt: number,             // When the conversation was created
}

// Subcollection for messages
conversations/{conversationId}/messages/{messageId} {
  // Base message fields
  id: string,                    // Unique message identifier
  senderId: string,              // User ID of the sender
  timestamp: number,             // Message timestamp
  readBy: string[],              // Array of user IDs who have read the message

  // Message content (varies by type)
  type: MessageTypeEnum,         // TEXT | FILE | REQUEST | CONFIRMATION | CANCELLED | EDIT

  // Type-specific fields
  // For TEXT messages:
  text?: string,                 // Message content for text messages

  // For FILE messages:
  name?: string,                 // Original filename
  fileType?: string,            // MIME type of the file
  fileUrl?: string,             // Storage URL for the file

  // For REQUEST messages:
  // ... includes BookingTattooInfo fields

  // For CONFIRMATION messages:
  dateTimestamp?: number,        // Confirmed booking date
  startTime?: number,           // Start time
  endTime?: number,             // End time
  notes?: string,               // Additional notes
  price?: number,               // Confirmed price

  // New field for booking-related messages
  bookingId?: string,           // Reference to related booking if message is booking-related
}

Message Types:

The messages subcollection supports different types of messages:
  1. TEXT: Standard text messages
  2. FILE: File attachments (images, documents, etc.)
  3. REQUEST: Booking requests with tattoo details
  4. CONFIRMATION: Booking confirmation details
  5. CANCELLED: Booking cancellation notifications
  6. EDIT: Booking edit notifications
Currently each conversation is unique per booking. We might want to refactor this to be one conversation per artist-client pair in the future.

Key Details:

  • Each conversation document tracks participants and message metadata
  • The unreadCounts map enables efficient unread message tracking per user
  • lastMessageText and lastMessageTimestamp enable conversation previews
  • Messages are stored in a subcollection for efficient pagination
  • File messages store URLs pointing to Firebase Storage
  • Special message types (REQUEST, CONFIRMATION) integrate with the booking system
  • The readBy array tracks message read status for all participants

user-notifications

The user-notifications collection manages notification state and history for each user, with a nested structure for individual notifications:
user-notifications/{userId} {
  id: string,                    // User ID
  lastUpdated: number,           // Timestamp when notifications were last viewed
  newNotificationIds: string[],  // Array of unviewed notification IDs
}

// Subcollection for individual notifications
user-notifications/{userId}/notifications/{notificationId} {
  id: string,                    // Unique notification identifier
  userId: string,                // ID of user receiving notification
  createdAt: number,             // Timestamp when notification was created
  isRead: boolean,               // Whether the notification has been read
  type: NotificationTypeEnum,    // Type of notification
  data: NotificationDataMap[T]   // Type-specific notification data
}

Notification Types

The system primarily supports booking-related notifications that track the lifecycle of a booking:
  • Booking Status Updates: Notifications for new requests, confirmations, edits, cancellations, and declines
  • Payment Updates: Notifications for deposit payments (to be implemented)
  • System Updates: Platform-wide notifications like new feature announcements (to be implemented)
Each notification includes relevant context like booking IDs and user names for display purposes.

Key Details:

  • Each user has a document tracking their notification state
  • lastUpdated tracks when the user last viewed their notifications
  • newNotificationIds maintains a list of notifications that appeared since the last view
  • Individual notifications are stored in a subcollection for efficient pagination
  • The isRead flag tracks individual notification read status
  • Notification data is type-safe through TypeScript generics

user-onboarding

The user-onboarding collection tracks the onboarding progress for users:
user-onboarding/{userId} {
  verifyEmail: boolean,        // Whether user has verified their email
  completeProfile: boolean,    // Whether user has completed their profile
  setupCalendar: boolean,      // Whether user has set up their availability calendar
  shareBookingLink: boolean,   // Whether user has configured their booking link
  setupPayments: boolean,      // Whether user has set up payment methods
  updatedAt: Date             // Last time onboarding status was updated
}

Key Details:

  • Each document represents a user’s onboarding progress
  • Boolean flags track completion status of each onboarding step
  • Steps include email verification, profile setup, calendar configuration, booking link setup, and payment setup
  • updatedAt field helps track when users last made progress in onboarding
  • Used to guide users through the necessary setup steps before they can fully use the platform

users

The users collection stores core user profile information and extends Firebase Authentication user data:
users/{userId} {
  // Basic Information
  id: string,                    // Firebase Auth User ID
  email: string,                 // User's email address
  firstName: string,             // First name
  lastName: string,              // Last name
  displayName: string,           // Full display name
  phoneNumber: {                 // Optional phone number
    countryCode: string,         // e.g., "+61"
    number: string,              // e.g., "0482394387"
  } | null,
  photoURL: string,              // Profile photo URL

  // Profile Details
  bio: string,                   // User's biography/description
  createdAt: number,             // Account creation timestamp
  location?: string,             // User's location
  pronouns: "Don't Specify" | "He/Him" | "She/Her" | "They/Them" | "Other",
  otherPronouns?: string,        // Custom pronouns if "Other" selected

  // Artist-specific fields
  userType?: "artist" | "client", // User role (defined after onboarding)
  styles: string[],              // Artist's tattoo styles
  socialMedia: {
    instagram: string,           // Instagram profile URL
  },
  stripeAccountId?: string,      // Connected Stripe account for payments

  // Miscellaneous
  howDidYouHearAboutUs?: string  // Platform discovery information
}

Key Details:

  • Extends Firebase Authentication with additional user profile information
  • Supports both artist and client user types
  • Artists have additional fields for styles, social media, and payment processing
  • Profile photos and media are stored in Firebase Storage with URLs in the document
  • Some fields become required based on user type and onboarding progress
  • Integrates with Stripe for artist payment processing
  • Social media integration currently focuses on Instagram, with potential for expansion

availability

This collection is still under development
The availability collection will manage artist availability and scheduling:
// Schema to be implemented
availability/{artistId} {
  // ... schema details coming soon
}

customerPaymentInfo

This collection is still under development
The customerPaymentInfo collection will handle customer payment methods and history:
// Schema to be implemented
customerPaymentInfo/{userId} {
  // ... schema details coming soon
}

Relationships

The database is built around several key relationships that enable the booking and communication flow:

Core User Relationships

  • usersuser-onboarding: Each user has an onboarding document tracking their setup progress
  • usersuser-notifications: Each user has a notifications document with their notification history
  • usersartist-clients: Artists have client relationships stored in nested collections

Booking Flow

  • bookingsusers: Each booking references both an artist and a client
  • bookingsconversations: Each booking has an associated conversation for communication
  • bookingsartist-clients: Bookings are tracked in the artist-client relationship

Communication

  • conversationsusers: Conversations track participants and their read/unread status
  • conversationsbookings: Messages can contain booking-related actions (requests, confirmations)
  • user-notificationsbookings: Notifications are generated for booking status changes
This interconnected structure ensures that:
  1. Artists can manage their client relationships and booking history
  2. Clients can track their bookings and communications with artists
  3. All booking-related actions are properly communicated and tracked
  4. User progress and notifications are properly managed

Data Access Patterns

[To be populated with common data access patterns]

Security Rules

[To be populated with Firebase security rules overview]

Best Practices

[To be populated with database-specific best practices]