# Cache Busting Fix Summary

**Date:** 2026-03-14

## Problem

Team members reported seeing broken styling on the website that required hard refresh (Cmd+Shift+R) to fix. This was caused by browser caching issues.

## Root Causes Identified

1. **Missing Version Parameters**: Critical CSS files (`/dist/output.min.css`, `/src/critical.css`) loaded without cache-busting query strings
2. **Immutable Directive**: `.htaccess` used `Cache-Control: immutable` which prevented browsers from revalidating even when query strings changed
3. **Inconsistent Implementation**: Some files used version parameters correctly, others didn't

## Changes Made

### 1. Fixed Critical CSS Files

**Files Updated:**
- `v2/base/head.php` - Added version parameters to `/dist/output.min.css` and `/src/critical.css`
- `v2/pages/blog/post.php` - Fixed 404 error page CSS includes
- `v2/pages/404.php` - Added version parameter
- `v2/pages/blog/category.php` - Added version parameter
- `v2/pages/event-lead-capture-simple.php` - Added version parameters

**Pattern Applied:**
```php
<?php
$css_path = $_SERVER['DOCUMENT_ROOT'] . '/dist/output.min.css';
$css_version = file_exists($css_path) ? filemtime($css_path) : time();
?>
<link rel="stylesheet" href="/dist/output.min.css?v=<?php echo $css_version; ?>">
```

### 2. Updated Cache Headers

**File:** `.htaccess`

**Change:**
- **Before**: `Cache-Control: public, max-age=31536000, immutable`
- **After**: `Cache-Control: public, max-age=31536000, must-revalidate`

**Why:**
- `immutable` prevented browsers from revalidating even when query strings changed
- `must-revalidate` allows revalidation when query strings change while maintaining long cache
- Query string changes (`?v=old` → `?v=new`) now force fresh fetch

### 3. Created Validation Script

**File:** `v2/scripts/dev-helpers/audit-unversioned-assets.py`

**Purpose:**
- Scans all PHP files for unversioned CSS/JS includes
- Reports file paths, line numbers, and URLs
- Exit code 0 = no issues, 1 = issues found

**Usage:**
```bash
python3 v2/scripts/dev-helpers/audit-unversioned-assets.py
```

### 4. Updated Documentation

**Files Updated:**
- `docs/performance/caching-strategy.md` - Updated cache header strategy, added cache busting requirements
- `docs/development/DEV_TOOLING.md` - Added cache validation script to quick reference
- `.cursor/rules/performance.mdc` - Added cache busting requirements and validation steps
- `docs/development/CACHE_BUSTING_GUIDE.md` - New comprehensive guide

## Testing Completed

### Automated Tests

✅ **Version Parameters Present**
- All critical CSS files have version parameters in HTML output
- Verified: `/dist/output.min.css?v=1773495141`, `/src/critical.css?v=1772479917`

✅ **Version Parameters Update**
- Tested file modification → version parameter updates correctly
- `filemtime()` works as expected

✅ **Cache Keys**
- Different version parameters create different cache entries
- Browsers will fetch new version when query string changes

✅ **PHP Files**
- All critical PHP files include version parameters correctly
- Pattern implemented consistently

**Test Scripts:**
- `php v2/scripts/dev-helpers/test-cache-busting.php` - ✓ Passed
- `./v2/scripts/dev-helpers/test-cache-busting-behavior.sh` - ✓ Passed

### Manual Browser Testing Required

**Before Production Deploy:**

1. **Make a CSS change** (e.g., change a background color)
2. **Load page normally** (soft refresh, not hard refresh)
3. **Verify change appears** without requiring hard refresh
4. **Check DevTools Network tab**:
   - CSS/JS files should have `?v=timestamp` parameter
   - Should show "200" status if version changed
   - Check "Cache-Control" header

**Test Pages:**
- Homepage (`/`)
- Blog posts (`/insights/lexikon/*`, `/insights/ratgeber/*`)
- 404 page (trigger by visiting invalid URL)
- Event lead capture pages

**Browser Compatibility:**
- Chrome (most strict with `immutable`, should now work)
- Firefox (revalidates more aggressively)
- Safari (may have different cache behavior)

**See:** `docs/development/CACHE_BUSTING_TEST_RESULTS.md` for complete test results

## Remaining Issues

### Noscript Tags

Many comparison pages have unversioned CSS in `<noscript>` tags. These are less critical since:
- Only load when JavaScript is disabled (rare)
- Can be fixed incrementally

**To Fix Later:**
- Run audit script to find all instances
- Fix noscript tags in comparison pages (60+ files)
- Pattern: Same as regular CSS includes with version parameter

## Validation

### Pre-Deployment Checklist

- [x] Fixed critical CSS files in `v2/base/head.php`
- [x] Updated `.htaccess` cache headers
- [x] Created validation script
- [x] Updated documentation
- [x] **COMPLETED**: Automated tests passed (version parameters work correctly)
- [x] **COMPLETED**: Verified cache busting behavior (file changes update versions)
- [ ] **PENDING**: Manual browser testing in production (Chrome, Firefox, Safari)

### Run Before Deploying

```bash
# Check for unversioned assets
python3 v2/scripts/dev-helpers/audit-unversioned-assets.py

# Should return exit code 0 (no critical issues)
# Note: May still report noscript tags - these are lower priority
```

## Expected Behavior After Fix

1. **CSS/JS changes appear immediately** without hard refresh
2. **Version parameters update** when files are modified (`filemtime()` changes)
3. **Browsers revalidate** when query strings change
4. **Long cache still works** for unchanged files (performance maintained)

## Rollback Plan

If issues occur:

1. **Revert `.htaccess` change**: Change `must-revalidate` back to `immutable`
2. **Note**: This will bring back the original caching issue
3. **Investigate**: Check if version parameters are working correctly
4. **Fix**: Ensure all critical files have version parameters

## Related Files

- `.htaccess` - Cache headers (lines 45-53)
- `v2/base/head.php` - Critical CSS includes (lines 84, 145)
- `v2/scripts/dev-helpers/audit-unversioned-assets.py` - Validation script
- `docs/development/CACHE_BUSTING_GUIDE.md` - Complete guide
- `docs/performance/caching-strategy.md` - Caching strategy documentation

## Success Criteria

✅ All critical CSS files have version parameters
✅ Cache headers allow revalidation
✅ Validation script catches future issues
✅ Documentation updated

⏳ **Pending**: Browser testing to verify fix works
⏳ **Pending**: Team verification that styling updates without hard refresh
