Vector tiles changed web mapping. tippecanoe is the industry-standard generator. This week you take a GeoJSON of 10,000 satellites and produce a smooth, multi-zoom vector tile set.
The TLE catalog has 10,000+ active objects. Plotting them all as GeoJSON in a browser brings any vector renderer to its knees — every feature must be loaded, parsed, indexed, and drawn. Vector tiles solve this elegantly: instead of one giant GeoJSON, you generate a pre-indexed pyramid of small tiles, each containing only the features visible at that zoom and location.
A vector tile is a Protocol Buffers (PBF) file containing a subset of features for a specific (z, x, y) tile address. The pyramid follows the standard slippy-tile convention: z=0 is the entire world in one tile, z=1 splits it into 4 tiles, z=2 into 16, and so on. At z=10, the world is 1,048,576 tiles. Each tile is small (typically 5–50 KB) and the renderer fetches only the tiles in the current viewport.
tippecanoe (now MIT-licensed at github.com/felt/tippecanoe) is the industry-standard generator: it takes a GeoJSON and produces an MBTiles or PMTiles archive. It's a C++ tool you install via Homebrew (brew install tippecanoe) or build from source.
tippecanoe \
-o satellites.pmtiles \
--maximum-zoom=10 \
--minimum-zoom=0 \
--layer=satellites \
--drop-densest-as-needed \
--extend-zooms-if-still-dropping \
satellites.geojson
The key flags:
--minimum-zoom / --maximum-zoom — what zoom range to generate. Generate fewer zooms when your features don't need them.--drop-densest-as-needed — at low zooms, drop the densest features to keep tile size manageable. Essential for large catalogs.--extend-zooms-if-still-dropping — if you're still dropping features at the max zoom, automatically extend.--layer — the layer name inside the tiles. Use it for styling later.MBTiles is the original spec: a SQLite database file containing every tile in the pyramid. Easy to generate, easy to serve via a tile server (martin, TiTiler, mbtileserver), but requires running infrastructure.
PMTiles is the modern improvement: a single file with an internal index that lets HTTP range requests fetch individual tiles directly. No tile server needed — just upload the PMTiles file to S3 (or any HTTP host) and configure the renderer to range-request from the URL. This is the modern default for static deployments.
// MapLibre with PMTiles
const protocol = new pmtiles.Protocol();
maplibregl.addProtocol("pmtiles", protocol.tile);
map.addSource('satellites', {
type: 'vector',
url: 'pmtiles://https://my-bucket.s3.amazonaws.com/satellites.pmtiles'
});
Aim for tiles to be 50 KB or smaller. If a tile is too large, MapLibre's frame rate drops. Strategies:
--include filters in tippecanoe.--simplification to reduce vertex count.You'll download the active CelesTrak satellite catalog (10,000+ TLEs), compute current sub-satellite points for all of them with skyfield, export as GeoJSON, generate vector tiles with tippecanoe across zoom levels 0–10, serve via PMTiles directly from local file system, and render in MapLibre. The result is a smooth, pannable map of every satellite in orbit — at 60 fps even on a 5-year-old laptop.
This is the architecture LaunchDetect uses for the /atlas/ page's spaceport layer (smaller catalog but same pipeline). PMTiles + S3 + CloudFront = no tile server to maintain.
Download the active CelesTrak TLE catalog. Compute current sub-satellite points. Export as GeoJSON. Generate vector tiles with tippecanoe across zoom levels 0–10. Serve via PMTiles and render with MapLibre.
Test yourself. Answer key on the certificate-track page (Gold-tier feature: progress tracking and auto-grading).