Geocode the camps of Black Rock City. Takes the official Burning Man placement PDF and the camp roster JSON, walks you through some interactive corrections, and emits two enriched JSON files that pair each camp with its real-world location on the playa.
For every camp in camps.json that could be matched to a polygon on the map,
the camp's location object gains:
-
location.centroid— a GeoJSONPointthat indicates where the camp should be indicated on a map for navigation. This might be at the center of the frontage, or at a corner for a corner camp. In some cases where camps have weird shapes, the centroid just ends up at the geographical center of the camp."centroid": { "type": "Point", "coordinates": [-119.21450503439554, 40.77861635238121] }
-
location.border— a GeoJSONPolygonoutlining the camp's footprint:"border": { "type": "Polygon", "coordinates": [[[-119.2142, 40.7785], [-119.2143, 40.7784], ...]] }
Two output files are written:
2025/camps-geocoded.json— camps +centroidonly.2025/camps-geocoded-with-borders.json— camps +centroid+border.
Camps that don't appear on the map come through unchanged (no centroid, no border) in both files.
We use two input files:
2025/input.pdf— the official BRC placement map2025/camps.json— the camp roster as an array of objects, from the Burning Man API
Data for each year of burning man is only released to the public when the gate opens. If you need earlier access to build your app and have it ready in time for the burn, join the org's Innovate community -- you will have to sign a nondisclosure agreement.
npm installRequires Node ≥ 18 (uses native ES modules).
npm startThen open http://localhost:3000.
The server extracts the four target layers from input.pdf at startup
(takes a few seconds for the full city) and serves the interactive app from a
single page.
A compass in the top-right toggles between 12:00-up (the PDF's native orientation) and true-north-up.
- Pan: drag with the left mouse button.
- Zoom: mouse wheel or trackpad pinch.
- Fit to window: 0 or f.
- Toggle orientation: click the compass icon in the top-right.
- Hover a camp: tooltip shows the camp's name (bold),
location_string,dimensions, andexact_locationfrom the roster.
The app guides you through the calibration steps in order. A status bar at the bottom left corner prompts for each one.
-
Set the Golden Spike. Click
YES, then aim at the dead center of the man and press Enter (red guides snap to the BRC clock-face radials to help you align). Confirm withACCEPT. -
Calibrate the map scale. Translucent green BRC streets are overlaid on top of the PDF. Use + / − to grow/shrink them and < / > to refine/coarsen the step size until the green rings sit on the actual streets. Press Enter to accept.
-
Enter the spike's lat/lon. Paste the published coordinates of the Golden Spike for the current year (e.g.
40.786958, -119.202994). Get this from the Burning Man datasets page -
Fix unclosed polygons. The camp outlines on the PDF map were hand drawn by placement team members nad sometimes they are not closed polygons due to user error. They will show up in red. For each one, you have three options: CLOSE AUTOMATICALLY (snaps the last vertex back to the first), DELETE (if the whole polygon is an artifact), or REDRAW (let's you draw a fresh polygon to replace the wrong one in the map, by clicking vertices — Esc cancels, Enter or clicking the start vertex closes).
-
Add missing polygons. Occasionally you'll see a camp name in the map that doesn't actually have any polygon around it representing its borders. Click
ADDand draw a polygon for each — orDONEto skip. -
Name unmatched camps. Polygons that the auto-matcher couldn't tie to a roster entry are highlighted pink. Pick the right name from the dropdown (or type one in) and
ACCEPT. The dropdown lists camps from the roster that aren't already on the map.
All corrections are saved as you go to 2025/corrections.json, so you can
quit and resume without losing progress.
Once every step is done — spike + scale + lat/lon set, no unclosed polygons, add-polygons step finished, no unmatched camps — the status bar disappears and the two output files are written automatically. The browser console logs:
Wrote camps-geocoded.json (N/total centroids) and camps-geocoded-with-borders.json (M borders)
Re-emission happens on every load (and on every correction once you're past the all-done threshold), so the files always reflect the latest state.
.
├── 2025/
│ ├── input.pdf (you supply)
│ ├── camps.json (you supply)
│ ├── corrections.json (created/updated as you work)
│ ├── camps-geocoded.json (output)
│ └── camps-geocoded-with-borders.json (output)
├── public/
│ └── app.js (browser-side logic)
├── extract.js (pdf.js layer extraction)
├── server.js (Node HTTP server + endpoints)
└── package.json