Data Layer
Yugma is fully Firebase-native: Auth, Firestore, Realtime Database, Cloud Storage, and Cloud Functions.
Firebase Services
Authentication
| Method | Provider |
|---|---|
| Email/password | Firebase Auth |
| Anonymous (guest) | Firebase Auth |
| Google OAuth | Firebase Auth |
Guest accounts can upgrade to email accounts without losing data. onUserCreate trigger seeds a user profile in Firestore.
Firestore Collections
| Collection | Path | Purpose | Access |
|---|---|---|---|
projects | projects/{projectId} | Scene data + metadata | Owner read/write |
projects/*/assets | projects/{pid}/assets/{aid} | Per-project asset library | Authenticated |
shareLinks | shareLinks/{linkId} | Public share link metadata | Public read, auth write |
aiSessions | aiSessions/{uid}/sessions/{sid} | AI chat history (Firestore copy) | Owner only |
aiRateLimits | aiRateLimits/{uid} | Per-user rate limit counters | Owner only |
generationJobs | generationJobs/{jobId} | Meshy text-to-3D jobs | Owner only |
materialJobs | materialJobs/{jobId} | AI material gen jobs | Owner only |
videoJobs | videoJobs/{jobId} | Phase 12 video reconstruction | Owner only |
renderJobs | renderJobs/{jobId} | Phase 16 render jobs | Owner only |
sysconfig/admins | — | Admin UID list | Auth read, console write |
sysconfig/providers | — | LLM provider config (keys) | Admin only |
Realtime Database Paths
| Path | Purpose | Frequency |
|---|---|---|
collab/{sessionId}/presence/{uid} | User online status | On connect/disconnect |
collab/{sessionId}/cursors/{uid} | 3D cursor position | ~30 Hz |
collab/{sessionId}/deltas/{deltaId} | Scene change deltas | Per edit |
rooms/{roomCode} | Room code → session mapping | On create/join |
sensors/{sensorId}/latest | Phase 13 live sensor readings | Varies (MQTT bridge) |
sensors/{sensorId}/history/{readingId} | Phase 13 sensor history | Varies |
Cloud Storage
assets/{uid}/{timestamp}_{filename} — uploaded GLBs, textures
generated/{uid}/{jobId}.glb — Meshy-generated models
videos/{uid}/{jobId}/{filename} — Phase 12 video uploads
Access via signed upload/download URLs (Cloud Functions).
AI Session Persistence
Sessions are stored in Firestore at aiSessions/{uid}/sessions/{sessionId}. Each document contains the full message array, auto-updated via setDoc with merge on each AI turn. On mount, loadLastSession queries the most recent session by updatedAt and hydrates the chat.
Client send message → AIPanel → saveAISession → Firestore (fire-and-forget)
Client mount → loadLastSession (Firestore query) → hydrateSession
Zustand Stores (14 total)
| Store | Key state |
|---|---|
useSceneStore | objects, objectOrder, selectedObjectId, environment, cameraTarget |
useAnimationStore | clips, currentFrame, isPlaying |
useProjectStore | projectMeta, isDirty |
useAuthStore | user, isLoading |
useAIStore | messages, isStreaming, sessionId |
useUIStore | toasts, theme |
useCollabStore | remoteUsers, isConnected |
useRoomStore | roomCode, isHost |
useCommentStore | comments |
useGenerationStore | jobs (text-to-3D) |
useHistoryStore | undoStack, redoStack |
useTwinStore | bindings, readings (Phase 13) |
usePhysicsStore | bodies, simulation state (Phase 15) |
useVideoStore | jobs (Phase 12) |
useProductStore | bom, enclosure, pcb, firmware (Phase 14) |
useCinematicStore | storyboards, shots, renderJobs (Phase 16) |
Security Rules
All Firestore rules enforce owner-only access for user-scoped data. Pattern:
allow read: if request.auth != null && resource.data.userId == request.auth.uid;
allow create: if request.auth != null && request.resource.data.userId == request.auth.uid;