Cloud Functions and Storage
Cloud Functions and Storage
So far, everything has run in the browser (frontend). But sometimes you need code that runs on a server — sending emails, processing payments, resizing images, or running scheduled tasks. That's where Cloud Functions come in. And when your app needs to handle file uploads, Cloud Storage is the answer.
Part 1: Cloud Functions
What Are Cloud Functions?
Cloud Functions are bits of server-side code that run in response to events. You write the function, deploy it to Firebase, and it runs automatically when triggered.
Think of them as "if this happens, do that" — but on a server:
| Trigger | Example |
|---|---|
| HTTP request | Someone visits a URL or calls an API |
| Firestore change | A document is created, updated, or deleted |
| Authentication | A new user signs up |
| Scheduled (cron) | Run every day at midnight |
| Storage | A file is uploaded |
Setting Up Cloud Functions
# If you didn't select Functions during firebase init: firebase init functions
Choose TypeScript when asked. This creates a functions/ directory:
functions/
├── src/
│ └── index.ts # Your functions go here
├── package.json
└── tsconfig.json
Install dependencies:
cd functions npm install
Your First HTTP Function
// functions/src/index.ts import { onRequest } from "firebase-functions/v2/https"; export const helloWorld = onRequest((request, response) => { response.json({ message: "Hello from Firebase!" }); });
Deploy and test:
firebase deploy --only functions
Firebase gives you a URL like:
https://helloworld-abc123.a.run.app
Visit that URL and you'll see { "message": "Hello from Firebase!" }.
Firestore Trigger Functions
Run code automatically when Firestore data changes:
import { onDocumentCreated, onDocumentUpdated, onDocumentDeleted } from "firebase-functions/v2/firestore"; // When a new user signs up, create a welcome notification export const onUserCreated = onDocumentCreated("users/{userId}", (event) => { const newUser = event.data?.data(); console.log("New user:", newUser?.name); // Create a welcome notification return event.data?.ref.firestore .collection("notifications") .add({ userId: event.params.userId, message: `Welcome, ${newUser?.name}!`, createdAt: new Date(), }); }); // When an order is updated, check if it was completed export const onOrderUpdated = onDocumentUpdated("orders/{orderId}", (event) => { const before = event.data?.before.data(); const after = event.data?.after.data(); if (before?.status !== "completed" && after?.status === "completed") { // Send confirmation email, update inventory, etc. console.log("Order completed:", event.params.orderId); } });
Scheduled Functions
Run code on a schedule (like a cron job):
import { onSchedule } from "firebase-functions/v2/scheduler"; // Run every day at midnight export const dailyCleanup = onSchedule("every day 00:00", async (event) => { // Clean up old data, send daily reports, etc. console.log("Running daily cleanup..."); }); // Run every hour export const hourlyCheck = onSchedule("every 60 minutes", async (event) => { console.log("Hourly check running..."); });
Callable Functions (Frontend Calls Backend)
These are functions your frontend can call directly, with built-in authentication:
// Backend — functions/src/index.ts import { onCall, HttpsError } from "firebase-functions/v2/https"; export const processPayment = onCall(async (request) => { // request.auth contains the calling user's info if (!request.auth) { throw new HttpsError("unauthenticated", "Must be logged in"); } const { amount, currency } = request.data; // Process payment... return { success: true, transactionId: "txn_123" }; });
// Frontend — calling the function import { getFunctions, httpsCallable } from "firebase/functions"; const functions = getFunctions(); const processPayment = httpsCallable(functions, "processPayment"); const result = await processPayment({ amount: 1999, currency: "usd" }); console.log(result.data); // { success: true, transactionId: "txn_123" }
What to ask your AI: "Create a Cloud Function that [does something] when [trigger event]. Use Firebase Functions v2 with TypeScript."
Testing Locally with the Emulator
Before deploying, test functions locally:
firebase emulators:start --only functions
This runs your functions on your computer. The emulator URL (usually http://localhost:5001) lets you test without deploying.
Deploy Functions
# Deploy all functions firebase deploy --only functions # Deploy a specific function firebase deploy --only functions:helloWorld
Part 2: Cloud Storage
What is Cloud Storage?
Cloud Storage is where your app stores files — images, PDFs, videos, user uploads, etc. It's like a file system in the cloud.
Setting Up Storage
- In Firebase Console → Storage → Get started
- Choose security rules (start with test mode for learning)
- Choose a location
Upload Files from the Frontend
import { storage } from "@/lib/firebase"; import { ref, uploadBytes, getDownloadURL } from "firebase/storage"; // Upload a file async function uploadFile(file: File, path: string): Promise<string> { const storageRef = ref(storage, path); const snapshot = await uploadBytes(storageRef, file); const downloadUrl = await getDownloadURL(snapshot.ref); return downloadUrl; } // Example: Upload a profile picture const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => { const file = event.target.files?.[0]; if (!file) return; const path = `profiles/${userId}/${Date.now()}-${file.name}`; const url = await uploadFile(file, path); // Save the URL to Firestore await updateDoc(doc(db, "users", userId), { avatarUrl: url, }); };
Upload with Progress Tracking
import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage"; function uploadWithProgress(file: File, path: string, onProgress: (percent: number) => void) { const storageRef = ref(storage, path); const uploadTask = uploadBytesResumable(storageRef, file); return new Promise<string>((resolve, reject) => { uploadTask.on( "state_changed", (snapshot) => { const percent = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; onProgress(percent); }, (error) => reject(error), async () => { const url = await getDownloadURL(uploadTask.snapshot.ref); resolve(url); } ); }); } // Usage in a React component const [progress, setProgress] = useState(0); const handleUpload = async (file: File) => { const url = await uploadWithProgress( file, `uploads/${file.name}`, (percent) => setProgress(percent) ); console.log("Uploaded! URL:", url); };
Delete Files
import { ref, deleteObject } from "firebase/storage"; async function deleteFile(path: string): Promise<void> { const storageRef = ref(storage, path); await deleteObject(storageRef); }
List Files in a Folder
import { ref, listAll, getDownloadURL } from "firebase/storage"; async function listFiles(folderPath: string) { const folderRef = ref(storage, folderPath); const result = await listAll(folderRef); const urls = await Promise.all( result.items.map(item => getDownloadURL(item)) ); return urls; } // Get all images in a user's folder const images = await listFiles(`profiles/${userId}`);
Storage Security Rules
Like Firestore, Storage has security rules (storage.rules):
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
// Users can only upload to their own folder
match /profiles/{userId}/{allPaths=**} {
allow read: if true;
allow write: if request.auth != null && request.auth.uid == userId;
}
// Anyone can read public files
match /public/{allPaths=**} {
allow read: if true;
allow write: if request.auth != null;
}
}
}
What to ask your AI: "Write Storage security rules that let users upload to their own folder and let everyone read public files."
Storage File Organization
Organize your files with clear paths:
storage/
├── profiles/
│ ├── userId1/
│ │ └── avatar.jpg
│ └── userId2/
│ └── avatar.jpg
├── posts/
│ ├── postId1/
│ │ ├── cover.jpg
│ │ └── attachment.pdf
│ └── postId2/
│ └── cover.jpg
└── public/
├── logo.png
└── banner.jpg
What to ask your AI: "Create a file upload component with drag-and-drop, progress bar, and preview. Store files in Firebase Storage and save URLs in Firestore."
What's Next?
You've covered all the major Firebase services. The final tutorial is your Firebase Cheat Sheet — a quick reference with commands, patterns, and AI prompts for every Firebase task.