# Vector Maps Implementation with MapLibre GL JS & OpenMapTiles

## 🚀 Overview

This implementation uses **MapLibre GL JS** (open-source) with **OpenMapTiles** vector tiles to provide:
- **Better performance** - Vector tiles are smaller and faster
- **Sharp rendering** - Perfect on Retina/HiDPI displays
- **Dynamic styling** - Change colors and styles at runtime
- **Club color integration** - Automatic application of club colors to map elements
- **Custom style support** - Full control via Mapbox GL Style JSON

## 📦 What Was Added

### New Files
- `frontend/src/components/home/VectorMap.tsx` - Main vector map component
- `frontend/src/components/admin/VectorMapStyleSelector.tsx` - Admin UI for vector maps
- `VECTOR_MAPS_IMPLEMENTATION.md` - This documentation

### Dependencies Added
```json
{
  "maplibre-gl": "^4.x.x",
  "@types/maplibre-gl": "^4.x.x"
}
```

## 🎨 Features

### 1. Vector Map Styles

Four professional styles from MapTiler (based on OpenMapTiles):

| Style | Description | Best For |
|-------|-------------|----------|
| **Positron** | Clean light style | Data visualization, colored overlays |
| **Dark Matter** | Sleek dark theme | Modern interfaces, night mode |
| **OSM Bright** | Colorful OSM style | General purpose, vibrant look |
| **Basic** | Simple clean base | Minimal, professional |

### 2. Dynamic Club Color Integration

The vector map automatically applies your club colors to:
- **Marker pins** - Colored with primary club color
- **Water features** - Tinted with club color (subtle)
- **Custom elements** - Can be extended via style JSON

### 3. Custom Style Support

Advanced users can provide custom Mapbox GL Style JSON:

```typescript
<VectorMap 
  customStyleUrl="https://your-server.com/custom-style.json"
  clubPrimaryColor="#e11d48"
  // ... other props
/>
```

## 🛠️ Technical Details

### MapLibre GL JS

**Why MapLibre?**
- ✅ Open-source fork of Mapbox GL JS
- ✅ No vendor lock-in
- ✅ Free for all uses
- ✅ Active community development
- ✅ Compatible with Mapbox styles

### OpenMapTiles

**Data Source:**
- Vector tiles from MapTiler API (free tier available)
- Based on OpenStreetMap data
- Updated regularly
- Global coverage

**Performance:**
- Vector tiles are ~75% smaller than raster tiles
- Smooth zooming and rotation
- Client-side rendering
- GPU acceleration

## 📋 Usage

### Basic Usage

```typescript
import VectorMap from '../components/home/VectorMap';

<VectorMap
  latitude={50.0755}
  longitude={14.4378}
  zoom={15}
  clubName="FK Example"
  address="Example Street 123, Prague"
  mapStyle="positron"
  clubPrimaryColor="#e11d48"
  clubSecondaryColor="#3b82f6"
/>
```

### Props

```typescript
interface VectorMapProps {
  latitude: number;                    // Required
  longitude: number;                   // Required
  zoom?: number;                       // Default: 15
  address?: string;                    // Optional popup content
  clubName?: string;                   // Optional popup content
  mapStyle?: 'positron' | 'dark-matter' | 'osm-bright' | 'klokantech-basic';
  height?: number;                     // Default: 400
  clubPrimaryColor?: string;           // Hex color for marker
  clubSecondaryColor?: string;         // Secondary color
  customStyleUrl?: string;             // Custom Mapbox GL Style JSON URL
}
```

## 🔑 API Key Setup

### For Development
The component includes a demo API key for testing.

### For Production

1. **Get a free API key** from [MapTiler](https://www.maptiler.com/)
   - Sign up (free tier: 100,000 tile requests/month)
   - Copy your API key

2. **Add to environment:**

Create/edit `.env` file:
```bash
REACT_APP_MAPTILER_KEY=your_api_key_here
```

3. **Rebuild the app:**
```bash
npm run build
```

## 🎨 Custom Styling

### Method 1: Modify Built-in Styles

Edit `VectorMap.tsx` and customize the `createCustomPositronStyle` function:

```typescript
const createCustomPositronStyle = (primaryColor?: string, secondaryColor?: string): any => {
  return {
    version: 8,
    name: 'Custom Style',
    sources: { /* ... */ },
    layers: [
      // Add/modify layers here
      {
        id: 'water',
        type: 'fill',
        paint: { 
          'fill-color': yourCustomColor 
        }
      }
    ]
  };
};
```

### Method 2: External Style JSON

Host your custom style JSON and reference it:

```typescript
<VectorMap 
  customStyleUrl="https://your-cdn.com/custom-positron.json"
/>
```

**Style JSON structure** (based on [Mapbox GL Style Spec](https://docs.mapbox.com/mapbox-gl-js/style-spec/)):

```json
{
  "version": 8,
  "name": "Custom Style",
  "sources": {
    "openmaptiles": {
      "type": "vector",
      "url": "https://api.maptiler.com/tiles/v3/tiles.json?key=YOUR_KEY"
    }
  },
  "layers": [
    {
      "id": "background",
      "type": "background",
      "paint": { "background-color": "#f8f8f8" }
    },
    {
      "id": "water",
      "type": "fill",
      "source": "openmaptiles",
      "source-layer": "water",
      "paint": { "fill-color": "#your-color" }
    }
    // ... more layers
  ]
}
```

### Method 3: Fork Positron GL Style

1. Clone the repository:
```bash
git clone https://github.com/openmaptiles/positron-gl-style.git
```

2. Customize `style.json`

3. Host on your server or CDN

4. Reference in your app

## 🎯 Integration with Existing System

### Option 1: Replace Existing Maps

Update imports in your components:

```typescript
// Old
import ContactMap from '../components/home/ContactMap';

// New
import VectorMap from '../components/home/VectorMap';

// Usage stays similar
<VectorMap 
  latitude={lat}
  longitude={lng}
  clubPrimaryColor={settings.primary_color}
  // ... same props
/>
```

### Option 2: Toggle Between Raster/Vector

Create a wrapper component:

```typescript
const AdaptiveMap: React.FC<MapProps> = (props) => {
  const useVector = settings.use_vector_maps; // from settings
  
  return useVector 
    ? <VectorMap {...props} />
    : <ContactMap {...props} />;
};
```

## 📊 Performance Comparison

### Vector Maps (MapLibre GL)
- **Initial Load:** 150-200 KB (tiles + library)
- **Per Zoom:** 20-50 KB (vector tiles)
- **Rendering:** GPU-accelerated
- **Zoom Quality:** Always sharp
- **Customization:** Full runtime control

### Raster Maps (Leaflet)
- **Initial Load:** 100 KB (library only)
- **Per Zoom:** 100-200 KB (PNG tiles)
- **Rendering:** Image-based
- **Zoom Quality:** Pixelated between levels
- **Customization:** Limited to tile source

**Verdict:** Vector maps are faster after initial load and provide better visual quality.

## 🌍 Self-Hosting Tiles (Advanced)

For complete independence from third-party services:

### 1. Set Up OpenMapTiles Server

```bash
# Clone OpenMapTiles
git clone https://github.com/openmaptiles/openmaptiles.git
cd openmaptiles

# Generate tiles for your region
./quickstart.sh czech-republic

# Start tile server
docker-compose up -d
```

### 2. Update VectorMap Component

```typescript
const TILE_SERVER = 'http://your-server.com';

sources: {
  'openmaptiles': {
    type: 'vector',
    url: `${TILE_SERVER}/tiles.json`
  }
}
```

### Benefits of Self-Hosting:
- ✅ No API key required
- ✅ No request limits
- ✅ Full data control
- ✅ Offline capability
- ❌ Requires server maintenance

## 🎨 Club Color Examples

### Red Club (e.g., Slavia Prague)
```typescript
<VectorMap 
  mapStyle="positron"
  clubPrimaryColor="#e11d48"
  clubSecondaryColor="#ffffff"
/>
```
Result: Red markers on light map, subtle red tint on water

### Blue Club (e.g., Slovan Liberec)
```typescript
<VectorMap 
  mapStyle="dark-matter"
  clubPrimaryColor="#3b82f6"
  clubSecondaryColor="#60a5fa"
/>
```
Result: Blue markers on dark map, modern look

### Green Club
```typescript
<VectorMap 
  mapStyle="osm-bright"
  clubPrimaryColor="#16a34a"
  clubSecondaryColor="#fbbf24"
/>
```
Result: Green markers on colorful map

## 🐛 Troubleshooting

### Map Not Loading

**Check browser console for errors:**

1. **API Key Issue:**
```
Error: HTTP 403 - Unauthorized
```
Solution: Add valid `REACT_APP_MAPTILER_KEY` to `.env`

2. **Network Error:**
```
Error: Failed to fetch tiles
```
Solution: Check internet connection, firewall settings

3. **Style Loading Error:**
```
Error: Failed to parse style
```
Solution: Validate your custom style JSON

### Blank Map

- Verify coordinates are valid (lat: -90 to 90, lng: -180 to 180)
- Check zoom level (1-20)
- Ensure API key has not exceeded quota

### Marker Not Visible

- Check `clubPrimaryColor` is a valid color
- Ensure marker color contrasts with map style
- Verify marker is within viewport

### Performance Issues

- Reduce zoom level for overview maps
- Use simpler map style (e.g., 'klokantech-basic')
- Limit number of map instances per page

## 📱 Mobile Optimization

Vector maps are automatically mobile-optimized:

- ✅ Touch gestures (pinch, pan, rotate)
- ✅ Responsive sizing
- ✅ Efficient data loading
- ✅ GPU acceleration on mobile

**Tips:**
- Use lower zoom levels on mobile (12-14 instead of 15-17)
- Consider disabling rotation on mobile
- Test on actual devices, not just desktop browser

## 🔮 Future Enhancements

Potential additions:

1. **Multiple Markers** - Show multiple club locations
2. **Custom Marker Icons** - Use club logo as marker
3. **Heatmaps** - Show fan distribution
4. **3D Buildings** - Add depth to maps
5. **Route Planning** - Show directions to stadium
6. **Catchment Areas** - Draw radius around stadium
7. **Animation** - Animate markers and transitions
8. **Clustering** - Group nearby markers

## 📚 Resources

### Documentation
- [MapLibre GL JS Docs](https://maplibre.org/maplibre-gl-js-docs/)
- [Mapbox GL Style Spec](https://docs.mapbox.com/mapbox-gl-js/style-spec/)
- [OpenMapTiles Schema](https://openmaptiles.org/schema/)
- [Positron GL Style](https://github.com/openmaptiles/positron-gl-style)

### Tools
- [Maputnik Style Editor](https://maputnik.github.io/) - Visual style editor
- [MapTiler Cloud](https://www.maptiler.com/) - Hosted tiles
- [OpenMapTiles](https://openmaptiles.org/) - Self-hosted solution

### Examples
- [MapLibre Examples](https://maplibre.org/maplibre-gl-js-docs/example/)
- [Vector Tile Style Gallery](https://openmaptiles.org/styles/)

## ✅ Checklist for Production

- [ ] Obtain MapTiler API key
- [ ] Add `REACT_APP_MAPTILER_KEY` to `.env`
- [ ] Test all map styles
- [ ] Verify club colors are applied correctly
- [ ] Test on mobile devices
- [ ] Check performance with browser DevTools
- [ ] Monitor API usage in MapTiler dashboard
- [ ] Consider self-hosting for high-traffic sites
- [ ] Add error boundaries for graceful failures
- [ ] Document custom styles if used

## 🎯 Migration Path

### Phase 1: Parallel Run (Recommended)
- Keep existing Leaflet maps
- Add vector maps as opt-in feature
- A/B test with users
- Monitor performance and feedback

### Phase 2: Gradual Rollout
- Enable vector maps for new features
- Offer toggle in admin settings
- Migrate high-traffic pages first

### Phase 3: Full Migration
- Default to vector maps
- Keep raster maps as fallback
- Remove Leaflet dependency

---

**Implementation Date:** 2025-10-10  
**Technology:** MapLibre GL JS 4.x + OpenMapTiles  
**License:** Open Source (BSD-3-Clause)  
**Status:** ✅ Ready for Integration
