TypeScript MIT

maptoposter-online

✨❤️‍🔥Turn the cities you love into stunning designs

I

ianho7

Dernière activité 3 août 2026
ianho7/maptoposter-online

946

étoiles

44

forks

1

issues ouvertes

designfrontendmapsopenstreetmapposterreactrusttailwindcsstypescriptvisualdesignvitewasmwebassembly

Ce README est souvent en anglais.

MapPoster Online

MapPoster Online

Turn the cities you love into stunning designs

English | 简体中文


Project Description

A browser-based upgrade to maptoposter (Python CLI) — no installation needed, just open and go

React TypeScript Tailwind CSS Bun Rust License

Asia

China - Beijing Japan - Tokyo South Korea - Seoul China - Hong Kong
Beijing Tokyo Seoul Hong Kong
Singapore Malaysia - Kuala Lumpur Thailand - Bangkok India - New Delhi
Singapore Kuala Lumpur Bangkok New Delhi

Europe

Switzerland - Zurich Norway - Oslo Sweden - Stockholm Denmark - Copenhagen
Zurich Oslo Stockholm Copenhagen
Austria - Vienna Germany - Berlin United Kingdom - London France - Paris
Vienna Berlin London Paris
Italy - Rome Russia - Moscow Turkey - Istanbul Netherlands - Amsterdam
Rome Moscow Istanbul Amsterdam

Americas, Africa & Oceania

USA - New York Canada - Ottawa Brazil - São Paulo Mexico - Mexico City
New York Ottawa Sao Paulo Mexico City
Argentina - Buenos Aires Australia - Melbourne South Africa - Cape Town Chile - Santiago
Buenos Aires Melbourne Cape Town Santiago

Features

  • 🚀 Zero installation — Runs entirely in the browser. Open the site, pick a city, and download your poster
  • ⚡ Rust/WASM rendering engine — High-performance map rendering compiled from Rust to WebAssembly (powered by tiny-skia)
  • 👁️ Live preview — See changes instantly and confirm results before exporting
  • 🎨 20 built-in themes — From frozen Nordic minimalism to cyberpunk neon, vintage nautical to glitch purple
  • ✏️ Custom color controls — Fine-tune every color: background, roads, water, green spaces, POIs, and text
  • 📍 Custom POI pushpins — Search places with Amap, save your own POIs, and render them on the exported poster
  • 📐 Multiple export formats — A4 (portrait/landscape), square, phone wallpaper, desktop 16:9, at 300 DPI for high-quality print
  • 🌐 Multi-language interface — Supports English, Japanese, Korean, Simplified Chinese, German, Spanish, and French
  • 💾 IndexedDB caching — Previously fetched map data is cached locally for faster regeneration
  • 🔤 Dynamic font loading — Use built-in serif fonts or upload your own TTF/OTF files
  • 🐍 Snake game — Beat boredom while waiting for your poster to generate (inspired by Chrome Dinosaur Game)

How it differs from maptoposter (Python CLI)

This project was inspired by maptoposter (Python CLI) — they each have their own strengths for different use cases:

maptoposter-online maptoposter (Python CLI)
Usage Open in browser, no install needed Command-line interface, requires local setup
Best for Quick start, on-the-go usage Command-line enthusiasts, advanced local customization
Rendering engine Rust/WASM (tiny-skia) Python/matplotlib
Platform Cross-browser, any device Desktop only (requires Python)

Different tech stacks, same goal — turning your favorite city into unique art.

Local Development

Tech Stack

  • Build — Vite 7 + Bun
  • Frontend — React 19 + TypeScript
  • Styling — Tailwind CSS v4
  • UI components — Radix UI + lucide-react
  • Map data — OpenStreetMap (Overpass API) + Protomaps
  • Rendering — Rust (wasm-pack) + tiny-skia
  • i18n — @inlang/paraglide-js
  • Caching — IndexedDB (idb)

Requirements

Setup

# 1. Install dependencies
bun install

# 2. Build the Rust/WASM rendering engine
# Compile Rust to WebAssembly using wasm-pack
cd wasm && wasm-pack build --target web --out-dir ../src/pkg
# Or use the npm script:
bun run build:wasm

# 3. Start the dev server
bun run dev

# 4. App available at http://localhost:5173

Available Scripts

Command Description
bun run dev Start dev server
bun run build Build for production
bun run build:wasm Rebuild WASM engine
bun run preview Preview production build
bun run lint Run linter
bun run fix Format + lint with auto-fix

Custom POI Setup

The custom POI dialog calls the Amap place-search API directly from the browser.

  1. Apply for your own Amap Web Service API key at the Amap Open Platform.
  2. Open the Pushpin section in the app, paste the key, test it, then start searching.

Notes:

  • Users must provide their own Amap key. Free-tier limits are managed by Amap.

Engineering Notes

Rendering Engine — Rust/WASM

  • Font anti-aliasing — 2× supersampling + Box Filter downsampling
  • Road hierarchy lacking depth — Road casing rendered in two passes (stroke first, then fill) + Z-order controls draw sequence by road class
  • Rendering too slow — Douglas-Peucker in screen coordinate space removes subpixel redundancy; single-scan dispatch by feature type

Data Processing

  • Python OSMnx workflow ported — Professional geospatial data processing logic adapted from osmnx
  • Overpass query failures — Auto-splits oversized areas into smaller chunks (2500km² default limit) to prevent Overpass failures
  • Single node timeout causing long waits — Concurrent requests to 4 mirror servers, fastest response wins

Page Responsiveness

  • Generation blocking the page — Data fetching, projection transforms, and WASM rendering all run in a Web Worker; road precision auto-reduces at large radii
  • Repeated generation taking too long — IndexedDB Gzip-compressed cache, ~100KB per city; direct read on regeneration

License

MIT License — see LICENSE

💖 Support

If this project has saved you time or made your life easier, consider buying me a coffee. Your support is the driving force behind the continued maintenance of this project!

Platform Payment Method Link
Afdian WeChat / Alipay 👉 Click to Sponsor
Buy Me a Coffee Credit Card / Apple Pay / Google Pay 👉 Click to Sponsor

Acknowledgments

Inspired by @originalankur's maptoposter

Map data provided by OpenStreetMap and Protomaps

Font LXGW Neo ZhiSong (霞鹜新致宋) by lxgw, licensed under IPA Font License 1.0

Cold-Start Performance Regression Test

scripts/record-cold-start.ps1 launches a fresh headless Chrome profile for each run and records cold-start navigation, long-task, and main-thread timing through the Chrome DevTools Protocol.

Requirements: Windows PowerShell 5.1+ and Google Chrome installed at C:\Program Files\Google\Chrome\Application\chrome.exe (or pass -ChromePath). Build and start the production preview before running the script:

bun run build
bun run preview -- --host localhost --port 4173

In a second terminal, collect a three-run summary:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts\record-cold-start.ps1 -Runs 3 -Summary

Use thresholds to turn it into a regression test. The command exits with code 1 when any run exceeds a supplied limit:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts\record-cold-start.ps1 `
  -Runs 3 -Summary -MaxLoadMs 800 -MaxLongTaskMs 300 -MaxTaskDurationMs 3000

-MaxLoadMs checks the page load event, -MaxLongTaskMs checks the largest browser long task, and -MaxTaskDurationMs checks Chrome's cumulative main-thread task duration. Set a threshold to 0 (the default) to disable that check. Omit -Summary to retain the detailed per-resource JSON record.

This is a browser-level regression test, not a hermetic unit test: map tiles, IP geolocation, and other external requests can vary by network. Use it locally or in scheduled monitoring first; a blocking CI gate should use mocked external endpoints and a calibrated baseline.

Projets similaires

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

TypeScriptmapsopenstreetmapposter
Yyousifamanuel
4,1 k étoiles431

Beautiful map components. 100% Free, Zero config, one command setup.

TypeScript
AAnmolSaini16
12,2 k étoiles717

Transform your favorite cities into beautiful, minimalist designs. MapToPoster lets you create and export visually striking map posters with code.

Pythondesignmapsmatplotlib-pyplot
Ooriginalankur
14,2 k étoiles1,3 k