← All work

Interactive map, West Cork

Roaringwater Places

The Roaringwater Journal has spent fifteen years writing about West Cork — 1,205 posts on its castles, megaliths, islands, walks and festivals. This turns that archive back into geography: 312 destinations you can pan around, each carrying the stories and photographs written about it.

Role
Built it solo
Source
Roaringwater Journal
Mapping library
None
The Roaringwater Places map: coloured pins across the West Cork coastline with journal photographs of Baltimore Harbour, Three Castle Head and Sheep's Head laid over the water
Three hundred and twelve places, seven categories, and the journal's own photography surfacing where there is room for it.
destinations mapped
312
journal stories linked
804
photographs indexed
3,146
mapping libraries used
0

Try it here

Drag to explore, click a pin for its stories, or open it full screen.

Basemap © OpenStreetMap contributors © CARTO. Photographs and writing © Roaringwater Journal, linked to their original posts. Full screen ↗

Turning an index back into a place

The journal's indexes are organised the way an archive is: by section, then by date. They are wonderful lists and hopeless maps. If you are standing in Skibbereen wondering what is worth the drive, a chronological column of post titles is not much help.

So all 1,205 posts were read for the places they are about. The authors tag their own posts — Dunmanus Castle, Mount Gabriel, Barley Cove — and those tags were matched against a gazetteer built from three sources: every named feature OpenStreetMap holds for the region, Wikidata's curated heritage records, and 2,800 monuments OpenStreetMap records without a name at all. A tag none of them can place is dropped rather than pinned somewhere plausible.

Where the pin comes from decides how precise it is. OpenStreetMap's surveyed nodes win, because Wikidata still rounds many settlements to the arcminute. Wikidata fills the gaps OpenStreetMap leaves — Dunmanus Castle is not in OSM at all. And where a post is tagged with a townland and a monument, the unnamed monument OSM records inside that townland becomes the pin. Where none of that lands on an actual spot, the pin sits at the centre of the townland and says so on its card rather than implying a precision it does not have. 85 of the 312 carry that caveat.

Posts about the same place merge onto one marker, so Ballydehob carries 130 stories behind a single pin rather than 130 pins arguing over the same village. Every description was then written from the place's own posts — what the journal actually says about it — rather than left as a bearing and a distance.

No mapping library

The whole thing is one HTML file with its CSS inline and about 1,500 lines of JavaScript beside it. No Leaflet, no MapLibre, no build step, no npm. The Web Mercator projection, tile grid, pinch handling and zoom anchoring are all written out longhand, which is why the map arrives in two requests.

Tiles are grouped into one container per zoom level. When you zoom, the level you came from stays underneath, stretched to line up, until the new tiles have landed, so the map never flashes white. Tiles load from the middle of the screen outwards, and a ring of off-screen tiles is kept so that short pans never refetch anything.

Pinching applies a live CSS transform to the basemap and commits to the nearest whole zoom when your fingers lift, so it tracks continuously instead of stepping. The pins are walked through the same transform by hand each frame rather than being scaled with it, so they stay their proper size throughout the gesture.

The map on a phone: pins thinned to dots where they crowd, with photo cards for Baile Bhuirne and Baltimore Harbour

On a phone the place list is a bottom sheet, and crowded pins become dots until you zoom in.

Making seventy pins legible

Three hundred and twelve markers, most of them inside Roaringwater Bay, is a puddle of teardrops. Three passes run whenever the map settles, and none of them run while you are dragging:

Thinning. Working down from the most-written-about place, any pin that would land on top of one already drawn is demoted to a small dot. The density stays visible and the coastline does not disappear, and zooming in promotes them back.

Labels. Each name is tried in eight positions around its pin and takes the first that clears every marker and every label already placed. A name that cannot be placed cleanly is dropped rather than smeared across its neighbours. Where a label ends up far from its pin, a hairline leader connects them.

Photographs. The same slot search runs for the photo cards, which additionally avoid the map controls, the attribution and each other, and are budgeted by zoom level and screen area so they never swamp the map.

Between settles, panning is nothing but a transform per element — the collision work is already done, and the label offsets travel with their pins.

Photo cards from the journal sitting over Roaringwater Bay beside their pins

Photographs are pulled straight from the posts, cropped by the journal's own CDN to exactly the size each slot needs.

The photographs load instantly

The obvious way to show a post's photography is to ask the WordPress API for it when someone opens a place. That is a round trip per story, and a gallery that arrives late and rearranges itself under your thumb.

Instead, all 804 posts were walked once, ahead of time, and 3,146 photographs were baked into the page as a 125KB index. Opening a place shows its gallery immediately, with no API call at all. Each image is requested at exactly the size its slot needs, and the neighbours in a gallery are warmed in the background so arrow keys and swipes never wait.

An earlier version leaned on website-screenshot previews. They were slow, frequently blank, and showed a web page where a photograph belonged.

Why the tiles come from CARTO

The first version drew tiles straight from tile.openstreetmap.org. That is the one thing the OpenStreetMap Foundation's tile policy explicitly asks you not to do, and their servers enforce it: requests from an embedded map come back carrying x-blocked: Access denied and a blank image. A map that renders perfectly on your laptop and shows nothing but pins on a live site.

The basemap now comes from CARTO's Voyager tiles — the same OpenStreetMap data, served from a CDN that is built for this, cached for six months, and available at double resolution for retina screens. Both are credited in the corner, as their licences require.

Seven kinds of day out

Every place falls into one, and any combination can be filtered on.

Vanilla JavaScript Web Mercator from scratch Raster tile engine Collision-based labelling Pointer Events WordPress REST API OpenStreetMap Overpass
← All work Next project

Tarski →