Skip to content

About

Full-stack web application for creating beautiful, print-ready map posters. Built with React, FastAPI, and OpenStreetMap data.

Resources

Stars

6 stars

Watchers

0 watching

Forks

Repository files navigation

Map2Poster

Transform any city into a stunning, print-ready map poster.

A full-stack web application for creating high-resolution map posters of cities worldwide. Built with React, FastAPI, and powered by OpenStreetMap data.

ko-fi

Map2Poster Demo


Screenshots

Toronto — Blueprint theme

Toronto — Midnight Blue theme

Washington — Neon Cyberpunk theme


Features

  • 18 Themes — From minimalist noir to vibrant neon cyberpunk, with full custom color override support
  • Real-Time SVG Preview — Watch your map render layer-by-layer; switch themes and colors instantly without re-fetching data
  • Global Coverage — Generate maps for any city in the world using OpenStreetMap data via OSMnx
  • 4 Formats — Vertical Poster (3:4), Horizontal Poster (4:3), Desktop Wallpaper (16:9), Phone Wallpaper (9:16) — all at 300 DPI
  • Layer Controls — Toggle motorways, primary/secondary/tertiary roads, water, ocean, and parks independently
  • Smart Caching — Two-level cache (raw OSM data + rendered preview) with optional Supabase cloud backup
  • History — Automatically saves SVG thumbnails and metadata with one-click restoration

Self-Hosting Guide

Map2Poster runs as two processes: a Python backend (FastAPI) that fetches OSM data and generates maps, and a React frontend (Vite) that provides the UI. Both run locally with no external services required.

Prerequisites

  • Python 3.8+ (3.11 recommended)
  • Node.js 16+ (18+ recommended)
  • pip (Python package manager)
  • GDAL/GEOS/PROJ system libraries (required by GeoPandas/Shapely)

Installing System Dependencies

macOS (via Homebrew):

brew install gdal geos proj

Ubuntu/Debian:

sudo apt-get install -y libgdal-dev libgeos-dev libproj-dev gcc g++

Windows: Install via OSGeo4W or use WSL with the Ubuntu instructions above.

Installation

  1. Clone the repository

    git clone https://github.com/ScottySalvo/Map2Poster.git
    cd Map2Poster
  2. Install Python dependencies

    pip install -r requirements.txt
  3. Install frontend dependencies

    cd frontend
    npm install
    cd ..

Running Locally

You need two terminals — one for the backend, one for the frontend.

Terminal 1 — Backend:

python api.py

The API server starts at http://localhost:8000. You should see:

⚠️ API: Cloud storage unavailable: ...
INFO:     Uvicorn running on http://0.0.0.0:8080

The cloud storage warning is normal — it just means Supabase isn't configured, so caching uses local disk only.

Terminal 2 — Frontend:

cd frontend
npm run dev

The frontend starts at http://localhost:5173. Open this URL in your browser.

The frontend automatically connects to http://localhost:8000 for the API (configured in frontend/src/config.js).

That's It

Enter a city and country, click Create Preview, and your map will generate. No API keys, no accounts, no external services needed. All data comes from the free OpenStreetMap Overpass API.

A note on generation speed: Map generation speed is largely dependent on the Overpass API (OpenStreetMap's public data server), which processes and returns road, water, park, and coastline data. The application itself is optimized — data is fetched in parallel, geometry processing is batched and vectorized, and a two-level cache ensures repeat requests are near-instant — but the Overpass API response time is the primary bottleneck and is outside the application's control.


Optional: Cloud Storage (Supabase)

By default, generated maps and cache are stored locally in posters/ and cache/ directories. For persistence across deploys (or if self-hosting on ephemeral infrastructure), you can optionally connect Supabase:

  1. Create a free Supabase project
  2. Create two storage buckets: map-cache and posters
  3. Copy .env.example to .env and fill in your credentials:
    cp .env.example .env
    SUPABASE_URL=https://your-project-id.supabase.co
    SUPABASE_KEY=your-anon-key-here
  4. Restart the backend — you should see ☁️ API: Cloud storage enabled

Optional: Production Deployment

For deploying to the internet (not just local use):

Backend (Railway, Render, Fly.io, etc.)

A Dockerfile and railway.json are included. Set these environment variables:

Variable Description Example
FRONTEND_URL Your frontend URL (for CORS) https://your-app.vercel.app
CUSTOM_DOMAIN Custom domain if applicable https://your-domain.com
SUPABASE_URL Supabase project URL https://xxx.supabase.co
SUPABASE_KEY Supabase anon key eyJ...

Frontend (Vercel, Netlify, etc.)

Set this build-time environment variable:

Variable Description Example
VITE_API_URL Your backend URL https://your-backend.up.railway.app

The frontend is a standard Vite/React app. Build with npm run build in the frontend/ directory.


Architecture

Map2Poster/
├── api.py                      # FastAPI server
├── create_map_poster.py        # Map generation engine
├── supabase_storage.py         # Cloud storage adapter (optional)
├── requirements.txt
├── Dockerfile
├── railway.json                # Railway deployment config
├── .env.example                # Environment variable template
├── themes/                     # 18 theme JSON files
├── fonts/                      # Custom fonts for poster text
├── data/                       # Natural Earth ocean shapefile
├── frontend/
│   ├── src/
│   │   ├── App.jsx             # Main application
│   │   ├── App.css             # Styles
│   │   ├── config.js           # API URL configuration
│   │   ├── components/
│   │   │   ├── MapPreviewSVG.jsx   # SVG map renderer
│   │   │   ├── MobileLayout.jsx    # Mobile-responsive layout
│   │   │   ├── HistoryModal.jsx    # History browser
│   │   │   └── FormatSelector.jsx  # Format picker
│   │   └── main.jsx
│   └── package.json
├── posters/                    # Generated output (auto-created)
└── cache/                      # Local disk cache (auto-created)

API Endpoints

Method Endpoint Description
POST /start-preview Start async preview generation
POST /start-generate Start async high-res poster generation
POST /start-restore Restore a map from history
GET /job-status/{id} Poll job progress
GET /themes List available themes
GET /history List saved previews
DELETE /history/{filename} Delete a history entry
POST /purge-cache Clear all caches and storage

Data Pipeline

  1. Geocode city name to coordinates (Nominatim)
  2. Fetch roads, water, parks, ocean data in parallel (OSMnx/Overpass API)
  3. Process ocean coastlines via polygonization, subtract ocean from parks
  4. Transform geometries to SVG paths using vectorized NumPy operations
  5. Render preview as JSON with SVG path data (frontend renders via React SVG)
  6. Generate high-res PNG via Matplotlib at 300 DPI (on demand)
  7. Cache at both raw data and rendered output levels

Available Themes

Autumn, Blueprint, Contrast Zones, Copper Patina, Crimson Noir, Feature Based, Forest, Gradient Roads, Japanese Ink, Midnight Blue, Monochrome Blue, Neon Cyberpunk, Noir, Ocean, Pastel Dream, Sunset, Terracotta, Warm Beige


Contributing

This project is open source and community-driven. Contributions are welcome!

  • Pull requests: Fork the repo, make your changes, and submit a PR
  • Theme contributions: Add a new JSON file to themes/ following the existing format

Project History

This project began as a Python CLI script by Ankur Gupta and has been rebuilt into a full-stack web application.

Original Map2Poster
Interface CLI Web app
Preview None Real-time SVG
Formats 1 4
Themes 1 18
Caching None Two-level + cloud

Acknowledgments

Built upon foundational work by Ankur Gupta who created the original map poster generation script.

Created by Scotty Salvo.

Map data from OpenStreetMap contributors.


License

MIT License — see LICENSE for details.


Support

If you find this project useful, consider buying me a coffee:

ko-fi

About

Full-stack web application for creating beautiful, print-ready map posters. Built with React, FastAPI, and OpenStreetMap data.

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages