Self-hosting

Navii ships a production-ready Docker image. Single-process Hono app, no database, in-memory PNG cache. Tested on Hetzner; portable to any Node runtime, Bun, Deno, or Cloudflare Workers (with the wasm raster).

Docker

docker build -t navii-api packages/api
docker run -p 8787:8787 navii-api

The Dockerfile is multi-stage: pnpm install + build in stage 1, slim runtime in stage 2. Fonts (fonts-dejavu-core) are installed in the runtime image so resvg-js renders text properly in PNG/OG output.

Environment variables

VarDefaultDescription
PORT8787HTTP listen port.
HOST0.0.0.0HTTP bind address.
RATE_LIMIT_PER_MIN120 (engine) · 600 (hosted)Per-IP rate limit on /avatar/*. Engine default is 120 if unset; the hosted deployment at navii-api.uxderrick.com runs 600. See Rate limits for full details.
PNG_CACHE_SIZE500LRU capacity for rasterized PNG responses.
TRUST_PROXY0Set to 1 behind a reverse proxy you control (Caddy/Nginx). Enables X-Forwarded-For reading for rate-limit IP attribution. Never enable behind raw CDN — clients could spoof IPs.
NAVII_API_BASEhttps://navii-api.uxderrick.comUsed in landing + docs HTML for absolute API URLs (e.g. cast images, OG image).
NAVII_SITE_BASEhttps://navii.uxderrick.comPublic site URL. Used in canonical + OpenGraph meta.

Reverse proxy

A sample Caddyfile snippet lives at deploy/Caddyfile.snippet. It does the usual: TLS, gzip, forward to :8787, set X-Forwarded-For.

Per-domain routing (landing on navii.uxderrick.com, API on navii-api.uxderrick.com) is purely DNS + proxy concern — the Hono app handles both transparently.

Health check

GET /healthz returns { "ok": true, "pngCacheSize": N }. The Docker image declares a built-in HEALTHCHECK that hits this endpoint every 30 s.

Resource notes

  • SVG generation is essentially free (~microseconds per avatar).
  • PNG raster is the expensive op — depends on size. ~10–40 ms for 256 px on a small VPS, dominated by resvg's text + filter pipeline.
  • In-process PNG cache (LRU) absorbs repeated hits. Default 500 entries; tune via PNG_CACHE_SIZE.
  • For multi-replica horizontal scale, swap the rate-limit Map for Redis (current implementation is single-process).