Project 002 · Field sales tool · map · realtime

AlmiBoost Scout

A mobile web app I built to run door-to-door sales in Bratislava. It shows every nearby business on a map, tracks each pitch and sale, and syncs live between my phone and my laptop. It runs without Google's APIs and without a server of my own.

RoleDesigner and developer
TimelineAug 2026 – present
StatusIn daily use, private
StackVanilla JS, Leaflet, OpenStreetMap, Supabase
AlmiBoost Scout screenshot

Overview

Door-to-door selling lives and dies on two questions: where should I go next, and what happened the last time I went there? Scout answers both. It is one HTML file you open on a phone, with a bundle of 8,493 Bratislava businesses built in, a map you can use outside, and a shared record of every pitch.

It is a private tool, so there is no public link. The screenshot below is the real app showing about eight thousand businesses on the map.

Why I built it

  • I needed to find streets full of the right kind of business: hair salons, cafés, bars, bakeries and small shops.
  • I needed to remember what I said, who was closed, who asked me to come back, and who bought.
  • I wanted the phone in my pocket and the laptop at home to show the same data, instantly.
  • I wanted to know what the whole effort cost and earned, including expenses.

What it does

Search by type and area

Chips for coffee, restaurants, hair salons, nail studios, beauty salons, bars, bakeries, barbershops, small supermarkets, flower shops, tattoo studios and clothing shops, combined with an area or street search and a Bratislava-only switch.

Find by name

A separate field for looking up one named business without the category filter getting in the way.

Filters and sort

Narrow results and sort them. The header always shows how many businesses match.

List, map and dashboard

Three views over the same data. The map colours markers by pitch state and has a "sales only" filter.

Pitch tracking

Open any business and record the outcome, notes and follow-up. Every change is saved and synced.

GPS and radius

A live location dot and a radius around you so you can see what is within walking distance.

Calendar and expenses

A calendar of pitches, an expense list and a net-revenue figure on the dashboard.

Review growth

For every sale, how many reviews the business had then and now, which is the metric that proves the card works.

The data: from Google to open data

The first version called Google Places for every search, Google Geocoding for every area lookup and the Google Maps JavaScript API for the map, with Firebase for storage. That meant a billing account, quotas and a recurring cost. I rebuilt it so that none of those are needed.

BeforeAfter
Google Places search, a call per searchA bundled file of 8,493 businesses that ships with the app
Google Geocoding for areasA bundled file of 2,448 street centrelines
Google Maps JavaScript mapLeaflet drawn over OpenStreetMap tiles
Firebase for the shared dashboardSupabase (Postgres and Realtime)

I verified the result: loading the app, running a search and opening the map produces zero requests to Places, Maps, Geocoding or Firebase. The only Google-owned request left is a free font CDN.

The business file is built by a script that pulls a fresh OpenStreetMap extract through Overpass and a current Overture Maps release, removes duplicates by name and proximity, maps categories onto the chips, filters out the big chains, and writes a new file. The app picks it up with no code change, so refreshing it every few months is a single command.

A better street search

Google capped each search at 20 results per category, so a search for a long street returned a random slice. The new version finds the road itself in the street file and returns everything standing along it.

That distinction matters more than it sounds. Matching the typed name against business address fields looks equivalent and is not. Gagarinova is a three-kilometre arterial lined with shops, yet only one of them lists "Gagarinova" as its address, because the rest are addressed to the side streets they front onto. Searching addresses found 1 business there; searching the road found 85. Obchodná returns 258 businesses instantly, with no paging.

The search corridor is 80 metres on each side of the centreline and widens automatically when a street comes back sparse, because an arterial's shops sit further from the road than an old-town street's.

Architecture

Scout is deliberately a single static file with no server. Any static host works.

  • Front end. Plain JavaScript, no framework and no build step. About a hundred small functions: search, rendering, map markers, modals, the calendar, the dashboard.
  • Map. Leaflet with OpenStreetMap tiles, markers redrawn from the current result list, a distance calculation for the radius filter.
  • Storage. Two Supabase tables, pitches and expenses. Each row keeps the whole entry in a JSON column, so the app's data shape carries over untouched and adding a field later needs no migration. A trigger keeps the update time honest.
  • Realtime. Both tables are in the Realtime publication, which is what makes a pitch marked on the phone appear on the laptop.
  • Works without a backend. Until the Supabase keys are filled in, the app keeps everything on one device, so it can be tried before it is set up.
  • Password gate. A front-end prompt on opening.

Ratings by hand

I checked carefully: there is no free source of Google ratings anywhere. So each business has an "Add rating" button. You tap "Open in Maps", read the two numbers and type them in. Once a number exists, everything that depended on it still works: the high-potential badge, the filters and the review growth since a sale. On the dashboard, "Update review counts" walks through every sale one at a time, so refreshing growth is a single job rather than hunting for each shop.

Copying a review link now copies a normal Google Maps search link for the business. It lands on the shop's Maps page, where "Write a review" is one tap away. The old direct link needed a Google Place ID, and keeping those would have meant going back to Google.

Moving the old data

The old app identified businesses by Google Place ID, and the new one has its own ids. A small migration page takes an export from the old site and re-links every pitch by name and location. Anything it cannot match is kept anyway with its full history, so the dashboard totals stay correct and nothing is lost; it just will not line up with a search result.

Honest limits

  • Coverage is about 80%, not 100%. Checked against 28 businesses I had actually pitched, 22 were in the free data. The misses were small or recently opened places that OpenStreetMap and Overture have not recorded. For those I search by name or add them later; a place I already pitched keeps its record regardless.
  • Ratings are manual, as described above.
  • The database key is public. It is embedded in the page, so the password prompt only deters casual access and does not protect the database. That is acceptable while the tool is private. If it were ever shared, the fix is Supabase Auth with real policies, and the schema file says exactly what to change.
  • Map tiles come from OpenStreetMap's own servers under their usage policy, which suits one person scouting a city. Growth would mean switching one tile-URL line to a paid or self-hosted provider.

What I learned

  • Open data goes a long way once you merge two sources and deduplicate carefully.
  • Constraints can improve a product: dropping Google forced a street search that is better than the paid one.
  • Be honest about security. Writing down exactly what the public key exposes made it easy to decide when it would need to change.
  • A tool you use every day tells you what to fix. Most features here exist because a visit went wrong without them.
Next project Pier AI →