Medium Pool · every medium your app could speak
$npx skills add funclosure/medium-pool

Visualization / Map

The Earth’s surface as the data
messageWhere is the content.
instance Slippy mapTiles, projection, location

A map is a visualization whose data domain is the surface of the Earth. It shares the lane’s concerns (a camera, hit testing, emphasis) and adds its own: a projection from longitude and latitude to pixels, a pyramid of image tiles fetched from a provider, and a new input, the device’s location.

That last part is why Map is a kind and not just a demo. Its skill has to cover tile services, attribution, keys, projections, and a permission prompt, none of which the general visualization skill should carry.

Reach for it when

  • where something is matters more than what it is
  • people will pan, zoom, and locate themselves
  • the data has coordinates, not just relations

This demo generates its own tiles in the page so it needs no tile provider. The projection, the tile grid, the zoom pyramid, and the marker math are the real thing.

direction
both ways
substrate
Web Mercator · z/x/y tiles from a provider · Geolocation

Where it bites

  • Web Mercator is the tile standard, and it is wrong near the poles and for area comparisons. Say so in the UI when it matters.
  • Tiles are addressed z/x/y and wrap in x, not in y. Clamp latitude, wrap longitude.
  • Attribution is a license term for almost every tile provider, not a courtesy. Render it always.
  • Geolocation needs HTTPS and a user gesture, can be blocked by an embedding frame, and returns nothing on desktops without a fix. The map must work without it.
  • Do not fetch tiles for zoom levels the user is flying through. Debounce zoom, cancel stale requests, cache what came back.

Instances of this kind

Each is one way to build it. None of them is the kind.

Slippy mapin the pool

Tiles, projection, location. reference/SlippyMap.ts

MapLibre GL JSopen source

Vector tiles on WebGL; the open successor to Mapbox GL and the default for production.

Leafletopen source

The small raster-tile classic. The slippy map this demo imitates.

deck.glopen source

Large-scale geospatial layers on WebGL, on top of a base map.

$npx skills add funclosure/medium-pool --skill medium-visualization-map
skills/medium-visualization-map/SKILL.md
---
name: medium-visualization-map
description: "Build an interactive map on the web: tile layers, Web Mercator projection, pan and zoom, markers, and device location. Use when adding a map, store locator, route view, or any view of geographic data. A kind of medium-visualization."
---

# Map (kind of Visualization)

## What this medium does to the person
A map makes "where" the content. Every other fact hangs off a position, and the person expects to find themselves on it.

## What this kind is
A visualization of geographic data. Inherits the lane's camera, hit testing, and emphasis; adds projection, tile pyramid, provider, and location input.

## Core building blocks
- Web Mercator: `lon/lat → world pixels at zoom z`, tile = floor(px / 256)
- A tile cache keyed `z/x/y`; wrap x, clamp y
- A provider (OpenStreetMap, MapTiler, Mapbox) with its attribution and key handled server-side or by domain restriction
- `navigator.geolocation.getCurrentPosition` behind a user gesture, with a no-location path
- Or a library that does all of the above (MapLibre GL, Leaflet), which is the right call for production

## UX rules that always apply
- Attribution visible at all times.
- Locate is a button, never automatic. Explain when it is blocked.
- Zoom and pan feel instant: draw cached tiles first, fill in fetched ones.
- Markers keep a stable pixel size across zoom levels; areas scale.

## Reference instances
Each is one way to speak this medium, cited as evidence. None of them is the medium.

`reference/SlippyMap.ts` — projection helpers, tile cache with a generated fallback tile, drag pan and wheel zoom, marker layer, locate-me with graceful denial. It uses a few layout class names from the pool's stylesheet (`row`, `btn`, `status`, `frame`); without that stylesheet the logic still runs and the controls are unstyled.

## Gotchas
- Mercator distorts area; do not compare sizes on it.
- Debounce zoom, cancel stale tile requests.
- Geolocation fails silently on many desktops; design for it.