Skip to main content

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 their uid, 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:

  1. Authentication Check: The function automatically verifies the user's ID token. If the user isn't authenticated, the function call fails.
  2. Create Initial Firestore Doc: Immediately create a new document in the generations collection with status: 'pending'. This gives the user instant feedback that the process has started.
  3. Call Gemini API: The function securely calls the Gemini API using your server-side API key (stored safely in Cloud Secret Manager).
  4. Handle Gemini Response:
    • On Success: Gemini returns the 3D model data (e.g., as a binary buffer).
    • On Failure: Gemini returns an error message.
  5. 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 example generations/{generationId}.glb.
    • Once uploaded, the function gets the public, signed, or CDN URL for the newly created file.
  6. 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.js SceneLoader 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

  1. Create Firebase Project: Go to the Firebase Console and create a new project. This also creates a corresponding Google Cloud project.
  2. 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.
  3. Configure React App:
    • Install the Firebase SDK: npm install firebase.
    • Initialize Firebase in your app with the configuration keys from the Firebase console.
  4. 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 the functions/src directory.
  5. 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.
  6. 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.
  7. 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 and firebase deploy --only hosting).

This architecture provides a robust, secure, and highly scalable foundation for your Text-to-CAD application.