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
Gallery
Asia
| China - Beijing | Japan - Tokyo | South Korea - Seoul | China - Hong Kong |
|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
| Singapore | Malaysia - Kuala Lumpur | Thailand - Bangkok | India - New Delhi |
|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
Europe
| Switzerland - Zurich | Norway - Oslo | Sweden - Stockholm | Denmark - Copenhagen |
|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
| Austria - Vienna | Germany - Berlin | United Kingdom - London | France - Paris |
|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
| Italy - Rome | Russia - Moscow | Turkey - Istanbul | Netherlands - Amsterdam |
|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
Americas, Africa & Oceania
| USA - New York | Canada - Ottawa | Brazil - Sรฃo Paulo | Mexico - Mexico City |
|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
| Argentina - Buenos Aires | Australia - Melbourne | South Africa - Cape Town | Chile - 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 through an Amap proxy, 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 uses the Amap geocoding API through a proxy endpoint at /api/amap-proxy/.
- Apply for your own Amap Web Service API key at the Amap Open Platform.
- Configure a proxy endpoint that forwards requests to
https://restapi.amap.com/v3/geocode/geo. - Open the
Pushpinsection in the app, paste the key, test it, then start searching.
Example Cloudflare Worker flow:
export default { async fetch(request: Request) { const url = new URL(request.url); const upstream = new URL("https://restapi.amap.com/v3/geocode/geo"); upstream.search = url.search; return fetch(upstream, { headers: { accept: "application/json", }, }); }, };
Notes:
- The current frontend assumes the proxy endpoint is
/api/amap-proxy/. - The frontend sends
key,address, andcityquery parameters to the proxy. - 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



























