Local directory
Wander
Wander is a demo directory built on native geospatial search. Each place stores a real latitude and longitude in a Location field, and a single `$near` filter asks Headless for everything within a radius — returned nearest-first, so the app never sorts by distance itself. Here’s how you’d build your own.

Step 0
The content model
Here’s the shape you’re aiming for. You don’t have to build it by hand — the next steps have an agent create it for you — but it helps to see the target first. Expand a type to see its fields.
placeCollection7 fields
A place on the map, with a real geo point.
- nameText
- descriptionText
- locationLocationGEO_POINT { lat, lng } — geo-indexed for $near
- categoryEnumcoffee · food-cart · park · bookstore · viewpoint
- ratingNumber
- pricelevelText$ · $$ · $$$
- addressText
The recipe
Build your own with an agent
Use this as a blueprint, not a script — adapt the fields and copy to whatever you’re making. Each step is a real prompt you can hand to a coding agent like Claude Code with the Headless MCP server connected; the terminals show the tool calls the agent makes, and the code is what it produces.
Create the project
The agent creates the project over MCP. Nothing special to configure — the Location field type does the geo work.
MCP · Headless# Spin up the project› claude "Create a Headless project called Wander for a local places directory"✓ create_project { name: "Wander", slug: "demo-local" }→ demo-local readyModel the content
One type is enough. The important field is Location — a native geo point that Headless indexes so it can answer radius queries. Everything else is ordinary metadata.
MCP · Headless# One type, with a real geo point› claude "Add a Place type with name, description, a Location field, a category enum, rating, price level, and address"✓ create_content_type { name: "Place" }✓ create_field × 7 (location as a Location field)→ the Location field is geo-indexed for $nearSeed the places
Batch-create places, each with real coordinates. Those points are what the `$near` filter searches against.
MCP · Headless# Drop pins around town› claude "Seed a dozen Portland places across coffee, food carts, parks, bookstores, and viewpoints — each with its real coordinates"✓ create_entries place × 12✓ publish_entries { count: 12 }→ every place has a location to search fromMint a read-only API key
The map runs in the browser, so create a public, read-only key under Project Settings → API Keys. The `$near` value is `lat,lng,radiusInMeters` — try it against downtown Portland.
Terminalcurl -s 'https://headless.build/api/v1/demo-local/place?filters[location][$near]=45.5190,-122.6794,3200' \ -H "X-API-Key: hls_live_your_read_only_key" | jqBuild the map
Hand the frontend to the agent — a Leaflet map beside a list. The whole search is one `$near` filter; because Headless returns results ordered nearest-first, the app renders them straight down the list with no distance sorting of its own.
Claude Code# A list synced to a map› claude "Write a single self-contained index.html with a Leaflet map and a list: send one $near filter for the chosen radius and category, and render the results nearest-first"✓ Write public/demos/demo-local/index.html→ 1 file · one geo filter · sorted by the serverindex.html// One $near filter does the radius search — value is "lat,lng,meters". function buildQuery(center, radiusMeters, category) { const p = new URLSearchParams(); p.set( "filters[location][$near]", `${center.lat},${center.lng},${radiusMeters}`, ); if (category !== "all") p.set("filters[category][$eq]", category); return `/place?${p}`; } // Headless returns matches ordered nearest-first — no client-side sort. const places = (await api(buildQuery(here, 3200, category))).data;Ship it
Deploy it anywhere; swap in the visitor’s real coordinates and it becomes a “near me” search. Add a place in Headless and it shows up the next time someone searches its radius — the geo index does the ranking, not your code.