Skip to content

Latest commit

Β 

History

History
588 lines (512 loc) Β· 25.7 KB

File metadata and controls

588 lines (512 loc) Β· 25.7 KB

πŸ“Έ Photobooth System Architecture

πŸ—οΈ System Components

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         TECH SPRINT 3.0                          β”‚
β”‚                      PHOTOBOOTH SYSTEM v1.0                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  β”‚                                  β”‚                  β”‚
β”‚  PIXEL DEVICE    │◄────── Staff Operates ────────►│  PARTICIPANTS    β”‚
β”‚  (Staff Use)     β”‚                                  β”‚  (Select Photo)  β”‚
β”‚                  β”‚                                  β”‚                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                                                      β”‚
         β”‚                                                      β”‚
         β–Ό                                                      β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                                   β”‚
β”‚                      FIREBASE BACKEND                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚  Firestore    β”‚  β”‚   Storage    β”‚  β”‚   Authentication     β”‚ β”‚
β”‚  β”‚  Collections  β”‚  β”‚   Buckets    β”‚  β”‚   (Existing)         β”‚ β”‚
β”‚  β”‚               β”‚  β”‚              β”‚  β”‚                      β”‚ β”‚
β”‚  β”‚ β€’ printQueue  β”‚  β”‚ β€’ photobooth/β”‚  β”‚ β€’ Users              β”‚ β”‚
β”‚  β”‚ β€’ checkins    β”‚  β”‚   {userId}/  β”‚  β”‚ β€’ Roles (staff)      β”‚ β”‚
β”‚  β”‚ β€’ registr...  β”‚  β”‚   photo.jpg  β”‚  β”‚                      β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚          β”‚                  β”‚                                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           β”‚                  β”‚
           β”‚                  β”‚ Real-time Sync
           β”‚                  β”‚
           β–Ό                  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                                   β”‚
β”‚                  PRINTER STATION COMPUTER                         β”‚
β”‚                    (Always-On Client)                             β”‚
β”‚                                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚  Browser: /printer/client                                  β”‚ β”‚
β”‚  β”‚  β€’ Real-time Firestore listener (onSnapshot)              β”‚ β”‚
β”‚  β”‚  β€’ Wake Lock API (prevents sleep)                          β”‚ β”‚
β”‚  β”‚  β€’ Auto-print on new jobs                                  β”‚ β”‚
β”‚  β”‚  β€’ 3-attempt retry logic                                   β”‚ β”‚
β”‚  β”‚  β€’ Connection monitoring + heartbeat                       β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
                             β”‚ Print Command
                             β–Ό
                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                   β”‚                    β”‚
                   β”‚   WiFi PRINTER     β”‚
                   β”‚  (Physical Device) β”‚
                   β”‚                    β”‚
                   β”‚  β€’ Full-size print β”‚
                   β”‚  β€’ No margins      β”‚
                   β”‚  β€’ High quality    β”‚
                   β”‚                    β”‚
                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“Š Data Flow Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        USER JOURNEY                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

1️⃣  SCAN QR CODE
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ Staff Scanner   β”‚
    β”‚ /staff/scanner  β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β”œβ”€ Check: User checked in? βœ“
             β”œβ”€ Check: Payment captured? βœ“
             β”œβ”€ Check: Already printed? βœ—
             β”‚
             β–Ό
    Record to Firestore:
    checkins/{id} = { userId, type: "photobooth", timestamp }
             β”‚
             β–Ό
    Redirect to capture page

2️⃣  TAKE PHOTOS
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ Staff Camera Interface β”‚
    β”‚ /photobooth/capture    β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                β”‚
                β”œβ”€ Activate: Back camera (4000x3000)
                β”œβ”€ Capture: Multiple photos (3-5)
                β”œβ”€ Canvas: imageSmoothingQuality = 'high'
                β”œβ”€ Export: toDataURL("image/jpeg", 0.95)
                β”‚
                β–Ό
    Upload to Firebase Storage:
    photobooth/{userId}/{timestamp}_0.jpg
    photobooth/{userId}/{timestamp}_1.jpg
    photobooth/{userId}/{timestamp}_2.jpg
                β”‚
                β–Ό
    Redirect to selection page

3️⃣  SELECT FAVORITE
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ Client Selection Page β”‚
    β”‚ /photobooth/select    β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
               β”œβ”€ List: All photos from Storage
               β”œβ”€ Display: Grid layout
               β”œβ”€ Check: Already printed? βœ—
               β”‚
               β–Ό
    User clicks photo + "Print Selected Photo"
               β”‚
               β–Ό
    Add to Firestore:
    printQueue/{id} = {
      userId, userName, teamName,
      photoUrl, status: "pending",
      createdAt: NOW
    }
               β”‚
               β–Ό
    Show success screen

4️⃣  AUTO-PRINT
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ Printer Client     β”‚
    β”‚ /printer/client    β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚
              β–Ό Real-time listener detects new job
              β”‚
    Update Firestore:
    printQueue/{id}.status = "printing"
              β”‚
              β–Ό
    Create iframe with print template:
    <style>@page { margin: 0mm; }</style>
    <img src="{photoUrl}" />
              β”‚
              β–Ό
    iframe.contentWindow.print()
              β”‚
              β”œβ”€ Success? βœ“
              β”‚   └─► Update: status = "completed", printedAt = NOW
              β”‚
              └─ Failure? βœ—
                  └─► Retry (max 3 attempts)
                      └─► Final failure: status = "failed"

5️⃣  PUBLIC GALLERY
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ Gallery Page       β”‚
    β”‚ /photobooth/galleryβ”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚
              β–Ό
    Query Firestore:
    printQueue WHERE status == "completed"
              β”‚
              β–Ό
    Display: Grid of all printed photos
    Filter: By team or classroom
    Real-time: onSnapshot listener

πŸ”’ Security Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   FIREBASE SECURITY LAYERS                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Layer 1: Authentication
─────────────────────────
β€’ All routes require: request.auth != null
β€’ Firebase Auth tokens verified server-side

Layer 2: Role-Based Access
───────────────────────────
β€’ Camera interface: Staff/Admin only
β€’ Scanner: Staff/Admin only
β€’ Gallery: All authenticated users
β€’ Printer client: No special role (runs as authenticated user)

Layer 3: Firestore Rules
─────────────────────────
printQueue Collection:
  β”œβ”€ Read: Any authenticated user
  β”œβ”€ Create: Staff/Admin only (checked via registrations/{uid}.role)
  β”œβ”€ Update: Any authenticated user (for status changes)
  └─ Delete: Admin only

checkins Collection:
  └─ (Existing rules apply - staff/admin can create)

Layer 4: Storage Rules
──────────────────────
photobooth/ Bucket:
  β”œβ”€ Read: Any authenticated user (for gallery)
  β”œβ”€ Write: Staff/Admin only
  └─ Delete: Admin only

Layer 5: Application Logic
───────────────────────────
β€’ Duplicate prevention: Triple check (scanner, selection, queue)
β€’ Check-in enforcement: Query checkins before allowing photobooth
β€’ Payment verification: Check payment_status == "captured"
β€’ One print per person: Query printQueue for existing completed prints

πŸ”„ State Machine (Print Status)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   PRINT JOB LIFECYCLE                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚   PENDING   β”‚  (User selected photo)
                  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
                         β”‚ Printer client detects (onSnapshot)
                         β–Ό
                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚  PRINTING   β”‚  (Print command sent)
                  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
                         β”‚
                    β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”
                    β”‚         β”‚
                Success?    Failure?
                    β”‚         β”‚
                    β–Ό         β–Ό
            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
            β”‚ COMPLETED  β”‚   β”‚  RETRY   β”‚  (Attempt 2/3)
            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜
                 β”‚                  β”‚
                 β”‚            β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”
                 β”‚            β”‚           β”‚
                 β”‚         Success?    Failure?
                 β”‚            β”‚           β”‚
                 β”‚            β–Ό           β–Ό
                 β”‚      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚      β”‚ COMPLETED  β”‚   β”‚  RETRY   β”‚ (Attempt 3/3)
                 β”‚      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜
                 β”‚                             β”‚
                 β”‚                       β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”
                 β”‚                       β”‚           β”‚
                 β”‚                    Success?    Failure?
                 β”‚                       β”‚           β”‚
                 β”‚                       β–Ό           β–Ό
                 β”‚                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚                 β”‚ COMPLETED  β”‚   β”‚  FAILED  β”‚
                 β”‚                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚                       β”‚                 β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                         β”‚
                                         β–Ό
                              Visible in public gallery
                              (if status == "completed")

Status Transitions:
─────────────────
β€’ pending β†’ printing (Printer client starts job)
β€’ printing β†’ completed (Print successful)
β€’ printing β†’ pending (Retry attempt)
β€’ printing β†’ failed (All retries exhausted)

Timestamps:
──────────
β€’ createdAt: When user selects photo
β€’ printedAt: When status becomes "completed"

🌐 Network Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   EVENT VENUE NETWORK                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚  WiFi Router  β”‚
                    β”‚  (Event WiFi) β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚             β”‚             β”‚
              β–Ό             β–Ό             β–Ό
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚   Pixel    β”‚  β”‚  Printer  β”‚  β”‚  WiFi    β”‚
     β”‚   Device   β”‚  β”‚ Computer  β”‚  β”‚ Printer  β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚               β”‚               β”‚
          β”‚               β”‚               β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β”‚
                          β”‚ Internet
                          β–Ό
                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                β”‚  FIREBASE CLOUD  β”‚
                β”‚                  β”‚
                β”‚ β€’ Firestore DB   β”‚
                β”‚ β€’ Cloud Storage  β”‚
                β”‚ β€’ Auth Service   β”‚
                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Connection Requirements:
───────────────────────
β€’ Pixel Device: WiFi + Internet (for Firebase sync)
β€’ Printer Computer: WiFi + Internet (for Firebase sync)
β€’ WiFi Printer: WiFi (for print commands from computer)
β€’ All devices on same network (recommended but not required)

Bandwidth Usage (Estimated):
────────────────────────────
β€’ Photo upload (4K): ~2-5 MB per photo
β€’ Photo download (printer): ~2-5 MB per photo
β€’ Firestore sync: < 1 KB per transaction
β€’ Total per participant: ~6-15 MB (3 photos captured, 1 printed)

πŸ”§ Technology Stack

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    TECHNOLOGY LAYERS                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Frontend Framework
──────────────────
β€’ Next.js 14+ (React framework)
β€’ TypeScript (type-safe development)
β€’ Tailwind CSS (styling)
β€’ Material-UI Icons (UI components)

Browser APIs
────────────
β€’ MediaDevices API (camera access)
β€’ Wake Lock API (prevent sleep)
β€’ Canvas API (image processing)
β€’ Print API (iframe.contentWindow.print())

Backend Services (Firebase)
────────────────────────────
β€’ Firestore Database (real-time data sync)
β€’ Cloud Storage (photo hosting)
β€’ Authentication (user management)
β€’ Security Rules (access control)

Libraries
─────────
β€’ html5-qrcode (QR scanner)
β€’ qrcode (QR generation - optional)
β€’ firebase SDK (v9+ modular)

Device Requirements
───────────────────
β€’ Pixel Device: Modern Android with camera
β€’ Printer Computer: Windows/Mac with modern browser
β€’ WiFi Printer: Any network printer

Browser Support
───────────────
β€’ Chrome 90+ (recommended)
β€’ Edge 90+ (recommended)
β€’ Safari 14+ (limited Wake Lock)
β€’ Firefox 89+ (limited Wake Lock)

πŸ“ˆ Performance Characteristics

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    PERFORMANCE METRICS                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Latency Measurements
────────────────────
β€’ Camera activation: 1-3 seconds
β€’ Photo capture: < 1 second
β€’ Canvas processing: < 1 second
β€’ Storage upload (per photo): 2-5 seconds
β€’ Firestore write: < 1 second
β€’ Real-time sync: < 1 second
β€’ Print trigger: < 1 second
β€’ Physical print: 30-60 seconds (printer-dependent)

Total Time Per User
───────────────────
β€’ Scanner to photo capture: 5 seconds
β€’ Taking 3 photos: 15 seconds
β€’ Upload: 10 seconds
β€’ Selection: 20 seconds
β€’ Print trigger: 2 seconds
β€’ Physical print: 45 seconds
─────────────────────────
TOTAL: ~97 seconds (~1.5 minutes)

Throughput Capacity
───────────────────
β€’ Max simultaneous captures: 1 (single Pixel device)
β€’ Max print queue size: Unlimited (Firestore)
β€’ Max concurrent prints: 1 (single printer)
β€’ Realistic throughput: 20-30 participants/hour
β€’ Event capacity (8 hours): 160-240 participants

Scalability
───────────
β€’ Bottleneck: Single printer (30-60 sec per print)
β€’ Solution: Add more printer computers + printers
β€’ Each additional printer: +20-30 participants/hour
β€’ Horizontal scaling: Linear with printer count

Resource Usage
──────────────
β€’ Firebase Storage: ~5 MB per participant (3 photos)
β€’ Firestore reads: ~10 per participant
β€’ Firestore writes: ~3 per participant
β€’ Network bandwidth: ~15 MB per participant
β€’ Browser memory: ~200 MB (printer client)

Cost Estimates (Firebase)
──────────────────────────
For 200 participants:
β€’ Storage: 1 GB = $0.026/month
β€’ Firestore reads: 2000 = $0.00036
β€’ Firestore writes: 600 = $0.00054
β€’ Network egress: 3 GB = $0.12
─────────────────────────
TOTAL: ~$0.15 for 200 participants

πŸ›‘οΈ Reliability & Fault Tolerance

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   FAILURE MODES & RECOVERY                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Component Failures
──────────────────

1. Pixel Device Camera Fails
   └─► Fallback: Lower resolution (1920x1440)
   └─► Manual: Use backup device
   └─► Impact: Medium (workflow stops)

2. WiFi Connection Lost
   └─► Auto-recovery: Firebase SDK reconnects
   └─► Manual: Check network, refresh page
   └─► Impact: High (uploads fail)

3. Printer Jams
   └─► Auto-recovery: 3 retry attempts
   └─► Manual: Clear jam, system retries
   └─► Impact: Low (queue buffers jobs)

4. Printer Computer Crashes
   └─► Auto-recovery: None (manual restart)
   └─► Manual: Reopen /printer/client
   └─► Impact: Medium (prints queue until restart)

5. Firebase Quotas Exceeded
   └─► Auto-recovery: None (upgrade plan)
   └─► Prevention: Monitor usage
   └─► Impact: Critical (system stops)

Redundancy Strategies
─────────────────────
β€’ βœ“ Retry logic: 3 attempts on failures
β€’ βœ“ Auto-reconnect: Firestore listener
β€’ βœ“ Queue buffering: Jobs persist in database
β€’ βœ“ Wake Lock: Prevents screen sleep
β€’ βœ“ Heartbeat: Monitors connection health
β€’ βœ— Multi-device: Single Pixel (bottleneck)
β€’ βœ— Load balancing: Single printer (bottleneck)

Data Persistence
────────────────
β€’ Photos: Permanently stored in Firebase Storage
β€’ Print queue: Permanently stored in Firestore
β€’ User data: Referenced from registrations
β€’ No local storage: All data in cloud

Recovery Time Objectives
─────────────────────────
β€’ Camera failure: < 1 minute (device swap)
β€’ Network loss: < 30 seconds (auto-reconnect)
β€’ Printer jam: < 2 minutes (manual clear)
β€’ Computer crash: < 5 minutes (reboot + reopen)
β€’ Firebase outage: N/A (wait for service)

πŸ“š API Reference (Internal)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   FIREBASE API USAGE                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Firestore Operations
────────────────────

READ: Query print history
  const q = query(
    collection(db, "printQueue"),
    where("userId", "==", uid),
    where("status", "==", "completed")
  );
  const snapshot = await getDocs(q);

WRITE: Add print job
  await addDoc(collection(db, "printQueue"), {
    userId, userName, teamName, photoUrl,
    status: "pending",
    createdAt: serverTimestamp()
  });

UPDATE: Change print status
  await updateDoc(doc(db, "printQueue", jobId), {
    status: "completed",
    printedAt: serverTimestamp()
  });

LISTEN: Real-time print queue
  const q = query(
    collection(db, "printQueue"),
    where("status", "==", "pending")
  );
  onSnapshot(q, (snapshot) => {
    snapshot.docChanges().forEach((change) => {
      if (change.type === "added") {
        handlePrint(change.doc.data());
      }
    });
  });

Storage Operations
──────────────────

UPLOAD: Photo to storage
  const storageRef = ref(storage, `photobooth/${uid}/${timestamp}.jpg`);
  await uploadBytes(storageRef, blob);

DOWNLOAD: Get photo URL
  const url = await getDownloadURL(storageRef);

LIST: All photos for user
  const folderRef = ref(storage, `photobooth/${uid}`);
  const result = await listAll(folderRef);
  const urls = await Promise.all(
    result.items.map(item => getDownloadURL(item))
  );

Architecture Version: 1.0
Last Updated: Pre-Deployment
Document Status: Complete
Review Status: Ready for Technical Review