Map poster pipeline for travlr-earth. Generates composited print and social-format map posters for any city — rendered with MapLibre GL JS on OpenStreetMap data via OpenFreeMap vector tiles.
A fork of Terraink by @yousifamanuel, stripped down to the core poster engine and rebuilt as a standalone pipeline for the travlr-earth ecosystem. The original UI, theming system, and poster compositor from Terraink provided the foundation this repo builds on. Full credit and respect to the Terraink team.
- 24 map themes — colour palettes for land, water, roads, text
- MapLibre GL JS vector tile renderer with OpenFreeMap source
- Poster compositor — map snapshot + vignette fades + city/country/coordinates typography overlay
- 35 export format specs — print (A5→A2, travel sizes), social (Instagram, TikTok, etc.), stories (9:16), wallpaper (16:9), web
- 7 batch export profiles — one-click ZIP bundles (Souvenir Print, Instagram Pack, Social Bundle, etc.)
- Formats: PNG, JPEG, WebP, PDF, layered SVG
- i18n foundation — UI strings in EN, NL, DE, FR, ES, JA
- Locale-aware font registry — 14 fonts covering Latin, CJK, mono, script categories
- Demo gallery at
/demo.html— all 24 themes rendered live with location picker
npm install
npm run dev # http://localhost:5173
# or for the demo gallery:
npx vite --port 5007
# then open http://localhost:5007/demo.htmlsrc/
engine core (keep, no UI coupling):
features/theme/domain + infrastructure — theme types, resolution
features/map/infrastructure — MapLibre style spec
features/poster/infrastructure/renderer — compositor (layers, typography)
features/export/infrastructure — PNG/JPG/WebP/PDF/SVG exporters
features/markers/infrastructure — marker canvas overlay
features/routes/infrastructure — GPX route canvas overlay
pipeline/ — batch export, format specs, profiles
shared/geo/ — coordinate math, bounds
shared/utils/ — color, string, number utils
i18n/ — locale strings (6 languages)
fonts/registry.ts — locale-aware font list
app (demo gallery as main UI):
demo/DemoApp.tsx — gallery with location picker + lightbox
demo/PosterRenderer.ts — offscreen MapLibre renderer (sequential)
demo/demo.css — dark gallery styling
The travlr web app (travlr-webpage) lets users export a diary marker or route as
a 1080×1920 share image. The request flows:
webpage share.js
→ Supabase Edge Function render-story (JWT-gated pass-through)
→ Fly.io worker mapimages-render/render (headless Playwright + MapLibre)
→ public bucket story-renders/renders/{sha256}.jpg (hash-keyed cache)
→ public CDN url back to the client
The worker (server/) serves render.html + the prebuilt render-lib.iife.js
bundle, drives a headless Chrome to run StoryShare.renderStoryCanvas, stores the
JPEG, and returns its public URL. The Edge Function only authenticates the caller
and forwards the request with the x-worker-secret header the worker checks.
One idempotent script does the whole pipeline — build, Fly deploy, bucket, and Edge Function secrets:
# from server/, with the service-role key in hand
# (Supabase Dashboard → Project Settings → API → service_role secret)
$env:SUPABASE_SERVICE_ROLE_KEY = "eyJ..."
./deploy.ps1It:
- Builds
server/public/render-lib.iife.js(npm run build:render) + compiles the worker (npm run build). - Deploys to Fly (
mapimages-render), settingSUPABASE_URL,SUPABASE_SERVICE_ROLE_KEY, and a generatedWORKER_SECRET. - Applies
supabase/setup.sql— creates the publicstory-rendersbucket + policies. - Sets the
render-storyEdge Function secretsRENDER_WORKER_URLandRENDER_SECRET(equal to the worker'sWORKER_SECRET, so their handshake matches). - Health-checks
GET /health.
Prerequisites: flyctl and supabase CLIs installed and authenticated
(fly auth login, supabase login).
Re-runs: safe and idempotent. Use -SkipSecrets for a code-only redeploy, or
-SkipWorker to only re-point the Edge Function. RENDER_SECRET is generated on
first run if not supplied and stored only on Fly + Supabase — never on disk.
Until RENDER_WORKER_URL is set, the Edge Function returns a clean
503 "Render worker URL not configured", so the share UI degrades gracefully.
This project is based on Terraink — an open-source map poster and wallpaper creator by Yousif Amanuel, licensed under AGPL-3.0. The map style system, poster compositor, typography renderer, and gradient fade logic were derived from Terraink's codebase and are used in accordance with the AGPL-3.0 license.
Map data © OpenStreetMap contributors. Vector tiles via OpenFreeMap.
AGPL-3.0 — same as the upstream Terraink project.