Skip to content

Tile Providers

Yoro works with any map tile provider. This guide shows how to configure different tile sources for various use cases.

Quick Reference

Best for general use. Free, no API key needed.

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '© OpenStreetMap contributors',
    maxZoom: 19,
}).addTo(map);

Free satellite imagery. Great for verifying parcel boundaries.

L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
    attribution: '© Esri, Maxar, Earthstar Geographics',
    maxZoom: 18,
}).addTo(map);

Free topographic map. Useful for altitude and terrain context.

L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
    attribution: '© OpenTopoMap',
    maxZoom: 17,
}).addTo(map);

Minimal light theme. Excellent for data overlays and the Yoro grid.

L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
    attribution: '© CARTO',
    maxZoom: 20,
}).addTo(map);

Complete Example: Multi-Layer Map

A full example with layer switching — ideal for field applications:

<!DOCTYPE html>
<html>
<head>
    <title>Yoro Multi-Layer Map</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9/dist/leaflet.css" />
    <style>
        body { margin: 0; }
        #map { height: 100vh; }
    </style>
</head>
<body>
<div id="map"></div>
<script src="https://unpkg.com/leaflet@1.9/dist/leaflet.js"></script>
<script>
    // Base layers
    const osm = L.tileLayer(
        'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
        { attribution: '&copy; OSM', maxZoom: 19 }
    );
    const satellite = L.tileLayer(
        'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
        { attribution: '&copy; Esri', maxZoom: 18 }
    );
    const topo = L.tileLayer(
        'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',
        { attribution: '&copy; OpenTopoMap', maxZoom: 17 }
    );
    const light = L.tileLayer(
        'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png',
        { attribution: '&copy; CARTO', maxZoom: 20 }
    );

    // Initialize with OSM
    const map = L.map('map', {
        center: [7.5, -5.5],
        zoom: 7,
        layers: [osm],
    });

    // Layer control
    L.control.layers({
        'OpenStreetMap': osm,
        'Satellite': satellite,
        'Topographic': topo,
        'Light': light,
    }).addTo(map);
</script>
</body>
</html>

Choosing the Right Tiles

Use Case Provider Why
General navigation OpenStreetMap Free, detailed roads/buildings
Parcel verification ESRI Satellite See actual land, trees, buildings
Terrain analysis OpenTopoMap Elevation contours, slopes
Data visualization CartoDB Positron Clean background for Yoro grid
Offline/field use MBTiles Pre-downloaded, no internet needed

Offline Tiles (MBTiles)

For field agents without internet connectivity, pre-download tiles as MBTiles:

# In your Django app, serve offline tiles
# Store .mbtiles files and serve via a tile proxy view

from django.http import HttpResponse
import sqlite3

def offline_tile(request, z, x, y):
    """Serve tiles from a local .mbtiles file."""
    y_tms = (1 << z) - 1 - y  # TMS to XYZ conversion

    conn = sqlite3.connect('/path/to/region.mbtiles')
    cursor = conn.execute(
        'SELECT tile_data FROM tiles WHERE zoom_level=? AND tile_column=? AND tile_row=?',
        (z, x, y_tms)
    )
    row = cursor.fetchone()
    conn.close()

    if row:
        return HttpResponse(row[0], content_type='image/png')
    return HttpResponse(status=404)

Then in Leaflet:

const offlineTiles = L.tileLayer('/tiles/{z}/{x}/{y}.png', {
    maxZoom: 16,
    attribution: 'Offline tiles',
});

Combining Yoro with offline maps

Yoro codes are computed purely from math — they work offline without any API call. Combined with pre-downloaded MBTiles, field agents can use the full addressing system with zero connectivity.

Satellite Imagery for EUDR

For EUDR (EU Deforestation Regulation) compliance, satellite imagery is critical to verify that parcels are not on deforested land:

// NICFI Planet basemaps (free for tropical forests, requires signup)
// https://www.planet.com/nicfi/
const nicfi = L.tileLayer(
    'https://tiles.planet.com/basemaps/v1/planet-tiles/planet_medres_normalized_analytic_{period}_mosaic/gmap/{z}/{x}/{y}.png?api_key={key}',
    {
        attribution: '&copy; Planet Labs',
        maxZoom: 17,
        period: '2024-01',  // Monthly mosaics available
        key: 'YOUR_NICFI_API_KEY',
    }
);

This lets you overlay Yoro codes on satellite imagery to visually verify each parcel's forest status.