Overview
The SmartProductSync system is a sophisticated real-time catalog synchronization engine that provides instant product loading using localStorage cache while maintaining real-time updates from Firestore.
Architecture
Dual-Mode Strategy Instant Load : Products load immediately from localStorage cache
Real-Time Updates : Firebase onSnapshot provides delta updates only for changed products
Implementation
The SmartProductSync is defined in public/js/app.js:12-113:
const SmartProductSync = {
STORAGE_KEY: 'pixeltech_master_catalog' ,
isListening: false ,
async init () {
// 1. Instant cache load
const localData = localStorage . getItem ( this . STORAGE_KEY );
let lastSyncTime = 0 ;
if ( localData ) {
const parsed = JSON . parse ( localData );
runtimeProductsMap = parsed . map || {};
lastSyncTime = parsed . lastSync || 0 ;
allProductsCache = Object . values ( runtimeProductsMap );
}
// 2. Start real-time connection
this . listenForUpdates ( lastSyncTime );
return true ;
}
}
Key Features
1. Offline-First Caching
Products are stored in localStorage with the key pixeltech_master_catalog:
{
map : { [ productId ]: productData },
lastSync : 1234567890 // Timestamp
}
On first load, the catalog appears instantly from cache without waiting for Firebase.
2. Delta Updates with onSnapshot
The sync system uses Firestore’s onSnapshot to listen only for changes since the last sync:
listenForUpdates ( lastSyncTime ) {
let q ;
if ( lastSyncTime === 0 ) {
// First-time user: Download all active products
q = query ( collectionRef , where ( "status" , "==" , "active" ));
} else {
// Returning user: Listen only for updates since last visit
q = query ( collectionRef , where ( "updatedAt" , ">" , new Date ( lastSyncTime )));
}
onSnapshot ( q , ( snapshot ) => {
snapshot . docChanges (). forEach ( change => {
// Process only changed documents
});
});
}
3. Change Detection
The system analyzes document changes to minimize resource usage:
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 ];
}
});
Instant Load Products appear in ~50ms from localStorage
Bandwidth Savings Only downloads changed products (delta sync)
Always Fresh Real-time updates for price/stock changes
State Persistence
The system automatically saves state after each update:
saveState () {
const state = {
map: runtimeProductsMap ,
lastSync: Date . now ()
};
localStorage . setItem ( this . STORAGE_KEY , JSON . stringify ( state ));
}
UI Updates
When the catalog updates, a global event is dispatched:
window . dispatchEvent ( new Event ( 'catalogUpdated' ));
Components listen for this event to re-render with updated prices/stock:
window . addEventListener ( 'catalogUpdated' , () => {
// Refresh product grids, cards, etc.
refreshAllGrids ();
});
Usage Example
Initialize the sync system on page load:
// In app.js initialization
await SmartProductSync . init ();
loadPromoSlider ();
loadBestSellers ();
Error Handling
If localStorage quota is exceeded, the cache won’t persist but the app continues functioning with live data.
try {
localStorage . setItem ( this . STORAGE_KEY , JSON . stringify ( state ));
} catch ( e ) {
console . warn ( "⚠️ Quota exceeded. Cache won't persist." );
}
Best Practices
Always initialize before loading UI components
Listen for catalogUpdated events in dynamic components
Handle cache corruption gracefully with try-catch
Update updatedAt timestamps in Firestore when products change