Skip to main content

tile57

Not for navigation

This project is coded almost entirely with AI (Claude) and human-reviewed. It is an experiment in building a large, complex specification (IHO S-101) with AI — not a certified or tested navigation product. Do not rely on it for real-world navigation. See Known limitations.

tile57 is a high-performance, low-memory S-57/S-101 → MVT vector-tile + S-52 style engine, embeddable from Zig, C, or Go, targeting native and WASM. It decodes IHO/NOAA S-57 ENC cells and generates Mapbox Vector Tiles by (z, x, y), running the official IHO S-101 Portrayal Catalogue in embedded Lua to produce S-52 nautical portrayal. Alongside the tiles it emits a MapLibre GL style and the portrayal assets it references — colour tables, line styles, and the sprite + area-fill pattern atlases — so a renderer such as MapLibre can draw a chart directly from tile57's output.

tile57 is the engine only: it produces tiles, a style, and assets. It does not draw to a screen — any MVT renderer can consume what it emits.

Goals

tile57 is an experiment in building a real, spec-faithful nautical chart engine almost entirely with AI assistance. A few specific goals shape its design:

  • AI-written, human-reviewed. Every significant piece of this codebase was generated by Claude and reviewed by a human. The project tests how far AI can carry the heavy lifting of spec interpretation, test coverage, and correctness on a non-trivial domain.

  • Spec adherence first. The goal is to implement S-57 decoding, S-101 portrayal, and S-52 display as faithfully as possible, using the actual IHO spec documents and the official Portrayal Catalogue — not approximations.

  • Cross-platform via Zig. Zig's build system and cross-compilation support let the same core compile to native (Linux, macOS, Windows) and WASM without code changes. Go and Zig were chosen specifically because both have excellent build systems and first-class WASM targets, making the engine usable in desktop apps, servers, and browsers from one codebase.

  • Coupled tile + style. The engine emits Mapbox Vector Tiles and a matching MapLibre GL style together. The same style works for MapLibre Native and MapLibre GL JS, so native and web renderers share one chart look without separate style maintenance.

  • Language-agnostic embedding. A thin C ABI (libtile57.a) bridges the Zig core to any language with C FFI. Go bindings ship in the repo; others are straightforward additions.

The pipeline

S-57 ENC cell (.000)
│ ISO 8211 decode src/iso8211/ (pkg: iso8211)

S-57 feature + geometry model src/s57/ (pkg: s57)
│ S-101 portrayal (embedded Lua) src/portray/ + src/s100/ (pkg: s100)

portrayal instruction stream
│ adapt + project + clip + encode src/{s57_mvt,tile,mvt,pmtiles}/

Mapbox Vector Tiles + MapLibre style.json + colortables / linestyles / sprite / patterns

Why tile57 is fast and small

The engine is high-performance and low-memory by design:

  • Lazy, per-cell work. A multi-cell ENC_ROOT is indexed cheaply (band + bbox); cells are parsed and portrayed only when a requested tile needs them, then held under an LRU bound. A streaming open reads a cell's bytes on demand (and frees them on eviction), so a host holds only the working set — not the whole catalogue.
  • Band-streamed bakes. Baking an ENC_ROOT to one PMTiles archive streams band-by-band (finest → coarsest, best-band dedup), so peak memory tracks the largest single band.
  • Pure-Zig core. The foundational format/encode packages (iso8211, s57, s100, mvt, tile, pmtiles) have no libc; only the Lua portrayal + the sprite rasterizer pull in C.

Portrayal

tile57 runs the official IHO S-101 Portrayal Catalogue — the real Lua rule files — in embedded Lua 5.4. The tiles carry S-52 colour tokens (never RGB), and the generated colortables.json resolves those tokens to Day / Dusk / Night hex, so a renderer can switch palette without regenerating tiles.

Where to go next