βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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 β
β β
ββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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"
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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 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 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
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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