Spaces:
Running
Running
|
Download AGENTS.md from isaachwf/MapToPoster: direct link, hf CLI and curl.
- Browser
- Download file 8.1 kB
-
https://huggingface.co/spaces/isaachwf/MapToPoster/resolve/main/AGENTS.md
- Command line
-
hf download hf://spaces/isaachwf/MapToPoster/AGENTS.md
-
curl -L -o AGENTS.md https://huggingface.co/spaces/isaachwf/MapToPoster/resolve/main/AGENTS.md
8.1 kB
AGENTS.md - City Map Poster Generator
This file provides essential information for agentic coding agents working in the maptoposter repository.
Project Overview
A Python-based web application that generates beautiful, minimalist map posters for any place in the world. The product UI is React/Vite over FastAPI, while OSMnx and Matplotlib power the map pipeline.
Tech Stack:
- Python 3.12+
- React + Vite (primary web UI)
- FastAPI (application/API layer)
- OSMnx (street network analysis)
- Matplotlib (map rendering)
- GeoPandas (geospatial data)
- Nominatim (geocoding)
Build/Test/Lint Commands
Environment Setup
# Install dependencies with uv
uv sync --all-groups
corepack pnpm --dir frontend install --frozen-lockfile
Running the Application
# Start the API
uv run python app.py
# Start the frontend dev server in another terminal
corepack pnpm --dir frontend dev
# Or use the restart script (handles port conflicts)
bash restart.sh
# Development UI: http://localhost:5173
# Production-style UI/API: http://localhost:7860 after building frontend
Running Tests
# Run the full pytest suite
uv run pytest
# Run individual test functions
uv run pytest test_logic.py -k "china_hierarchy or manual_coordinates"
Development Utilities
# Verify city data integrity
uv run python verify_data.py
# Create map poster directly (CLI)
uv run python create_map_poster.py --city "Beijing" --country "China" --theme japanese_ink --output-format png
Code Style Guidelines
General Principles
- Bilingual Support: All user-facing text should support both English (en) and Chinese (cn)
- File Encoding: Use UTF-8 encoding with BOM for Chinese characters:
# -*- coding: utf-8 -*- - Function Documentation: Use docstrings for all public functions
- Error Handling: Provide meaningful error messages in both languages when possible
Import Organization
# Standard library imports first
import os
import json
import sys
from datetime import datetime
# Third-party imports next
from fastapi import FastAPI
import osmnx as ox
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from geopy.geocoders import Nominatim
# Local imports last
from cities_data import get_countries, get_provinces, get_cities
from create_map_poster import generate_map_poster
Naming Conventions
- Files:
snake_case.py(e.g.,cities_data.py,test_logic.py) - Variables/Functions:
snake_case(e.g.,get_available_themes(),motorway_color) - Constants:
UPPER_SNAKE_CASE(e.g.,THEMES_DIR,LAYER_KEYS) - Classes:
PascalCase(rare in this codebase, but follow convention if used)
Type Hints
def generate_output_filename(city: str, theme_name: str, output_format: str) -> str:
"""Generate unique output filename with city, theme, and datetime."""
pass
def get_theme_choices(lang: str = "en") -> list[tuple[str, str]]:
"""Return a list of (Display Name, Internal Name) tuples for themes."""
pass
String Patterns
- Language Keys: Use
lang="en"orlang="cn"parameters - Layer Constants: Define parallel arrays for different languages
LAYERS_EN = ["Motorway", "Primary Roads", "Secondary Roads", "Water", "Parks"]
LAYERS_CN = ["ι«ιε
¬θ·―", "δΈ»εΉ²ι", "欑干ι", "ζ°΄ε", "ε
¬ε"]
LAYER_KEYS = ["motorway", "primary", "secondary", "water", "parks"]
Data Structures
- City Hierarchy: Use tuples for display/internal name pairs:
[("Display Name", "internal_name"), ...] - Theme Files: JSON format with descriptive names:
{"name": "Theme Name", "bg": "#FFFFFF", ...} - Coordinates: Use
(lat, lon)tuple format
Directory Structure
maptoposter/
βββ app.py # FastAPI + built frontend entry point
βββ Dockerfile # Hugging Face production container
βββ create_map_poster.py # Core poster generation logic
βββ cities_data.py # City/province/district data management
βββ test_logic.py # Test suite for data logic
βββ verify_data.py # Data integrity verification
βββ backend/ # FastAPI schemas and endpoints
βββ frontend/ # React/Vite editor
βββ docs/ # Deployment and maintenance guides
βββ .github/workflows/ # Validation and Space publishing
βββ src/maptoposter/ # Typed core, cache, renderer, resources
βββ themes/ # JSON theme configuration files
βββ fonts/ # Font files (Chinese and English)
βββ posters/ # Generated poster outputs
βββ public/ # Static assets and demo images
βββ restart.sh # Development restart script
Common Patterns
Language Support
def translate(text: str, lang: str = "en") -> str:
"""Simple translation wrapper."""
translations = {
"en": {"City": "City", "Theme": "Theme"},
"cn": {"City": "εεΈ", "Theme": "δΈ»ι’"}
}
return translations.get(lang, {}).get(text, text)
File Path Handling
THEMES_DIR = "themes"
FONTS_DIR = "fonts"
POSTERS_DIR = "posters"
# Always check existence
if not os.path.exists(THEMES_DIR):
return []
FastAPI Endpoint Patterns
@app.get("/api/v1/health")
def health() -> dict[str, str]:
"""Return service readiness and version information."""
return {"status": "ok", "version": __version__}
Testing Guidelines
Test Structure
- Use pytest tests with focused fixtures and mocks
- Group related tests in modules/functions (e.g.,
test_china_hierarchy()) - Test both data integrity and coordinate retrieval
- Include Chinese characters in test data
Test Execution
# Run all tests
uv run pytest
# The exact count grows with the maintained suite; require zero failures.
Error Handling
Common Patterns
# File not found handling
if not os.path.exists(font_path):
print(f"β Font not found: {font_path}")
continue
# API error handling
try:
result = geocoder.geocode(city)
except Exception as e:
print(f"β Geocoding failed for {city}: {e}")
return None
# Data validation
assert len(provinces) > 30, f"Expected >30 provinces, found {len(provinces)}"
Performance Considerations
- Caching: OSMnx caching is enabled:
ox.settings.use_cache = True - Large Cities: Be aware that Beijing/Shanghai may have centering issues
- Small Cities: Some layers may be empty due to missing OSM data
- Memory: Clear matplotlib figures after generation to prevent memory leaks
Font Management
The project supports both English and Chinese fonts:
- English: Goudy Old Style (Regular, Bold)
- Chinese: HYWenRunSongYunU.ttf
Always verify font availability before use:
if os.path.exists(font_path):
font = FontProperties(fname=font_path)
else:
print(f"β Font not found: {font_path}")
font = None
Theme Development
Themes are JSON files in the themes/ directory with the following structure:
{
"name": "Theme Display Name",
"description": "Brief description",
"bg": "#FFFFFF",
"text": "#000000",
"water": "#E0E0E0",
"parks": "#F0F0F0",
"road_motorway": "#FF0000",
"road_primary": "#333333",
"road_secondary": "#666666",
"road_tertiary": "#999999",
"road_residential": "#CCCCCC",
"road_default": "#888888"
}
Development Notes
- Port Management: Default port is 7860. Use
restart.shto handle conflicts - Output Directory: Generated posters go to
posters/(auto-created if needed) - Debugging: Use print statements with emoji indicators for important events
- Code Organization: Keep API routes in
backend/, UI code infrontend/, and domain logic insrc/maptoposter/ - Deployment: GitHub
mainis mirrored to the Docker Space only after CI validation - Dependencies: The project uses
uvfor dependency management. Lock file isuv.lock