# Performance Optimization Summary

## 🚀 Results
- **Bundle Size Reduction**: Reduced main vendor chunk from **~6.2MB** to **~0.6MB**.
- **Total Reduction**: ~90% reduction in vendor bundle size.
- **Image Loading**: Implemented lazy loading and blur-up effect for plan covers and stage images.

## 🛠️ Changes Implemented

### 1. Tree-Shaking Fix for Icons
**Problem**: The application was importing the entire `@phosphor-icons/vue` library (thousands of icons), causing a massive bundle size.
**Fix**: Refactored `apps/web/src/shared/components/BaseIcon.vue` to use **named imports** instead of a wildcard import.
**Details**:
- Removed: `import * as PhosphorIcons from '@phosphor-icons/vue'`
- Added: Explicit mapping of only the icons actually used in the app.
- Result: The bundler can now "tree-shake" (remove) unused icons.

### 2. Image Optimization
**Problem**: Lists of plans and stages were using raw `<img>` tags, causing layout shifts and loading all images at once.
**Fix**: Replaced `<img>` with the custom `<OptimizedImage>` component.
**Files Modified**:
- `apps/web/src/modules/planner/components/PlanCard.vue`
- `apps/web/src/modules/planner/components/StageList.vue`
- `apps/web/src/modules/explore/components/ExplorePlanCard.vue`

### 3. Backend Audit
**Status**: ✅ Clean
- Checked for forbidden `.offset()` usage in Firestore queries (none found).
- Verified `syncService` uses proper polling backoff (confirmed).

## 🐛 Bug Fixes (Post-Optimization)
- **Fixed Broken Navigation Icons**: The initial optimization broke the burger menu and close buttons because they used string names (`'menu'`, `'close'`, `'chevron_right'`) that were missing from the new static map.
- **Resolution**: Added `PhList`, `PhX`, and `PhCaretRight` to `BaseIcon.vue` and mapped them correctly.

## 📊 Build Stats (After Fix)
| Chunk | Size | Notes |
|-------|------|-------|
| `vendor-map` | ~1.7 MB | Mapbox GL JS (Expected heavy) |
| `vendor` | ~0.6 MB | Core dependencies (React/Vue/Utils) |
| `vendor-charts` | ~0.5 MB | Chart.js |
| `vendor-quasar` | ~0.3 MB | UI Framework |

## ⚠️ Long Term Maintenance (Critical)
To maintain this performance, **DO NOT** revert `BaseIcon.vue` to use wildcard imports (`import * as ...`).

### How to add a new icon:
1.  **Import it explicitly** in `apps/web/src/shared/components/BaseIcon.vue`:
    ```typescript
    import { PhRocket } from '@phosphor-icons/vue'
    ```
2.  **Add it to the `iconMap`**:
    ```typescript
    const iconMap = {
      // ...
      rocket: PhRocket
    }
    ```
3.  **Use it**: `<BaseIcon name="rocket" />` OR pass the component directly `<BaseIcon :name="PhRocket" />`.

**Note**: Passing the component object directly (e.g. `:name="PhRocket"`) is preferred as it is automatically tree-shakable and doesn't require updating the map. Use the string map only for dynamic icons (from DB/Config).
