ExplorInk
GitHub

development · map sync ·

Getting the map onto the reader, square by square

There is no region to buy and no four gigabyte country download. The reader keeps a list of the map squares it tried to open and did not have. The phone fetches those squares from our tile server over Bluetooth. If nobody has ever built one, the server builds it from OpenStreetMap because you asked for it, and it is usually there seconds later.

Real LilyGo T5 S3 Pro framebuffer: the map at Modra with no data at all, the whole screen diagonal hatching, only the position ring in the middle The same place after a sync: streets, forest, the villages Modra, Dubova, Vinosady and Pila, with hatching left only in the top corner
device The same screen, before and after. Left: this card had nothing for Modra, so the panel is all hatching. Right: the same view minutes later, after the reader asked the phone for what it was missing. The corner that is still hatched is a square the server had not built yet when this was taken. T5 S3 Pro, 540×960, 1:1, 2026-11-03.

Do I have to prepare the map before I go?

No, and you can. All of it is off until you start it, and a transfer is always started on the reader, never by the phone: it spends your mobile data, so it is your decision. Three ways in, and they are the same mechanism with different timing:

WhenWhat you doWhat happens
At home, the evening beforeOpen Sync on the reader with the phone nearbyEverything the reader noticed it was missing comes across
Planning a tripFind the place in the phone app and queue the areaThe phone holds the squares and pushes them the next time the reader is listening
Out on the waySwitch auto-sync on, once, in the reader's settingsWalking onto a square the reader does not have fetches it there and then

Nothing here needs an account, a subscription or a region licence. A square on your card is yours, offline, and stays there.

What a missing square looks like, and what the reader does about it

A square the reader does not have is drawn as diagonal hatching rather than as empty white. White would be a lie: it reads as flat ground with nothing on it. Hatching says no data here, which is a different sentence and the true one.

Behind that, the reader writes the square down, with a count of how many times it has been wanted, and the list survives a restart. That is a record of what a real ride actually needed, not a guess made at a desk, and it is what the Sync screen works through.

The Sync screen, with real figures

Sync is its own row on the home screen. Opening it starts Bluetooth and waits for the phone. The empty boxes are the squares it knows it is short of.

Top of the sync screen: Sync map tiles, over Bluetooth, waiting for the phone, open ExplorInk GPS on your phone nearby, with four empty squares drawn below
device Waiting for the phone, LilyGo T5 S3 Pro, 1:1, top of the screen. The boxes are the squares this card is missing.

With the app running nearby, the transfer starts on its own and the screen turns into a progress report: how many squares are done, how much has arrived, the speed, the time left, and which square is coming over right now with its own byte count.

Top of the sync screen during a transfer: 60 of 549 squares, 1.5 MB, 12.2 kB per second, 16 minutes 9 seconds left, progress bar at 10 percent
device A real transfer, same board, same day, 1:1: 60 of 549 squares, 1.5 MB in, 12.2 kB/s, 16 minutes left. The line under it is the square in flight, 5 kB of 18 kB.

So the numbers, measured on 2026-11-03 between a LilyGo T5 S3 Pro and a Samsung S24 Ultra: about 12 kB/s over Bluetooth, squares of roughly 5 to 35 kB, and an average near 25 kB. A whole queued area of 549 squares is about 14 MB and a bit under twenty minutes. A single square you walked onto is a second.

Leaving the screen cancels the transfer and the screen says so. Nothing is lost: the phone keeps the queue and carries on the next time you open Sync.

The same transfer, seen from the phone

The app carries the other half of the job, and it says the same numbers the reader does. This is its main screen while that transfer ran:

Crop of the ExplorInk GPS main screen: a map squares block reading 361 of 549 squares, 19.2 MB, 12.3 kB per second, 13 minutes 19 seconds left, with a progress bar nearly full
phone ExplorInk GPS on a Samsung S24 Ultra, 2026-11-03, same transfer as above. A crop of the main screen: the rest of it is the live position, which does not belong on a public page.

Queuing an area ahead of a trip is the Map areas screen. Give it a coordinate or a link shared out of Google Maps, pick a box 10, 20 or 40 km across, and ask what is there. It answers with the plan in exact numbers rather than an estimate, and nothing is queued until you have seen that and pressed Add.

Crop of the app's map areas screen: a field taking a coordinate or a shared maps link, a use my position button, box size radio buttons at 10, 20 and 40 km, and a check area availability button
phone The area picker. The grey text in the field is a hint, not a position.

The queue below it survives everything: the reader being off, the app being closed, the phone being rebooted. The two areas in this shot were queued in September and are still working through, one finished and one part way.

Crop of the app's queue: 550 queued, 367 sent, 10.6 MB left, about 14 minutes, then two queued areas of 40 km each with their own progress bars, one complete and one part way
phone The queue, with the two places painted out. Each area keeps its own count and its own progress, so a trip queued weeks ago is not lost behind a trip queued today.

When nobody has ever built that square

Then the server has not got it either, and that is the interesting case. The missing request is the request: within seconds our tile server counts the misses of the last day, takes the ten most wanted, builds those areas from OpenStreetMap and publishes them. The reader says not on the server yet, saved, will ask again, and the next sync usually brings it.

Top of the sync screen after a fetch: fetch finished, 6 of 14, 8 queued, 83 kB, checking 6 tiles for updates, then not on the server yet, saved, will ask again
device The honest half, caught on 2026-11-03: six squares arrived, eight did not exist anywhere yet. The reader says so and keeps them on its list. The before and after at the top of this page are that same run, a couple of minutes apart.

That is why there are no prepared country packs here and no coverage you have to wait for us to decide on. How the tiles are built has the format, the levels of detail and the server side of this.

A square that went out of date is a separate question

A square that opens and draws is treated as good forever, however old it is. That is deliberate: the reader cannot tell a stale square from a current one by looking at it. Each square carries an identifier that changes when it is rebuilt, and comparing that against what the server publishes is the only way to know.

Asking that question costs a connection and your data, so it has its own setting with three positions, and it ships off:

SettingWhat it does
Off, the defaultNever ask. Squares on the card are used as they are
Sync screenAsk once when you open Sync. Preparation at home, where spending data is expected
LiveAsk from the map as well, on a cooldown, while you are out

It is worth having, and it was earned the hard way. A classification bug once drew a tram line as a mainline railway. The bug was fixed, the area was rebuilt, and every reader that had already synced kept the wrong picture, permanently, because the file opened and drew perfectly well.

Everything here is off until you turn it on

Auto-sync during a ride is off. The staleness check is off. There is no background service, no account, no login, and the phone never pushes anything the reader did not ask for. The reason is the same in all three cases: it is your mobile data, and a map reader that quietly spends it has broken something more important than a map square.

What it cannot do today

A board using its own satellite receiver cannot fetch mid-ride. The map screen runs one radio at a time, so with the on-board receiver switched on there is no Bluetooth to ask the phone through, and a missing square stays hatched for that session. The Sync screen itself is unaffected. On the Xteink readers, which have no receiver, this does not come up.

Your phone needs a connection at the moment of fetching, since the squares come from our server. Queue the area at home over Wi-Fi and the data cost on the road is zero.

Bluetooth is the only path for a square today. 12 kB/s is fine for the handful you walk onto and slow for a country. The reader also has a Wi-Fi file transfer screen, where a browser can upload files onto the card directly, and wiring the tile sync to that is not done.