Chiitiler is a tiny MapLibre server that renders raster tiles and map cut-outs from any MapLibre Style JSON, with built-in caching backends for source assets and a lightweight debug UI.
Chiitiler accepts remote or local style.json definitions and serves raster tiles or bounding-box images on demand. It was inspired by maptiler/tileserver-gl and developmentseed/titiler but is intentionally minimal, scriptable, and easy to self-host.
- Zero-config startup: point Chiitiler at a style URL or POST a style object to receive tiles.
- Optimized for ephemeral serverless runtimes such as AWS Lambda.
- Multiple cache adapters (
memory,file,s3,gcs) to cache shared source assets (MVT tiles, glyphs, sprites) and reduce redundant fetches. - Built-in
/debugand/editorpages to preview styles during development.
- MIERUNE/tiles – see the live example map.
- dayjournal/qgis-amazonlocationservice-plugin – powering QGIS integrations.
- PLATEAU VIEW – serving Cesium.js imagery through the
/tilesendpoint. - Allmaps Latest (Bluesky).
Chiitiler can load tiles, sprites, glyphs, and assets via:
http://andhttps://s3://(AWS S3 or compatible endpoints)gs://(Google Cloud Storage)file://mbtiles://pmtiles://cog://(Cloud Optimized GeoTIFF, CRS must beEPSG:3857)
src/
main.ts # CLI entry point and cluster bootstrap
cli.ts # Commander-based CLI definition
server/ # Hono HTTP server & debug UI
render/ # Rasterization and Sharp pipelines
cache/ # Cache adapters (none/memory/file/s3/gcs)
source/ # Helpers for reading external sources
tests/ # Vitest integration & benchmark suites
localdata/ # Sample styles and tiles for demos
cdk/ # AWS CDK deployment project
- Node.js 20.10.0 or newer (
.node-versionis provided). - System dependencies to support
sharp(see Dockerfile for reference).
git clone https://github.com/Kanahiro/chiitiler.git
cd chiitiler
npm install
npx tsx src/main.ts tile-server --port 3000 --debugWhen the server starts you can request a tile:
http://localhost:3000/tiles/0/0/0.png?url=https://tile.openstreetmap.jp/styles/osm-bright/style.json
docker pull ghcr.io/kanahiro/chiitiler:latest
docker run --rm -p 3000:3000 \
-e CHIITILER_CACHE_METHOD=memory \
-e CHIITILER_CACHE_TTL_SEC=600 \
ghcr.io/kanahiro/chiitiler:latestThe container entrypoint wraps node /app/build/main.cjs tile-server, so command-line options can be provided via env vars or by overriding the container CMD explicitly.
The included docker-compose.yml spins up MinIO and fake-gcs-server:
docker compose upVolumes mount localdata/ and .cache/ so test assets and cached source data persist between runs.
| Method | Path Pattern | Description |
|---|---|---|
| GET/POST | /tiles/{z}/{x}/{y}.{ext} |
Render a raster tile (png, jpeg, jpg, webp). |
| GET/POST | /clip.{ext} |
Render a bounding box image (png, jpeg, jpg, webp). |
| GET | /debug |
Style explorer UI (requires debug mode). |
| GET | /editor |
Lightweight style editor (requires debug mode). |
url– Required when using GET. Points to a MapLibre Style JSON.tileSize– Tile size in pixels (default512).quality– JPEG/WebP quality (default100).margin– Tile edge margin (default0).bbox– Bounding box for/clipasminLon,minLat,maxLon,maxLat.size– Longest edge of/clipoutput (default1024).
POST requests accept the style object directly in the JSON body ({ "style": { ... } }).
Enable streaming (Sharp pipeline without buffering) by setting CHIITILER_STREAM_MODE=true or passing --stream.
Chiitiler exposes a single command: tile-server.
npx tsx src/main.ts tile-server --help| Option | Description | Environment Fallback | Default |
|---|---|---|---|
--cache <none/memory/file/s3/gcs> |
Select cache backend. | CHIITILER_CACHE_METHOD |
none |
--cache-ttl <seconds> |
TTL for memory/file caches. | CHIITILER_CACHE_TTL_SEC |
3600 |
--memory-cache-max-item-count <n> |
Max items in memory cache. | CHIITILER_MEMORYCACHE_MAXITEMCOUNT |
1000 |
--file-cache-dir <dir> |
Disk cache directory. | CHIITILER_FILECACHE_DIR |
./.cache |
--s3-cache-bucket <name> |
S3 bucket for caching. | CHIITILER_S3CACHE_BUCKET |
"" |
--s3-region <region> |
S3 region used for requests. | CHIITILER_S3_REGION |
us-east1 |
--s3-endpoint <url> |
S3-compatible endpoint. | CHIITILER_S3_ENDPOINT |
"" |
--s3-force-path-style |
Force path-style requests. | CHIITILER_S3_FORCE_PATH_STYLE (true/false) |
false |
--gcs-cache-bucket <name> |
GCS bucket for caching. | CHIITILER_GCS_CACHE_BUCKET |
"" |
--gcs-project-id <id> |
GCP project ID. | CHIITILER_GCS_PROJECT_ID |
"" |
--gcs-key-filename <path> |
Service account JSON. | CHIITILER_GCS_KEY_FILENAME |
"" |
--gcs-cache-prefix <prefix> |
GCS object prefix. | CHIITILER_GCS_CACHE_PREFIX |
"" |
--gcs-api-endpoint <url> |
Custom GCS endpoint. | CHIITILER_GCS_API_ENDPOINT |
"" |
--port <number> |
HTTP listen port. | CHIITILER_PORT |
3000 |
--stream |
Enable streaming mode. | CHIITILER_STREAM_MODE |
false |
--debug |
Enable debug UI routes. | CHIITILER_DEBUG |
false |
Set CHIITILER_PROCESSES to control clustering (0 uses all CPUs). When >1, the primary process forks workers that all share the same cache adapter.
In addition to the CLI options above, the server respects:
| Variable | Default | Notes |
|---|---|---|
CHIITILER_PROCESSES |
1 |
Number of worker processes; 0 = availableParallelism(). |
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY |
– | Used by the S3 cache adapter. |
AWS_REGION |
– | Overrides SDK default region if set. |
GOOGLE_APPLICATION_CREDENTIALS |
– | Path to a service account JSON used by the GCS adapter. |
Chiitiler caches the source material required for rendering (vector tiles, glyphs, sprites, spritesheets), not the final raster outputs. These cached assets are reused across requests to avoid refetching upstream sources.
- none – No caching; every request renders from scratch.
- memory – In-memory LRU cache with configurable TTL and max entries.
- file – Stores fetched source assets under
CHIITILER_FILECACHE_DIR. - s3 – Uploads cached source assets to S3/MinIO; honors custom endpoint and path-style.
- gcs – Uploads cached source assets to Google Cloud Storage or
fake-gcs-server.
Each adapter exposes the same get/set interface and can be reused when embedding Chiitiler as a library.
Run with --debug or CHIITILER_DEBUG=true to unlock:
/debug– Inspect styles, test queries, and view response metadata./editor– Lightweight MapLibre style editor with live preview.
npm run dev # Watch mode via tsx
npm run build # Bundle to build/main.cjs with esbuild
npm run test:unit # Vitest unit suite (src/**/*.test.ts)
npm run test:integration # End-to-end scenarios in tests/
npm run test:coverage # Unit coverage with V8 provider
npm run test:benchmark # Performance tests (see BENCHMARK.md)Benchmark scenarios and recent measurements live in BENCHMARK.md.
Chiitiler is also published as an npm library. Core helpers return Sharp instances or encoded buffers so you can integrate the renderer into other pipelines.
import { createWriteStream } from 'node:fs';
import {
getRenderedTileBuffer,
getRenderedBboxBuffer,
getRenderedTileStream,
getRenderedBboxStream,
ChiitilerCache,
} from 'chiitiler';
const cache = ChiitilerCache.fileCache({ dir: './.cache', ttl: 3600 });
const tile = await getRenderedTileBuffer({
stylejson: 'https://tile.openstreetmap.jp/styles/osm-bright/style.json',
z: 5,
x: 27,
y: 12,
tileSize: 512,
margin: 0,
ext: 'webp',
quality: 100,
cache,
});
const clip = await getRenderedBboxBuffer({
stylejson: 'file://localdata/style.json',
bbox: [123.4, 34.5, 124.5, 35.6],
size: 1024,
ext: 'png',
quality: 95,
cache: ChiitilerCache.noneCache(),
});
// you can get Sharp streams directly
const tileStream = await getRenderedTileStream({
stylejson: 'https://tile.openstreetmap.jp/styles/osm-bright/style.json',
z: 5,
x: 27,
y: 12,
tileSize: 512,
margin: 0,
ext: 'png',
quality: 90,
cache,
});
const bboxStream = await getRenderedBboxStream({
stylejson: 'file://localdata/style.json',
bbox: [123.4, 34.5, 124.5, 35.6],
size: 1024,
ext: 'jpeg',
quality: 85,
cache,
});- AWS CDK – The
cdk/directory contains an AWS CDK app for provisioning Chiitiler on ECS/Fargate. Seecdk/README.mdfor stack details. - Docker – The provided
Dockerfileinstalls runtime dependencies forsharpand exposestile-serveras the default entrypoint. - Bench setups –
docker-compose.ymlprovisions MinIO, Fake GCS, and sample data for local smoke tests.
graph LR
subgraph sources
direction LR
A[style.json]
z/x/y.pbf
z/x/y.png/webp/jpg
sprite
glyphs
end
subgraph chiitiler
cache
render
server
end
sources --> cache --> render --> server --/tiles/z/x/y--> png/webp/jpg
cache <--get/set--> memory/file/S3