Welcome to the MapToPoster developer guide! This document explains how to set up the development environment, configure the codebase, and understand the application's core architecture.
MapToPoster consists of a Python command-line map renderer, a FastAPI REST API (with an asynchronous sequential job queue), and a Next.js single-page web app.
Ensure you have the following tools installed on your local machine:
- Node.js (v18.0.0 or higher) and
npm - Python (v3.11 or higher)
- uv (v0.1.0 or higher) — Astrals' ultra-fast Python package installer
- Install on macOS/Linux via Homebrew:
brew install uv - Install via curl:
curl -LsSf https://astral.sh/uv/install.sh | sh
- Install on macOS/Linux via Homebrew:
We have provided a custom setup script that configures virtual environments, installs Python and Node dependencies, and creates template configuration .env files automatically.
- Clone & Navigate to the repository.
- Run the setup script:
./setup_dev.sh
- Start the developer services:
./start_dev.sh
start_dev.sh spins up both:
- FastAPI Backend: http://localhost:8000 (Interactive Swagger Docs:
/api/swagger) - Next.js Frontend: http://localhost:3000
Press Ctrl+C in the terminal to gracefully shut down both services.
| Variable | Description | Default |
|---|---|---|
ALLOWED_ORIGINS |
CORS allowed origins (comma-separated) | http://localhost:3000 |
CACHE_DIR |
Directory for geocoding & map features caching | ../../cache |
| Variable | Description | Default |
|---|---|---|
BACKEND_URL |
Endpoint of the FastAPI backend server | http://localhost:8000 |
NEXT_PUBLIC_SITE_URL |
Canonical URL of the frontend website | http://localhost:3000 |
MapToPoster/
├── create_map_poster.py # Core map rendering engine (matplotlib + OSMnx)
├── font_management.py # Google Fonts loader and downloader
├── setup_dev.sh # One-click environment setup script
├── start_dev.sh # Concurrent developer services runner
├── DEVELOPMENT.md # This developer guide
├── EXAMPLES.md # API integration code samples
├── pyproject.toml # uv/python project metadata & requirements
├── themes/ # Curated theme JSON files
├── fonts/ # Custom fonts directory (Roboto + caches)
├── posters/ # Outputs directory for generated map posters
└── web/
├── backend/
│ ├── main.py # FastAPI REST application & Sequential Worker Queue
│ └── requirements.txt
└── frontend/
├── package.json
├── next.config.ts
└── src/
├── app/ # Next.js Pages & Proxying (/api/[...proxy]/route.ts)
└── components/ # UI Elements (Header, Footer, ScrollReveal)
┌────────────────────────┐
│ Next.js Web UI │ (localhost:3000)
└────────────────────────┘
│
▼ (Next.js API route proxying)
┌────────────────────────┐
│ FastAPI Server │ (localhost:8000)
└────────────────────────┘
│
▼ (Job Submission)
┌────────────────────────┐
│ Sequential Worker Queue│ (Thread-safe background worker loop)
└────────────────────────┘
│
▼ (Calls)
┌────────────────────────┐
│ create_map_poster.py │ (Generates maps with Nominatim + OSMnx)
└────────────────────────┘
Fetches spatial features (streets, water bodies, park polygons) using the OSMnx library from OpenStreetMap APIs, scales road widths and highlights coordinates using geopandas, and draws high-resolution posters with custom typography through matplotlib.
Matplotlib and geocoding resources contain global variables that are not thread-safe. To handle concurrent API requests safely, the backend:
- Receives requests via
/api/generateand assigns a UUID (job_id). - Appends the job request into an in-memory sequential queue (
_job_queue). - A background worker loop processes jobs one-by-one to avoid state corruption.
- Clients poll
/api/jobs/{job_id}until status isdone, returning the poster image encoded in base64.
To prevent CORS preflight requests in production, Next.js uses an catch-all proxy route. Any requests to /api/* on port 3000 are automatically forwarded to BACKEND_URL/api/* on the server-side.