At FOSS4G Oceania 2019, I lamented the lack of free tools for collaboratively maintaining small datasets of locations, a common need in many community groups. So, this weekend I had a go at building one: TinyMap! A simple tool that lets you add and remove points with names and descriptions from any map you care to name.
- Zero-cost to host.
- Shave every possible corner on implementation effort (security, scalability, performance…)
- Get it done in a weekend.
Learning authentication seemed more like work than fun, so I’ve decided to rely on secret URLs as the only security mechanism. The burden of choosing an unguessable URL, and not distributing it, lies entirely on the users. I’m sure this will end well.
For storing and retrieving a few hundred points, running PostGIS seems overkill. Even using a hosted NoSQL solution like FireBase felt much too serious. I really wanted the NoSQL equivalent of SQLite, and eventually found TingoDB, which is basically MongoDB but in pure NodeJS.
Writing an API wrapper around it with Express is pretty easy. I don’t write many servers, but the Express documentation is always such a pleasure to use. Just under 100 lines of code to provide CRUD services and very basic authentication.
And where to host? On my favourite free NodeJS hosting platform, Glitch. It can sometimes feel a bit weird writing code directly in the browser, but it’s really nice skipping directly over the questions of “where should I host this?”, “how do I get my code there?” and “how do I make the server accessible to the outside world?”. Glitch makes for insane levels of productivity: just clone the Express starter project, and go – it’s already running.
We end up with an API structure like:
You can see the code here: https://glitch.com/edit/#!/shared-map-api
The front end builds on my “community-map” VueJS template which provides a basic app structure, with the Tachyons CSS kit, and initialises a Mapbox-GL-JS map enhanced with my mapbox-gl-utils library and primed to deploy to Github Pages. I wanted to keep it as simple as possible.
Three URL structures are understood:
- /?layer=layername&secretkey=mysecret: user can add and delete features on the “layername” layer.
- /?layer=layername: user can view features on the layername layer
- /: user is invited to create a new map.
Interaction code can be surprisingly verbose to write. The simple mechanic of “click add, click the map, type a name and description, click save” immediately spawns questions such as “what if the user wants to cancel?” and “what if the user clicks on an existing point while they’re meant to be adding a new one?”
For simplicity, I’ve been trying to avoid storing any information about the map itself – only the points themselves are stored. That means, there’s no way to define where you want the viewpoint to be centred. My sneaky solution to that is to always centre it around where the points are.
There is absolutely no error handling. If you enter an incorrect secret key, there is no warning – mostly because I didn’t have a method offhand for flashing an alert.
There is also no way to edit an existing item (yet). Or to add any fields other than Name and Description. (Now it’s possible to existing items :) )
Front-end hosting is easy to set up on Github Pages. I like to put a domain name on even weekend hack projects, so, inspired by too many episodes of TinyHouse Nation, I went with tinymap.website.
The front-end code is on Github: https://github.com/stevage/tinymap/
Cutting corners is so liberating. If you’re not actually building the next great SaaS, perhaps you don’t need a high performance database. Maybe you don’t need Kubernetes, and a tiny service running on Glitch will do.
I’m not sure what happens next with TinyMap. If you like it, let me know!