# Cache Fix v2 - Permanent Solution **Date:** November 3, 2025 **Status:** ✅ DEPLOYED AND VALIDATED **Version:** 0.1.6 --- ## Problem Summary After deploying Phase 2 (Agent Lightning integration), users experienced: - **Flickering** between old and new content (multiple reloads in quick succession) - **Stale content** persisted even after hard cache clear in private windows - Content would "flash" new version then revert to old version --- ## Root Causes Identified ### 1. **auto-reload.js Causing Reload Loops** Located at `/js/auto-reload.js`, this script listened for two service worker events: ```javascript - 'CACHE_CLEARED' message → triggered reload - 'controllerchange' event → triggered reload ``` **Problem:** Service worker activation would trigger BOTH events, causing: 1. sw-reset.js runs → reloads page 2. New SW installs → sends CACHE_CLEARED → auto-reload.js reloads page 3. New SW takes control → fires controllerchange → auto-reload.js reloads page AGAIN 4. **Result:** 3+ reloads in rapid succession = flickering ### 2. **Critical Files Cached Without Cache-Busting** Files loaded without `?v=` parameters: - `/js/auto-reload.js` - NO cache-busting - `/js/sw-reset.js` - NO cache-busting - `/js/components/umami-tracker.js` - NO cache-busting **Problem:** nginx caches these files for 1 year: ```nginx location ~ ^/(css|js|images|downloads|fonts)/ { expires 1y; add_header Cache-Control "public, max-age=31536000" always; } ``` **Result:** Catch-22 - The script designed to clear caches was itself cached! ### 3. **Service Worker Too Aggressive** Old service worker tried to cache everything: - Cached critical assets on install - Used complex cache-first/network-first strategies - Intercepted fetch requests and served stale cached content - Conflicted with HTTP cache-busting via `?v=` parameters --- ## Permanent Solution Implemented ### Fix #1: Removed Reload Loop Scripts ```bash # Removed from ALL HTML files: - auto-reload.js (was causing multiple reloads) - sw-reset.js (catch-22: itself was cached) ``` ### Fix #2: Simplified Service Worker (v0.1.6) **New minimal service worker:** ```javascript // NO caching at all - let HTTP/nginx handle caching self.addEventListener('fetch', (event) => { return; // Don't intercept - browser handles normally }); ``` **Benefits:** - Service worker ONLY does version checking (no caching) - All requests go directly to nginx → proper HTTP caching works - `?v=timestamp` parameters respected by browsers - No fetch interception = no stale content served from SW cache ### Fix #3: Enhanced nginx Configuration Added explicit location blocks for critical files: ```nginx # Root path - NEVER cache location = / { try_files /index.html @proxy; expires -1; add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always; } # Service worker - NEVER cache (critical for updates) location = /service-worker.js { expires -1; add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always; try_files $uri @proxy; } # Version check file - NEVER cache location = /version.json { expires -1; add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always; try_files $uri @proxy; } # Static files - cache with respect for ?v= parameters location ~ ^/(css|js|images|downloads|fonts)/ { expires 1y; add_header Cache-Control "public, max-age=31536000" always; # When ?v= changes, browser treats as new URL → fetches fresh } ``` --- ## How It Works Now ### Cache Strategy: 1. **HTML files:** Never cached (nginx: `no-store, no-cache`) 2. **service-worker.js:** Never cached (critical for updates) 3. **version.json:** Never cached (for update detection) 4. **JS/CSS files:** Cached for 1 year BUT with `?v=timestamp` parameters - When content changes → timestamp changes → browser fetches new file 5. **Service worker:** Minimal - NO fetch interception, NO caching ### Deployment Flow: 1. Update code → `update-cache-version.js` runs 2. Increments `CACHE_VERSION` in service-worker.js 3. Updates all HTML `?v=` parameters to new timestamp 4. Deploys via rsync 5. nginx reload (automatic in deploy.sh) 6. **Result:** Fresh content served immediately, no reload loops ### User Experience: - Visit site → HTML loaded fresh from nginx (never cached) - JS/CSS with ?v= parameters load (cached if timestamp unchanged) - Service worker activates (minimal, no caching) - No flickering, no reload loops - **One smooth page load with current content** --- ## Verification Commands ```bash # 1. Check HTML is NOT cached curl -I https://agenticgovernance.digital/index.html | grep -i cache # Should show: cache-control: no-store, no-cache, must-revalidate # 2. Check service worker is NOT cached curl -I https://agenticgovernance.digital/service-worker.js | grep -i cache # Should show: cache-control: no-store, no-cache, must-revalidate # 3. Verify service worker version curl -s https://agenticgovernance.digital/service-worker.js | grep CACHE_VERSION # Should show: const CACHE_VERSION = '0.1.6'; # 4. Verify no problematic scripts curl -s https://agenticgovernance.digital/ | grep -E "(auto-reload|sw-reset)" # Should return nothing (exit code 1) # 5. Check Phase 2 content is served curl -s https://agenticgovernance.digital/ | grep "Join the Community" # Should show community section HTML ``` --- ## What Was Removed - ❌ `auto-reload.js` - Removed from all HTML files - ❌ `sw-reset.js` - Removed from all HTML files - ❌ Service worker fetch interception - No longer intercepts requests - ❌ Service worker caching - No longer caches any assets - ❌ CRITICAL_ASSETS caching - Removed from service worker --- ## What Remains - ✅ `version-manager.js` - Registers minimal service worker, shows update notifications - ✅ Service worker - Minimal version for version checking only - ✅ `update-cache-version.js` - Updates ?v= parameters on deployments - ✅ nginx caching - Properly configured with cache-busting support - ✅ Phase 2 content - All Agent Lightning integration content --- ## Future Deployments The deployment process is now robust and permanent: ```bash # Deploy (automatically handles cache-busting) ./scripts/deploy.sh --frontend-only # What happens: # 1. Detects JS/CSS changes # 2. Runs update-cache-version.js # 3. Auto-commits cache version bump # 4. Deploys via rsync # 5. Reloads nginx automatically # 6. Fresh content served immediately ``` **No more:** - ❌ Manual cache clearing - ❌ Hard refresh requirements - ❌ Reload loops - ❌ Flickering between versions - ❌ Stale content after deployments --- ## Technical Details ### Files Modified: - `/home/theflow/projects/tractatus/public/service-worker.js` - Minimal version (v0.1.6) - `/home/theflow/projects/tractatus/public/version.json` - Updated to 0.1.6 - `/home/theflow/projects/tractatus/public/**/*.html` - Removed auto-reload.js and sw-reset.js - `/etc/nginx/sites-available/tractatus` - Added explicit location blocks ### Commits: - Removed auto-reload.js and sw-reset.js from all HTML - Simplified service worker to minimal caching-free version - Enhanced nginx configuration for critical files --- **Result:** ✅ Cache invalidation works reliably, no reload loops, fresh content on every deployment **Status:** Production fix deployed and validated - November 3, 2025