Boîte à Livre: mapping free neighborhood libraries with Leaflet, OpenStreetMap, and Firebase
A community map of little free libraries in France. Notes on choosing Leaflet over Mapbox, why Firebase Realtime Database still has a niche, and the moderation problem you cannot avoid.
Boîte à Livre is a community map for boîtes à livres: the small wooden cabinets people set up outside their houses or in parks in France, full of secondhand books anyone can take or leave. They exist everywhere in the country and there is no single registry. This app is a registry: pan the map, see boxes near you, tap one to see what other users have noted about it, add a new one if you spot it on a walk. Repo: github.com/aelmufti/boitealivre. Live: boitesauxlivres.web.app.
Why Leaflet, not Mapbox or Google Maps
For a hobby project with no budget and no business model, the cost structure of commercial map SDKs is the wrong shape. Mapbox and Google both have generous free tiers, but the tiers are sized for traffic patterns I do not want to think about, and a single viral moment on Reddit can leave you holding a bill.
Leaflet is a few-kilobyte open-source map renderer that talks to any tile server. Point it at the public OpenStreetMap tile servers and you have a working map with no account, no key, no quota dashboard. The features I gave up — vector tiles, smooth 3D pitching, turn-by-turn — are not features anyone needs to find a book box.
For production traffic, the right move is to host your own tile server (or use a service like Stadia / MapTiler) rather than hammer the OSM public tiles, which are meant for development. I am within the polite limits for now; if usage grew I would swap in a self-hosted tile pipeline before the Open Street Map foundation rate-limited me.
Why Firebase Realtime Database is fine here
Firebase Realtime Database (RTDB) is the older of the two Firebase databases. Most new projects reach for Firestore instead, and that is usually correct. RTDB has earned its reputation for awkward queries.
For this app though, the data shape is one flat tree of points, each with coordinates, a name, and an array of user notes. Total dataset size is small (low thousands of documents). Reads are dominated by a single query — "everything in this bounding box" — and that query is cheap even if you just download the whole tree on first load and filter client-side, which is what Boîte à Livre does.
RTDB's strengths are exactly fitted to that pattern: a single document subscription, instant push when a new box is added, no schema migration to do when the data shape evolves. If the dataset grew by an order of magnitude I would move to Firestore (or Postgres + PostGIS, frankly). At the current scale RTDB is the smaller solution.
The moderation problem
Any "anyone can add a pin to a map" app eventually meets the same three failure modes:
- Spam pins. Someone drops a pin in the middle of the ocean labelled "test", and never comes back to delete it.
- Misplaced pins. Honest user, wrong address autocomplete, pin lands one street over.
- Pins for things that are not boxes. The local bookstore, a personal bookshelf, an obsolete pile of magazines.
I did not solve moderation, and I want to be honest about that. What I did was small:
- Pins added by a brand-new account are flagged as unverified, and rendered with a different icon, until at least one other user confirms them.
- Every pin can be reported by any user. A small number of reports moves the pin to a hidden queue.
- I review that queue manually. For a project at this scale it is a few entries a month — totally manageable as a solo project, totally unsustainable if traffic 100×'d.
The honest answer to "how does this scale to a national registry" is "it does not, without a real moderation pipeline". Wikipedia-style trust graphs, neighbourhood moderators, machine-vision validation of submitted photos — any of those is a real piece of work and none of them are cheap.
The PWA story is simpler than I expected
The app installs to a phone like a native app. The whole offline path is: service worker caches the JS bundle, IndexedDB caches the last-seen pin set, and the map degrades to "your last sync" when offline. None of that needed a framework — it is a couple of hundred lines of plain service-worker code.
The single nuance is that Leaflet tiles do not cache cleanly in a service worker without help, because the tile URLs are infinite (every zoom × every coordinate pair). The pragmatic fix is to cache the tiles in the area the user has actually looked at, with a small LRU. Anything more clever than that is over-engineering for the actual usage.
What this project was really for
Honestly, the project is mostly an excuse. The product is a directory of book boxes. The reason I built it is that the boîte à livre near my place changes its contents every couple of days, I wanted to share that habit with friends, and an app was a more durable way to do that than a group chat. The engineering choices in this note all flow from that scale: a few thousand boxes, a few hundred users, a single maintainer. Picking tools that match that scale, instead of the scale you wish you had, is most of what makes a hobby project shippable.