Inspired by Homebrew Website Club, which I’ve been going to recently, I created a web app. Microformats2 on a Map reads webpages that have been marked up according to the microformats2 standard, extracts locations from them, and displays the locations on—yes—a map. You can try it out here.
The project isn’t complete yet; the UI is unpolished and nested microformats aren’t yet supported. See the GitHub project page for more caveats, usage information, and technical details. The source code is available there under the GNU GPL, version 3. Pull requests are welcome! Bug reports are also welcome but slightly less so.
As part of my endless process of tinkering with this website instead of actually writing posts for it, I went back and added location data to all of my blog entries. Each one now shows the city and state whence it was posted. This information is marked up with the microformats2 h-adr standard to make it machine-readable.
After going through the effort of figuring out where I posted each entry from, I wanted to be able to see all of these locations on a map. It’s a form of gamification: I feel a sense of accomplishment in general when I post a blog entry, and seeing all of my posts laid out visually just reinforces that feeling. (Instagram used to have a similar feature but it seems that they’ve discontinued it… bummer!)
The same-origin policy bit me while I was making this. My original plan was to offer an interface where users could put in multiple URLs and then the app would retrieve each page and extract all of its locations. I was also hoping to make a completely client-side web app so that I could host a few static files but not worry about any server-side logic. But I realized that the same-origin policy would prevent a page hosted on my server from downloading pages from other servers.1
My solution was an awkward compromise. I added a mode in which the user could just put in some HTML and locations would be extracted from that. I also created a server with an endpoint that would take in a URL, retrieve it, and return its contents—the world’s simplest proxy. If someone downloads Microformats2 on a Map and runs the server, the client-side code detects that and offers the possibility to enter a list of URLs. (The pages are retrieved through this proxy, which is allowed by the same-origin policy since that server and the client-side code are coming from the same port on localhost.)
This solution adds a little bit of complexity but it allows me to host a copy of the application without being responsible for a server that could probably be made to DOS someone. It also provides for the ability—if you run the server piece—to map multiple webpages’ locations, which I think is much more useful than just mapping the locations from a single page.
Standing on the node_modules of giants
It’s been said that modern web development consists mostly of hooking together other people’s libraries. In this case, that’s totally true. I pulled in Leaflet for the maps, Leaflet.markercluster to gracefully handle markers that were visually close together, and microformat-node to extract Microformats data from HTML. The app uses OpenStreetMap for map tiles and OpenStreetMap’s Nominatim service for geocoding (turning addresses into latitudes and longitudes). My contribution was a paltry 255 lines of code on the client side and 32 for the server.