[HN Gopher] Show HN: Offline tiles and routing and geocoding in ...
       ___________________________________________________________________
        
       Show HN: Offline tiles and routing and geocoding in one Docker
       Compose stack
        
       Hi HN,  I'm building Corviont, a self-hosted offline maps appliance
       (tiles + routing + search) for edge/on-prem devices.  Hosted demo
       (no install): https://demo.corviont.com/  Self-host (Docker Compose
       repo): https://github.com/corviont/monaco-demo  Docs:
       https://www.corviont.com/docs  What's inside:                 -
       Vector tiles served locally (PMTiles)       - Routing served
       locally (Valhalla)       - Offline geocoding/search + reverse
       (SQLite Nominatim-based index)       - MapLibre UI wired to the
       local endpoints       After the initial image + data pulls, it runs
       fully offline (no external map/routing/geocoding API calls).  Next
       (if people need it): a signed on-device updater for regional
       datasets (verify - atomic swap - reload).  I'd love feedback: where
       offline maps/routing/search matters for you, and what constraints
       bite (hardware, fleet size, update windows, regions, deployment
       style).
        
       Author : packet_mover
       Score  : 70 points
       Date   : 2026-01-03 15:55 UTC (7 hours ago)
        
 (HTM) web link (www.corviont.com)
 (TXT) w3m dump (www.corviont.com)
        
       | bikelang wrote:
       | This is super cool. I've been kicking around an idea for ages
       | regarding tile-based routing that I think would be excellent for
       | offline routing. You could leverage the quadtree aspect of tiling
       | to encapsulate faster, direct routes (ie highways) and as you go
       | to deeper zoom levels you'd unlock small roads - even down to
       | pathways. This keeps your in-memory graph small while traversing
       | large distances (which would just be highways anyways) and once
       | you eliminated most of the distance your remaining graph
       | traversal on local roads would be small
        
         | krapht wrote:
         | What you suggested has been done before - you might find a
         | review of the literature fun if this sort of thing interests
         | you, even if academic papers are pretty dry reading normally.
        
           | tomaskafka wrote:
           | Also game engines need to do painting very fast
        
         | packet_mover wrote:
         | That's a really interesting framing - you're basically
         | describing hierarchical routing / "zoom-level" graphs: do the
         | long leg on a coarse network (highways), then refine locally as
         | you get closer to origin/destination.
         | 
         | FWIW, Valhalla already does a version of this: it partitions
         | the routing graph into hierarchical tiles and runs with
         | multiple hierarchy levels (highway / arterial / local)
         | specifically to keep search + in-memory working set smaller on
         | long routes: https://valhalla.github.io/valhalla/tiles/
         | 
         | The "quadtree tile unlock" mental model is a nice way to think
         | about it though - if you have a favorite paper / implementation
         | that leans harder into the tiling aspect, I'd love a pointer.
         | I'm currently focused on packaging + offline data consistency,
         | but routing performance on constrained edge boxes is definitely
         | a core constraint I care about.
        
         | michaelt wrote:
         | You might enjoy reading the papers "Highway Hierarchies Hasten
         | Exact Shortest Path Queries" [1] and "Exact Routing in Large
         | Road Networks using Contraction Hierarchies" [2] if you're
         | interested in hierarchical approaches to shortest path routing.
         | 
         | The algorithms _do_ divide the map up into chunks that are
         | themselves divided up and so on, but not on the strict
         | geographical basis a quadtree uses. You might not want to
         | divide Manhattan in two for routing purposes, even if the 74th
         | longitude line runs straight through it.
         | 
         | [1]
         | https://turing.iem.thm.de/routeplanning/hwy/esaHwyHierarchie...
         | [2]
         | https://publikationen.bibliothek.kit.edu/1000028701/14297392...
        
       | willi59549879 wrote:
       | searching with street name and number offline would be nice. In
       | google maps search only works when online
        
         | packet_mover wrote:
         | Good point - house-number search isn't there yet in Corviont.
         | 
         | Right now the offline geocoder in the demo does place/street-
         | level search + reverse, but street + house number ("Main St
         | 12") isn't supported yet. It's explicitly on the near-term
         | roadmap: richer geocoding output with house numbers and
         | (optionally) street/area geometry instead of just centerpoints.
        
           | dennis16384 wrote:
           | Why not package photon?
        
             | packet_mover wrote:
             | Photon is solid - but it comes with a very different
             | operational profile than what I am aiming for.
             | 
             | Photon is built on Elasticsearch (Java) - so it tends to
             | mean a heavier index + higher RAM/CPU expectations and more
             | moving parts. That's fine on a beefy server, but it is a
             | rough fit for the "drop-in appliance on small edge/on-prem
             | boxes (amd64/arm64) + simple ops" goal.
             | 
             | Corviont's geocoder is intentionally "boring": a single
             | SQLite file + an HTTP service, built from Nominatim-derived
             | data. Fast startup, low RAM, easy to ship per-region, and
             | it stays consistent with the rest of the stack.
             | 
             | That said - if there is demand for a "server-grade geocoder
             | option" for people already comfortable running Elastic, I
             | am not opposed to offering it as an alternative profile.
             | The default is just optimized for constrained edge hardware
             | and minimal moving parts.
        
       | dabreegster wrote:
       | Quite cool to see this space being explored!
       | https://github.com/headwaymaps/headway is another related
       | project.
        
         | packet_mover wrote:
         | Nice - thanks for the pointer. Headway is definitely a related
         | "self-hosted maps stack" project.
         | 
         | One place Corviont is trying to differentiate is the update
         | story for edge/fleet deployments: the goal is a signed,
         | resumable regional dataset updater (verify manifest -> atomic
         | swap -> reload/rollback) so boxes in the field can stay fresh
         | without manual rebuilds or "re-download the world" updates.
         | Headway (at least from a quick skim) looks more like "bring
         | your own data / regenerate when needed," which is totally fine
         | for servers, but fleets usually need something more automated.
         | 
         | If you've seen Headway (or similar) handle incremental/regional
         | updates well, I'd love to learn from it - updater design is the
         | big missing piece I'm validating demand for.
        
           | ikawe wrote:
           | (Headway maintainer here)
           | 
           | Indeed there is currently no incremental update in Headway,
           | and deployments are largely an exercise left to the reader.
           | 
           | For maps.earth (a Headway planet deployment), I typically
           | rebuild the world, and then do a blue/green deployment.
           | 
           | I guess the one exception is for transit routing. We have
           | individual transit zones small enough to fit into memory,
           | which can be deployed incrementally. There's nothing really
           | built in about it - just another level of indirection via our
           | "travelmux" service which redirects your routing queries to a
           | different backend depending on mode and region.
        
             | packet_mover wrote:
             | Thanks for chiming in - super helpful context.
             | 
             | I am trying to learn from real deployments as I design
             | Corviont's updater for edge boxes (bandwidth caps,
             | maintenance windows, unreliable WAN, atomic swap +
             | rollback).
             | 
             | When you say transit "zones" are small enough to deploy
             | incrementally - what is the actual artifact per zone
             | (roughly what format), and what sizes do you typically see?
             | 
             | And when a transit zone dataset changes, how do you roll
             | that out safely - do you restart/reload the backend that
             | serves that zone, or do you bring up a new backend/version
             | and then flip travelmux to point at it?
        
       | leros wrote:
       | Does this not require a massive database of tiles?
       | 
       | I ask because I've been looking to self host some sort of map
       | tile server and they seem to have database in the hundreds of GB.
        
         | packet_mover wrote:
         | Good question. Corviont is region-focused (you package one
         | region), not "host the whole planet". Hundreds of GB is usually
         | the full planet at high zoom / lots of layers.
         | 
         | Also it's not one giant tile DB - there are 3 datasets:
         | - map tiles (PMTiles)       - routing tiles (Valhalla tiles)
         | - geocoder index (SQLite)
         | 
         | For Monaco all three are tiny - you can see the exact files
         | here: https://github.com/corviont/monaco-demo/tree/main/data
         | 
         | For small countries like Austria/Slovakia, each is typically
         | hundreds of MB.
        
       | tomaskafka wrote:
       | I love it, thanks!
       | 
       | If I may have a feature request, I'd like to have only some of
       | the features turned on - in my case it would be just the reverse
       | geocoder (so I could skip the map and routing data download and
       | storage).
       | 
       | Right now I have my own reverse geocoder for
       | https://weathergraph.app which downloads OSM dumps and builds in-
       | memory KD tree for lookups. Surprisingly, the whole world can fit
       | in 3-4 GB of RAM, and service starts in 90 seconds on a cheap
       | VPS, no database needed, but of course, having a battle tested
       | solution that just works (and someone else maintains it) would
       | help.
        
         | packet_mover wrote:
         | Thank you! And yes, Corviont is intentionally a stack of
         | separable services behind one gateway - so "geocoder-only" is
         | exactly the kind of config I want to support (skip PMTiles +
         | Valhalla and ship only the SQLite index + reverse API).
         | 
         | Re: Weathergraph - thanks for the details. Since you already
         | run whole-world reverse geocoding on a single server, that's a
         | bit different from Corviont's current regional/fleet packaging
         | (where you ship only the area you need to each edge/on-prem
         | deployment). A "world geocoder-only" pack could still make
         | sense - but it's a different distribution/update story than my
         | default.
         | 
         | For your use case, do you want reverse results at the
         | city/region/country level - or do you also need street/house
         | number detail? That choice mostly determines how heavy a world
         | geocoder-only pack needs to be.
        
       | t0mk wrote:
       | I like how you packed only the necessities - tiles for maps,
       | routing, and geocoding index in in sqlite. I checked the monaco
       | deployment and missed lookup with street number, as someone else
       | also pointed out.
       | 
       | Why not create a "builder" repo, where people could generate
       | their own local datasets by a bounding box?
        
         | packet_mover wrote:
         | Yeah, house-number lookup is not there yet. The demo geocoder
         | does place/street-level search + reverse, but house numbers
         | need a richer address index - it's on the roadmap.
         | 
         | Re: a bbox "builder" repo - it's an interesting idea. I could
         | see it going two ways: (a) you want to run a bbox builder
         | yourself, or (b) you want a simple way to specify a bbox so the
         | dataset pack can be produced for you.
         | 
         | I started with the "ship a known-good pack" approach because
         | the build pipeline is the messy part, and I want deployed boxes
         | to stay simple/reproducible.
         | 
         | For your use case, which did you mean - run the build locally,
         | or "draw/paste a bbox and get back a ready-to-run pack"? And
         | would bbox be OK, or do you prefer admin boundaries
         | (country/state/city)?
        
       | onaclov2000 wrote:
       | Definitely interesting, I don't see an obvious comment on
       | hardware requirements, do you know what those are?
       | 
       | I've played around with OSRM, and Nominatim, etc, but had to do
       | some trickery to run on a raspberry pi.
       | 
       | (For anyone interested in running some of these kind of things on
       | a pi, I talk about it generally here, I need to post an update
       | with more info at some point.
       | http://blog.onaclovtech.com/2025/02/general-purpose-to-speci...)
        
       ___________________________________________________________________
       (page generated 2026-01-03 23:01 UTC)