TackMap Pin Board
What it does for you
A Leaflet pin board with boards, tags, distance measuring, GeoJSON and CSV in and out, and whole boards shared as a single link.

Screenshots

In more detail
Tack is a pin board for places. You click the map to drop a labeled pin, organize pins into boards, and send a whole board to a friend as a single link. No account and no server in the middle, and your pins can leave as GeoJSON or CSV whenever you want.
Honest limits
I'm assuming light personal use of the OpenStreetMap tile server fits its usage policy. Board naming and deletion still use the browser's plain prompt() and confirm() boxes. A board with long notes makes a long URL, since there's no compression. Tested by automated checks and screenshots, not by real users on real phones.
How I built it
Another one from the bulk one-shot night, built by Claude Code from the shared brief in about 0.4 hours. I set the feature list, the tested-core rule, the idea of putting the share link in the URL hash, the no-build constraint, and the demo: a ten-stop Charlotte coffee and car-meet crawl.
Claude Code wrote pins.js, the 177 tests, the UI, and the static server in one pass. pins.js has no DOM and no Leaflet in it. It's a pure reducer for boards and pins, plus distance and bearing math, search, GeoJSON and CSV import and export, and the share-link codec.
The screenshot loop is where this build got interesting. The first screenshots showed tag chips but no list, no markers, no stats. The second pass showed the map tiles I had specified (CARTO) watermarked "API KEY REQUIRED." The zoom control also sat on top of the editor's Delete button. Claude Code fixed all three, and it flagged the tile swap as a deviation from my spec instead of hiding it. I agreed with the call.
Small environment note: python3 isn't installed on this machine, so a scripted patch failed and the edits were redone by hand.
What I learned
- Leaflet's
map.getCenter()throws until the map has a center and zoom. My list sorted pins by distance from the view, so that one exception silently took the markers and stats down too. Passing center and zoom into the map constructor fixed it. - Free keyless tile endpoints are not a stable dependency. The dark map became standard OpenStreetMap tiles with a CSS invert and hue-rotate on the tile layer only, so markers and controls stay untouched.
- A hand-written base64url over
TextEncoderbytes is about 20 lines, and the same share encoder runs in Node tests and the browser, emoji included. The share link lands at roughly 56 percent the size of the equivalent GeoJSON. - Returning the same state object from a reducer when nothing changed is worth testing directly. It let the UI skip saves and re-renders with one check, and 9 of the 177 tests pin it down.
What carried forward
It used the tested-core pattern from #9 through #13 and the brief's serve.mjs on port 5114. The app name caused a real coordination snag later: the kanban board (#31) was first built as "Tack" too. It was one of the duplicate app names found in the coordination checks later in the sprint. #31 was renamed Kanso, so the name stayed here.
If I took it further
I'd add marker clustering and deflate compression for share links, and swap the plain browser prompts for the same styled dialogs the share flow uses.
#014 Built with Claude Code September 19, 2026 177 automated checks