Building MaKe, a fire hydrant map for my volunteer fire brigade
How I replaced our unit's old GIS viewer with MaKe, a Flutter hydrant map built for moving vehicles, and why the data was the hard part.

Juho Torkkeli
· 8 min read

MaKe is the map we use in my volunteer fire brigade to find fire hydrants and other water sources. It runs in all of our unit’s vehicles, on Windows computers and Android tablets. It has been in use for about two years, and it replaced the legacy app we used before.
The name is a fun acronym. Our unit has two pumps, one named Majava (beaver) and the other Kettu (fox). Majava + Kettu = MaKe, which is also why the app icon has a beaver and a fox guarding a hydrant.
The old tool
Before MaKe, we used a MapInfo viewer from Pitney Bowes (now Precisely). Updating its data needed a paid license, so keeping the data up to date was expensive.
The bigger problem was that it was hard to use. The buttons were small, which is not ideal when you’re trying to hit them in a moving vehicle, and new members found it especially hard to learn. It also didn’t remember its settings between restarts. Every time you opened it, you first had to set the same handful of options again before you could get to what you actually came for.
Starting with the people who use it
I decided to build a replacement. I had used the old app a lot myself, so I already knew its biggest pain points. I also interviewed other users about how they use it and wrote down theirs.
Those notes turned into three design goals:
- Easy to see and easy to hit. The app is used in a moving vehicle, so everything has to be readable at a glance and hard to miss.
- No extra steps. Finding an address shouldn’t start with a trip through the settings.
- Autofill the address. You should rarely have to type a whole address.
A proof of concept first
My first attempt was in spring 2023: Flutter with flutter_map, Mapbox tiles and geocoding, and Hive for local storage. It already had desktop targets and a dialog for editing points on the map.
It was a proof of concept, and it stayed one. When I started the real app, it was cleaner to start from an empty project than to build on top of it.
Six days to a first version
The real project started on May 3, 2024, and the first version took about six days. It was desktop-first from day one: in the first commits I removed the Android, iOS and web targets and kept Windows, macOS and Linux. The computers in our vehicles run Windows.
The first version had:
- A split view. Two maps side by side, each with its own base map, so you can see the same spot on the terrain map and in aerial imagery at the same time. The base maps are OpenStreetMap and the National Land Survey of Finland’s open terrain map and orthophotos.
- Clustered hydrant markers, so the map stays smooth with lots of hydrants on screen.
- One measuring tool for both distances and areas.
- Address search on top of the local address data. A teammate wrote the first full-text search. I added a simpler search with separate fields for street, house number and municipality that shows the five best matches as you type.
- A local Isar database for hydrants and addresses, filled by importing the data files.
- Keyboard shortcuts for the main actions. Today, the arrow keys pan, + and − zoom, H opens search, J, K and L switch between the pointer, ruler and hand tools, M toggles the split view, and N jumps to the search result.

This is the 2024 version. The UI is in Finnish: Mittaa means measure, Matka distance and Pinta-ala area. It also shows a bug. According to the panel, a shape 7,150 m long has an area of 249.85 m², about the floor area of a large house. The number was really in hectares: the code divided square meters by 10,000 and kept the m² label. I fixed it in December 2025, together with the length calculation.
The screenshot shows no hydrants, and it stays that way: part of the hydrant data isn’t public.
Flutter on the desktop
Flutter does really well on the desktop. I develop MaKe on macOS and only test it on Windows, which keeps my time on Windows to a minimum. I consider that a feature.
One of the few Windows-specific fixes was the + zoom shortcut. The window_manager package handles the desktop details: the app opens maximized and has a minimum window size.
The data was the hard part
The app came together quickly. The hardest part of the whole project was the data.
The first job was getting our old hydrant data into the coordinate format the map uses (WGS84 latitude and longitude) with enough precision. That matters more than it sounds: in WGS84, the fifth decimal of a degree is roughly a meter, so every digit lost along the way moves the hydrants.
The second job was removing duplicate points without removing any real data. Combining several sources means the same hydrant can show up more than once. The catch is telling a duplicate from a real hydrant nearby, and deleting a real hydrant is a much worse bug than showing one twice.
No single tool did all of it. I used a mix of Python and Dart scripts to convert, clean up and combine the files, and QGIS turned out to be the final piece of the puzzle for getting the coordinate conversion right. The work started with the first version in 2024 and picked up again in 2025, when new hydrant data from several sources arrived as DXF drawings, shapefiles and CSV files and needed the same treatment.
Addresses needed their own pipeline, because the autofill needs address data for our whole area. Today, I build the address index from OpenStreetMap buildings that have a house number, fetched through the Overpass API, with each address placed at the center of its building. Then I fill the gaps with address data from Finnish public agencies, adding a record only when OpenStreetMap doesn’t already have that address.
Everything lives in a local database on the device: hydrants, municipalities and addresses. Search and hydrant lookups work without a network connection. Map tiles are the exception. Tile caching is off, because raster tiles for our whole area are too big to store on the device.
For now, I update the data by hand. The app has an import screen for hydrant, municipality and address files, with a progress bar.
Two years of small improvements
- Autumn 2024: a progress bar for imports and some clustering tweaks, including a minimum cluster size, so small groups show as individual hydrants. House-number search also matches partial input.
- December 2025: new hydrant data and parsers, and markers colored by type. Tapping a hydrant opens a popup with its type, for example an underground or above-ground hydrant or a natural water source that needs a pump. The popup also has buttons to copy its coordinates or the nearest address. Clusters now form only from 20 or more markers. I also added municipality autocomplete.
- March 2026: the search became step by step. You pick the municipality (five suggestions as you type), then the street, then the house number. It’s debounced and works from the keyboard. This is where the address autofill from the design goals ended up: you rarely type a whole address. The app also got a proper icon and a splash screen.
- May 2026: mobile. The same codebase now builds for iOS and Android, with GPS location and a button that centers the map on you. Beyond that, the main UI change for mobile was a responsive layout for the search dialog. The Android version runs on the tablets in our vehicles. I also moved the local database to the community fork of Isar.
The feedback has been simple: people are happier with MaKe because it’s simpler and easier, so everyone can use it. And updating the data no longer needs a license.
What’s next
Secure sync. Right now I update the data by hand. I’ve designed a zero-trust sync: a device has to be activated before it gets any data, updates are signed so the app can verify where they came from, the data on the device is encrypted, and a lost device can be wiped. It’s offline-first, because the app has to keep working where the network doesn’t. I haven’t built it yet.
Vector maps. MaKe will move to vector maps with maplibre_flutter, my own MapLibre package for Flutter. Needing vector maps on the desktop is what started that package in the first place. Desktop support had been the blocker for MapLibre vector maps in Flutter. At the time of writing, maplibre_flutter is the only package that supports enough of the MapLibre API on every Flutter platform, desktop included.
Offline maps. They have been in the plan since day one. Vector tiles are much smaller than raster tiles for the same area, so after the migration I can finally add them. Aerial imagery won’t be offline, though some of it may be cached.

