Skip to main content

Platform Overview

PixelTech Colombia is a modern e-commerce platform built entirely on Firebase, designed for high performance and real-time synchronization. The architecture leverages Firebase services for a serverless, scalable solution optimized for the Colombian retail market.

Technology Stack

Frontend

  • Vanilla JavaScript (ES6+)
  • Tailwind CSS
  • Firebase SDK 10.7.1
  • Service Workers (PWA)

Backend

  • Cloud Functions (Node.js 24)
  • Firestore (NoSQL Database)
  • Firebase Authentication
  • Cloud Storage

Integrations

  • MercadoPago API
  • ADDI API
  • Sistecrédito API
  • WhatsApp Business API
  • Nodemailer (SMTP)

Firebase Services Architecture

The platform uses five core Firebase services working together:

1. Firebase Authentication

Purpose: User authentication and authorization Sign-in Methods:
  • Email/Password authentication
  • Google OAuth provider
  • Anonymous authentication for guest checkouts
User Roles:
Role-based Access Control
// User document structure in Firestore
{
  "uid": "user_firebase_uid",
  "email": "[email protected]",
  "role": "admin" | "customer",
  "displayName": "John Doe",
  "createdAt": Timestamp,
  "photoURL": "https://..."
}
Implementation: Authentication state is managed globally in public/js/firebase-init.js and checked on every page load through onAuthStateChanged listeners.

2. Cloud Firestore (Database)

Purpose: Real-time NoSQL database for all application data Collections Structure:
firestore
├── products/              # Product catalog
│   ├── {productId}
│   └── history/          # Price & stock history (subcollection)
├── users/                # Customer accounts
│   ├── {userId}
│   └── addresses/        # Saved shipping addresses (subcollection)
├── orders/               # Customer orders
├── categories/           # Product categories
├── brands/               # Product brands
├── config/               # Store configuration
│   ├── system           # General settings
│   └── shipping         # Shipping rules
├── warranties/           # Product warranties
├── remissions/           # Delivery notes
├── suppliers/            # Supplier management
├── purchases/            # Purchase orders
├── expenses/             # Business expenses
├── accounts/             # Account management
├── payables/             # Accounts payable
└── chats/                # WhatsApp conversations
    └── messages/         # Chat messages (subcollection)
```text

**Data Model Examples**:

<CodeGroup>
```javascript Product Document
// products/{productId}
{
  "id": "iphone-15-pro-max",
  "name": "iPhone 15 Pro Max",
  "brand": "Apple",
  "category": "smartphones",
  "price": 5499000,
  "originalPrice": 5999000,
  "stock": 10,
  "status": "active", // "active" | "inactive" | "out_of_stock"
  "description": "Latest iPhone with titanium design",
  "mainImage": "https://storage.googleapis.com/.../main.jpg",
  "images": ["url1", "url2", "url3"],
  "colors": ["Natural Titanium", "Blue Titanium"],
  "capacities": ["256GB", "512GB", "1TB"],
  "combinations": [
    {
      "color": "Natural Titanium",
      "capacity": "256GB",
      "stock": 5,
      "sku": "IPH15PM-NT-256"
    }
  ],
  "tags": ["flagship", "5g", "premium"],
  "warranty": 12,
  "createdAt": Timestamp,
  "updatedAt": Timestamp,
  "last_updated": Timestamp // Auto-updated by Cloud Function
}
```text

```javascript Order Document
// orders/{orderId}
{
  "orderId": "ORD-2024-03-001",
  "userId": "firebase_uid",
  "status": "pending", // pending | confirmed | shipped | delivered | cancelled
  "paymentStatus": "PENDING_PAYMENT", // PENDING_PAYMENT | PAID | FAILED | REFUNDED
  "paymentMethod": "mercadopago", // mercadopago | addi | sistecredito | cod
  "items": [
    {
      "id": "product_id",
      "name": "Product Name",
      "price": 100000,
      "quantity": 2,
      "color": "Black",
      "capacity": "128GB",
      "mainImage": "url"
    }
  ],
  "subtotal": 200000,
  "shippingCost": 15000,
  "total": 215000,
  "shippingInfo": {
    "name": "Customer Name",
    "phone": "+573001234567",
    "address": "Calle 123 #45-67",
    "city": "Bogotá",
    "department": "Cundinamarca",
    "postalCode": "110111",
    "notes": "Delivery instructions"
  },
  "tracking": {
    "carrier": "Servientrega",
    "trackingNumber": "1234567890",
    "estimatedDelivery": Timestamp
  },
  "mercadopagoId": "mp_preference_id",
  "createdAt": Timestamp,
  "updatedAt": Timestamp
}
```text

```javascript Config Document
// config/system
{
  "storeName": "PixelTech Colombia",
  "storeEmail": "[email protected]",
  "storePhone": "+57 300 1234567",
  "currency": "COP",
  "taxRate": 0.19,
  "cacheVersion": 1, // Increment to force client cache clear
  "freeShippingThreshold": 150000,
  "enableWhatsApp": true,
  "whatsappNumber": "+573001234567",
  "maintenanceMode": false
}
</CodeGroup>

### 3. Cloud Storage

**Purpose**: Store product images, warranties, invoices, and chat attachments

**Storage Structure**:
```text
storage
├── products/           # Product images
│   └── {productId}/
│       ├── main.jpg
│       └── gallery/
├── warranties/         # Warranty documents
│   └── {orderId}/
├── warranty_reports/   # Technical reports
├── invoices/           # PDF invoices
├── banners/            # Homepage banners
├── categories/         # Category images
├── brands/             # Brand logos
└── chats/              # WhatsApp attachments
```text

**Security Rules**: Public read for products/banners, authenticated write for all uploads.

### 4. Cloud Functions

**Purpose**: Serverless backend for payments, notifications, and automation

**Function Architecture** (from `functions/index.js`):

```javascript Payment Functions
// MercadoPago Integration
exports.createMercadoPagoPreference = functions.https.onCall(...);
exports.mercadoPagoWebhook = functions.https.onRequest(...);

// ADDI Buy Now Pay Later
exports.createAddiCheckout = functions.https.onCall(...);
exports.addiWebhook = functions.https.onRequest(...);

// Sistecrédito
exports.createSistecreditoCheckout = functions.https.onCall(...);
exports.sistecreditoWebhook = functions.https.onRequest(...);

// Cash on Delivery
exports.createCODOrder = functions.https.onCall(...);
Notification Functions
// Email notifications via Nodemailer
exports.sendOrderConfirmation = emailModule.sendOrderConfirmation;
exports.sendDispatchNotification = emailModule.sendDispatchNotification;

// WhatsApp Business API
exports.whatsappWebhook = whatsappModule.webhook;
exports.sendWhatsappMessage = whatsappModule.sendMessage;
Automated Tasks
// Scheduled maintenance (runs every 24 hours)
exports.cleanupOldOrders = onSchedule("every 24 hours", ...);
exports.processScheduledTransfers = schedulerModule.processScheduledTransfers;
exports.cancelAbandonedPayments = schedulerModule.cancelAbandonedPayments;
exports.checkExpiredPromotions = schedulerModule.checkExpiredPromotions;
Triggers & Utilities
// Firestore trigger: Auto-update product timestamps
exports.touchProductTimestamp = onDocumentWritten("products/{productId}", ...);

// Google Merchant Center feed
exports.generateProductFeed = merchantModule.generateProductFeed;

// Dynamic sitemap generation
exports.sitemap = sitemapModule.sitemap;
Key Function Modules:
ModuleFilePurpose
MercadoPagofunctions/mercadopago.jsPayment processing and webhooks
ADDIfunctions/addi.jsBuy now pay later integration
Sistecréditofunctions/sistecredito.jsCredit payment gateway
CODfunctions/cod.jsCash on delivery orders
Emailsfunctions/emails.jsOrder confirmation and shipping notifications
WhatsAppfunctions/whatsapp.jsCustomer service automation
Schedulerfunctions/scheduler.jsAutomated maintenance tasks
Syncfunctions/sync.jsProduct timestamp management
Google Merchantfunctions/google-merchant.jsProduct feed for Google Shopping
Sitemapfunctions/sitemap.jsSEO sitemap generation

5. Firebase Hosting

Purpose: Host the frontend application with CDN distribution Configuration (firebase.json):
firebase.json
{
  "hosting": {
    "public": "public",
    "rewrites": [
      {
        "source": "/sitemap.xml",
        "function": "sitemap"
      },
      {
        "source": "/google-feed.xml",
        "function": "generateProductFeed"
      },
      {
        "source": "**",
        "destination": "/index.html"
      }
    ],
    "headers": [
      {
        "source": "**",
        "headers": [
          {
            "key": "Content-Security-Policy",
            "value": "default-src 'self' https: data: blob: 'unsafe-inline' 'unsafe-eval'"
          }
        ]
      }
    ]
  }
}
Features:
  • Single Page Application (SPA) routing
  • Dynamic sitemap via Cloud Function
  • Google Merchant feed integration
  • Content Security Policy headers
  • CDN caching and SSL certificates

Frontend Architecture

Smart Sync System

The platform’s core innovation is the Smart Sync system - an intelligent real-time caching mechanism that minimizes Firestore reads while keeping data fresh. How it Works (public/js/app.js):
Smart Sync Architecture
const SmartProductSync = {
    STORAGE_KEY: 'pixeltech_master_catalog',
    
    async init() {
        // 1. Instant load from localStorage (0ms)
        const localData = localStorage.getItem(this.STORAGE_KEY);
        if (localData) {
            const parsed = JSON.parse(localData);
            runtimeProductsMap = parsed.map || {};
            lastSyncTime = parsed.lastSync || 0;
            console.log(`📂 Loaded ${Object.keys(runtimeProductsMap).length} products from cache`);
        }

        // 2. Listen for updates since last sync
        this.listenForUpdates(lastSyncTime);
    },

    listenForUpdates(lastSyncTime) {
        const collectionRef = collection(db, "products");
        let q;

        // CASE 1: First visit -> Download all active products
        if (lastSyncTime === 0) {
            q = query(collectionRef, where("status", "==", "active"));
        } 
        // CASE 2: Returning user -> Listen ONLY for changes since last visit
        else {
            q = query(collectionRef, where("updatedAt", ">", new Date(lastSyncTime)));
        }

        onSnapshot(q, (snapshot) => {
            snapshot.docChanges().forEach(change => {
                const data = change.doc.data();
                const id = change.doc.id;

                if (change.type === 'added' || change.type === 'modified') {
                    if (data.status === 'active') {
                        runtimeProductsMap[id] = { id, ...data };
                    } else {
                        delete runtimeProductsMap[id];
                    }
                } else if (change.type === 'removed') {
                    delete runtimeProductsMap[id];
                }
            });

            // Save to localStorage and trigger UI update
            this.saveState();
            window.dispatchEvent(new Event('catalogUpdated'));
        });
    },

    saveState() {
        const state = {
            map: runtimeProductsMap,
            lastSync: Date.now()
        };
        localStorage.setItem(this.STORAGE_KEY, JSON.stringify(state));
    }
};
Benefits:
  • Instant load: Products appear in under 50ms from cache
  • Minimal reads: Only downloads changes since last visit
  • Real-time updates: Listens for price/stock changes
  • Offline-first: Works without network connection
  • Cost-effective: Reduces Firestore reads by ~95%

Cache Invalidation

Global cache clearing mechanism (public/js/firebase-init.js):
Cache Version Control
export async function checkCacheVersion(db) {
    const configRef = doc(db, "config", "system");
    const snap = await getDoc(configRef);
    
    if (snap.exists()) {
        const serverVersion = snap.data().cacheVersion || 1;
        const localVersion = parseInt(localStorage.getItem('pixeltech_cache_version') || '0');

        // If server version is higher, clear all caches
        if (serverVersion > localVersion) {
            console.warn(`🔄 New version detected (v${serverVersion}). Clearing cache...`);
            
            Object.keys(localStorage).forEach(key => {
                if (key.includes('pixeltech_')) {
                    localStorage.removeItem(key);
                }
            });
            
            localStorage.setItem('pixeltech_cache_version', serverVersion.toString());
            window.location.reload(true);
        }
    }
}
Usage: Increment cacheVersion in Firestore config/system to force all clients to refresh their cache.

Component Structure

Modular JavaScript Files:
FilePurpose
firebase-init.jsFirebase SDK initialization and exports
app.jsSmart Sync engine and global state
cart.jsShopping cart management
checkout.jsCheckout flow and payment processing
catalog.jsProduct listing and filtering
product-detail.jsProduct page with variant selection
auth-logic.jsAuthentication UI and flows
profile.jsUser profile and order history
admin-*.jsAdmin panel modules
Global Components (public/js/global-components.js):
  • Search modal with instant results
  • Shopping cart drawer
  • Product quick view modal
  • Variant selector (color/capacity)
  • Toast notifications

Progressive Web App (PWA)

Service Worker (public/service-worker.js):
  • Offline catalog caching
  • Background sync for orders
  • Push notification support
  • Asset precaching
Manifest (public/manifest.json):
  • Installable on mobile devices
  • Splash screens and icons
  • Standalone app experience

Backend Architecture

Cloud Functions Structure

Payment Processing Flow: Example: MercadoPago Flow (functions/mercadopago.js):
MercadoPago Integration
exports.createPreference = async (data, context) => {
    // 1. Authenticate user
    const uid = context.auth.uid;
    
    // 2. Validate cart items against DB prices (security)
    for (const item of data.items) {
        const pDoc = await db.collection('products').doc(item.id).get();
        const realPrice = pDoc.data().price;
        // Use realPrice, not client-provided price
    }
    
    // 3. Create order in Firestore with PENDING_PAYMENT status
    const orderRef = await db.collection('orders').add({
        userId: uid,
        items: validatedItems,
        total: calculatedTotal,
        status: 'pending',
        paymentStatus: 'PENDING_PAYMENT',
        createdAt: admin.firestore.Timestamp.now()
    });
    
    // 4. Create MercadoPago preference
    const preference = await client.preference.create({
        items: mpItems,
        external_reference: orderRef.id,
        notification_url: WEBHOOK_URL,
        expires: true,
        expiration_date_from: now,
        expiration_date_to: now + 30 minutes
    });
    
    // 5. Return checkout URL
    return { 
        orderId: orderRef.id, 
        checkoutUrl: preference.init_point 
    };
};

exports.webhook = async (req, res) => {
    // 1. Verify webhook signature
    // 2. Get payment status from MercadoPago
    const payment = await client.payment.get(paymentId);
    
    // 3. Update order status
    await db.collection('orders').doc(orderId).update({
        paymentStatus: payment.status === 'approved' ? 'PAID' : 'FAILED',
        status: payment.status === 'approved' ? 'confirmed' : 'cancelled',
        mercadopagoPaymentId: paymentId
    });
    
    // 4. Trigger email notification (Firestore trigger)
    // sendOrderConfirmation function automatically fires
    
    res.status(200).send('OK');
};
Email Notifications (functions/emails.js):
Email Triggers
exports.sendOrderConfirmation = onDocumentCreated(
    "orders/{orderId}", 
    async (event) => {
        const order = event.data.data();
        
        // Generate beautiful HTML email
        const html = getBeautifulEmailTemplate('CONFIRMATION', order);
        
        // Send via Nodemailer
        await transporter.sendMail({
            from: process.env.SMTP_EMAIL,
            to: order.shippingInfo.email,
            subject: `Pedido Confirmado #${orderId}`,
            html: html
        });
    }
);

exports.sendDispatchNotification = onDocumentUpdated(
    "orders/{orderId}",
    async (change) => {
        const before = change.data.before.data();
        const after = change.data.after.data();
        
        // Only send if status changed to 'shipped'
        if (before.status !== 'shipped' && after.status === 'shipped') {
            const html = getBeautifulEmailTemplate('DISPATCH', after);
            await transporter.sendMail({...});
        }
    }
);

Scheduled Tasks

Automated maintenance with Cloud Scheduler (functions/scheduler.js):
Scheduled Functions
exports.cleanupOldOrders = onSchedule("every 24 hours", async (event) => {
    // Delete orders older than 90 days with status 'cancelled'
    const cutoff = new Date();
    cutoff.setDate(cutoff.getDate() - 90);
    
    const snapshot = await db.collection('orders')
        .where('status', '==', 'cancelled')
        .where('createdAt', '<', cutoff)
        .get();
    
    const batch = db.batch();
    snapshot.docs.forEach(doc => batch.delete(doc.ref));
    await batch.commit();
    
    console.log(`🗑️ Deleted ${snapshot.size} old orders`);
});

exports.cancelAbandonedPayments = async () => {
    // Find orders pending payment for >30 minutes
    const cutoff = new Date(Date.now() - 30 * 60 * 1000);
    
    const snapshot = await db.collection('orders')
        .where('paymentStatus', '==', 'PENDING_PAYMENT')
        .where('createdAt', '<', cutoff)
        .get();
    
    // Cancel and restore stock
    for (const doc of snapshot.docs) {
        await doc.ref.update({ status: 'cancelled' });
        // Restore inventory...
    }
};

Security Model

Firestore Security Rules

Core Principles:
  1. Defense in depth: Validate on client AND server
  2. Role-based access: Admin vs Customer permissions
  3. Data validation: Ensure required fields exist
  4. Owner isolation: Users can only access their own data
Key Rules (firestore.rules):
function isAdmin() {
  return request.auth != null && 
    exists(/databases/$(database)/documents/users/$(request.auth.uid)) &&
    get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin';
}

function isOwner(userId) {
  return request.auth != null && request.auth.uid == userId;
}

function isAuthenticated() {
  return request.auth != null;
}
Storage Security Rules (storage.rules):
Storage Security
service firebase.storage {
  match /b/{bucket}/o {
    // Products: Public read, authenticated write
    match /products/{allPaths=**} {
      allow read: if true;
      allow write: if request.auth != null;
    }
    
    // Warranties: Only for authenticated users
    match /warranties/{orderId}/{fileName} {
      allow read, write: if request.auth != null;
    }
    
    // Invoices: Only authenticated users
    match /invoices/{fileName} {
      allow read, write: if request.auth != null;
    }
  }
}

API Security

Cloud Functions Authentication:
Function Security
// Callable functions automatically include context.auth
exports.createMercadoPagoPreference = functions.https.onCall(
    async (data, context) => {
        // Verify user is authenticated
        if (!context.auth) {
            throw new functions.https.HttpsError(
                'unauthenticated', 
                'User must be logged in'
            );
        }
        
        const uid = context.auth.uid;
        // ... process with uid
    }
);

// HTTP functions require manual verification
exports.mercadoPagoWebhook = functions.https.onRequest(
    async (req, res) => {
        // Verify webhook signature
        const signature = req.headers['x-signature'];
        if (!verifyWebhookSignature(signature, req.body)) {
            return res.status(403).send('Invalid signature');
        }
        // ... process webhook
    }
);

Data Flow

Customer Purchase Flow

1. Browse Products
   ↓ [Smart Sync loads from cache + listens for updates]
2. Add to Cart
   ↓ [localStorage + UI update]
3. Checkout
   ↓ [Authenticate with Firebase Auth]
4. Select Payment
   ↓ [Call Cloud Function]
5. Payment Gateway
   ↓ [External API: MercadoPago/ADDI/etc]
6. Webhook Callback
   ↓ [Cloud Function updates order]
7. Email Notification
   ↓ [Firestore trigger sends email]
8. Order Confirmed
   ↓ [User dashboard updates]

Admin Order Management Flow

1. View Orders
   ↓ [Real-time Firestore listener]
2. Update Status
   ↓ [Firestore update with validation]
3. Add Tracking Info
   ↓ [Update order document]
4. Trigger Notification
   ↓ [Cloud Function detects status change]
5. Send Dispatch Email
   ↓ [Nodemailer + tracking link]
6. Customer Notified
   ↓ [Email + WhatsApp optional]

Real-time Inventory Sync

Product Updated (Admin Panel)

Firestore Write

touchProductTimestamp Cloud Function

Update 'updatedAt' field

Smart Sync Listener (All Connected Clients)

Update Local Cache

Dispatch 'catalogUpdated' Event

UI Re-renders with New Data

Performance Optimizations

Smart Sync Cache

95% reduction in Firestore reads through intelligent localStorage caching

Lazy Loading

Images load on-demand with IntersectionObserver for fast initial page load

Code Splitting

Separate JS files for admin/customer flows to reduce bundle size

CDN Hosting

Firebase Hosting distributes assets globally with edge caching

Service Worker

Offline-first PWA with asset caching and background sync

Firestore Indexes

Optimized compound indexes for fast complex queries

Scalability

Current Architecture Supports:
  • Products: Unlimited (tested with 10,000+ items)
  • Orders: Unlimited with automatic archival
  • Concurrent Users: 10,000+ (Firebase scales automatically)
  • Traffic: Handles Colombian retail peak seasons
Scaling Considerations:
  • Use Firestore subcollections for large nested data
  • Implement pagination for large result sets
  • Archive old orders to separate collection
  • Use Firestore composite indexes for complex queries
  • Keep functions warm with scheduled pings
  • Use minimum instances (paid feature) for critical functions
  • Optimize function bundle size
  • Use Node.js 24 for better performance
  • Compress images before upload (max 1200x1200)
  • Use Firebase Storage CDN caching
  • Implement image optimization pipeline
  • Delete unused files regularly
  • Smart Sync reduces reads by 95%
  • Use cache-first strategies
  • Implement pagination for admin panels
  • Aggregate data in summary documents

Monitoring & Debugging

Firebase Console

Monitor usage, performance, and costs in real-time

Cloud Functions Logs

View function execution logs with firebase functions:log

Performance Monitoring

Track page load times and API latency automatically

Crashlytics

Monitor frontend errors and crashes
The architecture is designed for Colombian e-commerce at scale - handling multiple payment methods, real-time inventory across channels, and seamless customer experience.

Next Steps

Quickstart Guide

Deploy your own PixelTech store

Payment Integrations

Configure MercadoPago, ADDI, and more

Admin Features

Explore the admin dashboard capabilities

API Reference

Cloud Functions API documentation

Build docs developers (and LLMs) love