Skip to content

Firebase Complete Project: Build a Full-Stack Security App from Scratch

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about Firebase Complete Project: Build a Full. We cover key concepts, practical examples, and best practices to help you master this topic.

This project combines all Firebase services into a production-ready security dashboard app — Firebase Auth, Firestore, Storage, Cloud Functions, Hosting, FCM, and Analytics working together.

What You'll Learn

How to architect and build a complete Firebase application, integrating authentication, database, storage, serverless functions, hosting, push notifications, and analytics into a cohesive system.

Why It Matters

Individual Firebase services are powerful. Combined, they form a complete backend. This project shows how DodaTech builds full-stack applications with zero server management using Firebase.

Real-World Use

The Durga Antivirus Pro dashboard: users sign in (Auth), register devices (Firestore), upload suspicious files (Storage), receive scan results (Functions + FCM), and view analytics (Analytics).

flowchart TD
    A["User"] --> B["Firebase Auth\nSign In"]
    B --> C["Web Dashboard\nHosting"]
    C --> D["Register Device\nFirestore"]
    C --> E["Upload File\nStorage"]
    D --> F["Cloud Functions\nProcess Scan"]
    E --> F
    F --> G["Result in\nFirestore"]
    G --> H["FCM Notification\nPush Alert"]
    G --> C
    G --> I["Analytics\nTrack Events"]
    style B fill:#fef3c7,stroke:#d97706
    style F fill:#dbeafe,stroke:#2563eb
    style H fill:#fce7f3,stroke:#ec4899

Project Architecture

security-dashboard/
  src/
    index.html          # Entry point
    app.js              # Firebase init + routing
    auth.js             # Auth logic
    devices.js          # Device management
    scans.js            # Scan results
    storage.js          # File uploads
    notifications.js    # FCM handling
    analytics.js        # Event tracking
  functions/
    index.js            # Cloud Functions
    scanProcessor.js    # Scan analysis
    notifier.js         # FCM sender
    cleanup.js          # Scheduled cleanup
  firestore.indexes.json
  storage.rules
  firestore.rules
  firebase.json

Step 1: Firebase Init and Auth

// app.js
import { initializeApp } from "firebase/app";
import { getAuth, onAuthStateChanged } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import { getStorage } from "firebase/storage";
import { getMessaging } from "firebase/messaging";
import { getAnalytics, logEvent } from "firebase/analytics";

const firebaseConfig = {
  apiKey: "AIzaSy...",
  authDomain: "durga-antivirus.firebaseapp.com",
  projectId: "durga-antivirus",
  storageBucket: "durga-antivirus.appspot.com"
};

const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const db = getFirestore(app);
export const storage = getStorage(app);
export const messaging = getMessaging(app);
export const analytics = getAnalytics(app);

onAuthStateChanged(auth, (user) => {
  if (user) {
    logEvent(analytics, "user_signed_in");
    loadDashboard();
  } else {
    showLoginPage();
  }
});

Step 2: Device Registration with Image Upload

// devices.js
import { doc, setDoc, collection, addDoc } from "firebase/firestore";
import { ref, uploadBytes, getDownloadURL } from "firebase/storage";
import { auth, db, storage } from "./app.js";

async function registerDevice(deviceName, os, screenshotFile) {
  const userId = auth.currentUser.uid;
  const deviceRef = doc(collection(db, "devices"));

  // Upload screenshot
  let screenshotUrl = null;
  if (screenshotFile) {
    const storageRef = ref(storage, `users/${userId}/devices/${deviceRef.id}/screenshot.png`);
    await uploadBytes(storageRef, screenshotFile);
    screenshotUrl = await getDownloadURL(storageRef);
    console.log("Screenshot uploaded");
  }

  // Save device data
  await setDoc(deviceRef, {
    userId,
    name: deviceName,
    os: os,
    screenshotUrl,
    createdAt: new Date(),
    lastScan: null,
    status: "active"
  });

  console.log("Device registered:", deviceRef.id);
  return deviceRef.id;
}

Step 3: Cloud Function Scan Processing

// functions/scanProcessor.js
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

exports.processScan = functions.firestore
  .document("devices/{deviceId}/scans/{scanId}")
  .onCreate(async (snap, context) => {
    const scan = snap.data();
    const { deviceId, scanId } = context.params;

    console.log(`Processing scan ${scanId} for device ${deviceId}`);

    // Simulate threat analysis
    const threatLevel = scan.threats > 0 ? "detected" : "clean";

    // Update scan status
    await snap.ref.update({
      status: "completed",
      threatLevel,
      processedAt: admin.firestore.FieldValue.serverTimestamp()
    });

    // Send notification if threats found
    if (scan.threats > 0) {
      const device = await admin.firestore()
        .collection("devices")
        .doc(deviceId)
        .get();
      const userId = device.data().userId;

      // Get user FCM token
      const user = await admin.firestore()
        .collection("users")
        .doc(userId)
        .get();
      const fcmToken = user.data()?.fcmToken;

      if (fcmToken) {
        await admin.messaging().send({
          token: fcmToken,
          notification: {
            title: "Threat Detected",
            body: `${scan.threats} threats found on ${device.data().name}`
          },
          data: { deviceId, scanId }
        });
        console.log("Notification sent to user");
      }
    }

    console.log(`Scan ${scanId} completed`);
    return null;
  });

Step 4: Hosting and Security Rules

// firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /devices/{deviceId} {
      allow read, write: if request.auth != null
        && request.auth.uid == resource.data.userId;
      match /scans/{scanId} {
        allow read: if request.auth != null
          && request.auth.uid == get(/databases/$(database)/documents/devices/$(deviceId)).data.userId;
      }
    }
  }
}
# Deploy everything
firebase deploy --only hosting,firestore,functions,storage

# Expected output:
# ✔  Deploy complete!
# ✔  Project: durga-antivirus-pro
# ✔  Hosting URL: https://durga-antivirus-pro.web.app

Common Mistakes

1. Scattered Service Initialization

Initialize all Firebase services in a single module. Scattered initialization across files makes it hard to manage dependencies and debug initialization issues.

2. Not Planning Security Rules Early

Adding security rules after the app is built often requires major refactoring. Design the data model and rules together before writing UI code.

3. Ignoring Offline Support

Firestore and Auth work offline by default. Test the app with airplane mode to verify offline behavior and Conflict Resolution.

4. Tight Coupling Between Services

Functions should be independent and idempotent. If a function fails (FCM send fails), it should not break the core data flow (scan processing).

5. Not Monitoring Usage

Set up budget alerts and monitoring for Service Usage in Google Cloud Console before launching to prevent surprise bills.

Practice Questions

  1. How do you architect a Firebase app that uses multiple services?
  2. What is the correct order of initialization for Firebase services?
  3. How do you handle errors across services (e.g., FCM fails but Firestore write succeeded)?
  4. What monitoring should you set up for a production Firebase app?

Answers:

  1. Design the data model and security rules first. Then implement services bottom-up: Storage → Firestore → Functions → Auth → Hosting → FCM → Analytics.
  2. Initialize initializeApp first, then services in dependency order: Auth → Firestore → Storage → Messaging → Analytics.
  3. Use Cloud Functions to orchestrate multi-service operations. Try/Catch each service call and handle failures independently without rolling back successful operations.
  4. Set budget alerts, monitor Firestore usage (reads/writes/storage), monitor Function invocation counts and error rates, enable Crashlytics, and set up Analytics events for key user actions.

Challenge: Build the complete Durga Antivirus Pro dashboard: deploy Auth + Firestore + Storage + Functions + Hosting + FCM + Analytics, write security rules for all services, create a CI/CD pipeline, and monitor usage post-launch.

FAQ

How many Firebase services should a project use?

Use what you need, not everything. Each service adds SDK size and complexity. Start with Auth + Firestore + Hosting, add more as requirements grow.

How do you handle local development with multiple services?

Use Firebase Emulator Suite which supports Auth, Firestore, Functions, Storage, and PubSub emulation in a single local environment.

Can I migrate a Firebase project to a custom backend later?

Yes. Export Firestore data, export Auth users, and rebuild with a backend language of your choice. Plan for this early if vendor lock-in is a concern.

What are the scaling limits for combined Firebase services?

Firestore: 1M concurrent connections, 10K writes/second. Functions: 3000 concurrent invocations. Storage: unlimited. Hosting: 10GB/month free, unlimited with Blaze.

How do you manage costs across multiple Firebase services?

Set budgets in Google Cloud Console, monitor usage daily, use Firestore efficiently (avoid unnecessary reads), and set Function max instances to prevent runaway costs.

Mini Project

Build and deploy the complete Durga Antivirus Pro security dashboard: user auth (email + Google), device registration with Firestore, scan result display with real-time listeners, file upload to Storage, Cloud Function scan processing, FCM notifications, preview channel deployment, and Analytics event tracking.

What's Next

You've completed the Firebase learning path. Explore SendGrid Email API for transactional email, or Twilio SMS API for SMS notifications.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro