Architecture
Of course. Using a "full-Google" stack is an excellent strategy for rapid development, tight integration, and simplified management.
Here is a detailed architectural plan in Markdown format. You can save this as ARCHITECTURE.md
in your project's root directory.
Architecture Plan: Text-to-CAD with Gemini & Firebase
This document outlines the complete technical architecture for the Vite/React-based Text-to-CAD application. The chosen stack leverages the Google Cloud/Firebase ecosystem for a seamless, scalable, and rapidly deployable solution.
1. Core Principles & Technology Stack
- Principle: Speed of development and tight integration are paramount. We will leverage managed services to minimize infrastructure overhead.
- Frontend: Vite + React with Babylon.js for 3D rendering.
- Authentication: Firebase Authentication for user sign-up, login, and session management.
- Metadata Database: Cloud Firestore for storing all structured data like user info, prompts, and model details. Its real-time capabilities are a key advantage.
- 3D Model Storage: Google Cloud Storage (GCS) for storing the large
.glb
binary files generated by the AI. - Backend Logic: Cloud Functions for Firebase to provide a secure server-side environment for calling the Gemini API and interacting with GCS. This is critical for security.
2. High-Level Architectural Diagram
This diagram illustrates the flow of data and requests between the components.
+---------------------+ (1. Login/Auth) +-------------------------+
| Vite/React App |<-------------------->| Firebase Authentication |
| (Babylon.js Scene) | +-------------------------+
+---------------------+
| ^
| (2. Call | (6. Listen for real-time
| Generate | updates & get Model URL)
| Function) |
v |
+------------------------------------+ (3. Call Gemini) +------------------+
| Cloud Function for Firebase |---------------------->| Gemini 1.5 API |
| (Node.js Backend Logic) |<----------------------| (returns .glb) |
+------------------------------------+ (4. Process & Save) +------------------+
| |
| (5a. Update | | (5b. Upload .glb file)
| Metadata) | |
v v
+----------------+ +----------------------------+
| Cloud Firestore| | Google Cloud Storage |
| (Users, Gens) | | (Stores the actual models) |
+----------------+ +----------------------------+
3. Data Models (Firestore Collection Design)
We will use a flat data structure in Firestore to enable simple and efficient queries. We will not use sub-collections for this core model to avoid query complexity.
a. users
collection
Stores public-facing information about each user. The document ID will be the user's unique ID (uid
) provided by Firebase Authentication.
Document ID: user.uid
// /users/{uid}
{
"email": "user@example.com", // string (from Firebase Auth)
"displayName": "Alex Doe", // string (from Firebase Auth)
"photoURL": "https://...", // string (from Firebase Auth)
"createdAt": "2023-10-27T10:00:00Z", // timestamp
"plan": "free" // string ('free', 'pro', etc.)
}
b. generations
collection
Stores the metadata for every single text-to-CAD generation attempt.
Document ID: (Auto-generated by Firestore)
// /generations/{generationId}
{
"userId": "the_user_uid_from_auth", // string (links to the user)
"status": "completed", // string ('pending', 'processing', 'completed', 'failed')
"prompt": "a 10mm hex bolt with M6 threading", // string
"negativePrompt": "smooth head", // string (optional)
"generationParams": { // map (stores specific Gemini settings)
"seed": 42,
"quality": "high_detail"
},
"modelURL": "https://storage.googleapis.com/...", // string (public URL to the .glb in GCS)
"thumbnailURL": "https://storage.googleapis.com/...", // string (URL to a preview image)
"error": null, // string (stores error message if status is 'failed')
"createdAt": "2023-10-27T10:05:00Z" // timestamp
}
4. Detailed End-to-End Workflow
This is the step-by-step process from a user action to seeing the result.
Step 1: User Authentication (Client-Side)
- The React app uses the Firebase Web SDK (
firebase/auth
). - It presents login options (e.g., Google Sign-In, Email/Password).
- Upon successful login, Firebase provides a
user
object containing theiruid
,email
, etc., and an ID token. - We can create a corresponding document in our
users
collection if one doesn't already exist.
Step 2: Triggering a Generation (Client to Backend)
- The user types a prompt into a form in the React app and clicks "Generate".
- The React app does not call the Gemini API directly. This would expose your API keys.
- Instead, it calls a Callable Cloud Function. This is more secure and easier than setting up a full REST API.
// React Component Snippet
import { getFunctions, httpsCallable } from "firebase/functions";
const functions = getFunctions();
const generateModel = httpsCallable(functions, 'generateModel');
const handleGenerateClick = async () => {
try {
const result = await generateModel({ prompt: "my cad prompt" });
console.log("Generation started with ID:", result.data.generationId);
// Now we can start listening for changes to this document
} catch (error) {
console.error("Error calling function:", error);
}
};
Step 3: Backend Processing (The Cloud Function)
This is where the heavy lifting happens. The generateModel
Cloud Function performs the following actions:
- Authentication Check: The function automatically verifies the user's ID token. If the user isn't authenticated, the function call fails.
- Create Initial Firestore Doc: Immediately create a new document in the
generations
collection withstatus: 'pending'
. This gives the user instant feedback that the process has started. - Call Gemini API: The function securely calls the Gemini API using your server-side API key (stored safely in Cloud Secret Manager).
- Handle Gemini Response:
- On Success: Gemini returns the 3D model data (e.g., as a binary buffer).
- On Failure: Gemini returns an error message.
- Upload to Google Cloud Storage:
- The function takes the binary model data.
- It uploads this data to a GCS bucket (e.g.,
gs://your-project-id-models
). The file is named uniquely, for examplegenerations/{generationId}.glb
. - Once uploaded, the function gets the public, signed, or CDN URL for the newly created file.
- Update Firestore Document:
- The function updates the Firestore document created in step 2.
- It sets
status
to'completed'
(or'failed'
). - It populates the
modelURL
with the GCS link. - If there was an error, it populates the
error
field.
Step 4: Real-time Feedback on the Frontend
- Instead of repeatedly asking the server "are you done yet?" (polling), the frontend will use Firestore's real-time capabilities.
- After calling the Cloud Function and getting the
generationId
, the React app subscribes to that specific document.
// React Component Snippet
import { getFirestore, doc, onSnapshot } from "firebase/firestore";
const db = getFirestore();
const unsub = onSnapshot(doc(db, "generations", generationId), (doc) => {
const data = doc.data();
if (data.status === 'completed') {
// SUCCESS! Load the model into Babylon.js
loadModelIntoScene(data.modelURL);
unsub(); // Stop listening
} else if (data.status === 'failed') {
// Show an error message to the user
showError(data.error);
unsub(); // Stop listening
}
// else, status is 'pending' or 'processing', so just wait.
});
Step 5: Loading the Model (Client-Side)
- Once the
modelURL
is available, the Babylon.jsSceneLoader
can load the model directly from Google Cloud Storage.
// Babylon.js Loading Snippet
import { SceneLoader } from "@babylonjs/core";
const loadModelIntoScene = (modelURL) => {
SceneLoader.ImportMeshAsync(null, "", modelURL, scene, (meshes) => {
// Model loaded, position it, etc.
});
};
5. Security Rules
This is a non-negotiable part of the Firebase architecture. We will define rules to prevent unauthorized data access.
a. Firestore Security Rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Users can only read their own user doc, and anyone can create one for themselves.
match /users/{userId} {
allow read, update: if request.auth != null && request.auth.uid == userId;
allow create: if request.auth != null;
}
// Generations can be read by anyone (for a public gallery).
// A user can only create a generation for themselves.
// Only the owner can update or delete their generation.
match /generations/{generationId} {
allow read: if true; // Or change to `if request.auth != null` for logged-in users only
allow create: if request.auth != null && request.resource.data.userId == request.auth.uid;
allow update, delete: if request.auth != null && resource.data.userId == request.auth.uid;
}
}
}
b. Cloud Storage Security Rules
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
// Only allow file uploads for files inside a 'generations' folder where the filename
// matches the user's ID. This is a common pattern for user-owned content.
// Our Cloud Function will have admin privileges and bypass these rules, but this
// prevents malicious client-side uploads.
match /generations/{userId}/{fileName} {
allow read: if true; // Allow public reads of all models
allow write: if request.auth != null && request.auth.uid == userId;
}
}
}
6. Setup & Deployment Checklist
- Create Firebase Project: Go to the Firebase Console and create a new project. This also creates a corresponding Google Cloud project.
- Enable Services:
- In the Firebase Console, enable Authentication, Firestore, and Storage.
- In the Google Cloud Console, enable the Gemini API and Cloud Secret Manager API.
- Configure React App:
- Install the Firebase SDK:
npm install firebase
. - Initialize Firebase in your app with the configuration keys from the Firebase console.
- Install the Firebase SDK:
- Set up Cloud Functions:
- Install the Firebase CLI:
npm install -g firebase-tools
. - Run
firebase init functions
in your project root. Choose TypeScript or JavaScript. - Write the
generateModel
function logic in thefunctions/src
directory.
- Install the Firebase CLI:
- Local Development:
- Use the Firebase Local Emulator Suite (
firebase emulators:start
). This is essential for testing your functions, Firestore rules, and auth flow locally without incurring costs.
- Use the Firebase Local Emulator Suite (
- API Keys:
- Store your Gemini API Key in Cloud Secret Manager. Do not hardcode it in your Cloud Function. Access it at runtime from the function.
- Deployment:
- Deploy security rules:
firebase deploy --only firestore:rules,storage:rules
- Deploy your function:
firebase deploy --only functions
- Deploy your Vite/React app: Use Firebase Hosting for the simplest deployment (
firebase init hosting
andfirebase deploy --only hosting
).
- Deploy security rules:
This architecture provides a robust, secure, and highly scalable foundation for your Text-to-CAD application.