Skip to content

travlr-earth/mapimages

 
 

Repository files navigation

mapimages

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.

What this is

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.

What's inside

  • 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

Quick start

npm install
npm run dev          # http://localhost:5173
# or for the demo gallery:
npx vite --port 5007
# then open http://localhost:5007/demo.html

Architecture

src/
  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

Story-share render pipeline

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.

Deploy

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.ps1

It:

  1. Builds server/public/render-lib.iife.js (npm run build:render) + compiles the worker (npm run build).
  2. Deploys to Fly (mapimages-render), setting SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, and a generated WORKER_SECRET.
  3. Applies supabase/setup.sql — creates the public story-renders bucket + policies.
  4. Sets the render-story Edge Function secrets RENDER_WORKER_URL and RENDER_SECRET (equal to the worker's WORKER_SECRET, so their handshake matches).
  5. 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.

Credits

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.

License

AGPL-3.0 — same as the upstream Terraink project.

About

Terraink: The Cartographic Poster Engine that creates unique and customizable map posters

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages

  • TypeScript 88.8%
  • CSS 5.5%
  • JavaScript 2.4%
  • PowerShell 1.7%
  • HTML 1.4%
  • Dockerfile 0.2%