Skip to main content

Welcome Contributors

Thank you for your interest in contributing to MapToPoster! This guide will help you set up your development environment and understand the contribution workflow.
MapToPoster is a CLI-focused project. We welcome bug fixes and feature enhancements that align with the project’s minimalist design philosophy.

Contribution Philosophy

Before starting work, please review these guidelines:

✅ We Welcome

  • Bug fixes for rendering issues, crashes, or incorrect output
  • Performance improvements for data fetching or rendering speed
  • New themes with well-designed color palettes
  • Documentation improvements for clarity and completeness
  • New map layers (railways, buildings, etc.) that enhance poster quality
  • Internationalization improvements for better font/script support
  • Test coverage additions and improvements

❌ Please Don’t Submit

  • User interfaces (web apps, desktop GUIs, mobile apps)
    • MapToPoster is intentionally CLI-only to maintain simplicity
  • Dockerization for now
    • May be considered in the future, but not a current priority
  • Major architectural rewrites without prior discussion
    • Please open an issue or discussion first
Before working on large features, please ask in GitHub Discussions or open an issue to confirm it will be merged. This saves everyone’s time!

Development Setup

Prerequisites

  • Python 3.11 or higher (required since v0.3.0)
  • Git for version control
  • Text editor or IDE (VS Code, PyCharm, etc.)

Installation Methods

Traditional Python virtual environment setup:

Verify Installation

Test that everything is working:
You should see:
  1. Progress bars for data fetching
  2. Theme loading confirmation
  3. A new PNG file in posters/ directory

Project Structure

Understanding the codebase layout:

Key Files to Know


Making Changes

Development Workflow

1

Create a feature branch

Use clear branch names: fix/, feature/, docs/, test/
2

Make your changes

Edit the relevant files. See Architecture Overview for code structure.For bug fixes:
  • Identify the problematic function(s)
  • Add print statements or use a debugger to trace the issue
  • Fix the root cause, not just the symptom
For new features:
  • Follow existing code patterns (see Extension Points)
  • Add necessary theme properties to ALL theme JSON files
  • Update fallback values in load_theme() function
3

Test your changes

CRITICAL: Test before and after versions!
Test multiple scenarios:
  • Different cities (grid vs organic layouts)
  • Different themes (light vs dark backgrounds)
  • Different distances (small 4000m vs large 18000m)
  • Edge cases (coastal cities, islands, etc.)
4

Commit your changes

Use Conventional Commits format:
  • fix: for bug fixes
  • feat: for new features
  • docs: for documentation changes
  • test: for test additions
  • refactor: for code refactoring
5

Push and create PR

Then open a Pull Request on GitHub with:
  • Clear description of the problem/feature
  • Before/after screenshots for visual changes
  • Testing steps you performed
  • Any breaking changes or migration notes

Testing Guidelines

Manual Testing Checklist

Before submitting a PR, test these scenarios:
  • Basic poster generation works
  • Geocoding resolves city/country correctly
  • Cache is created and reused on second run
  • Theme loading works for all built-in themes
  • Error handling doesn’t crash the script
  • Roads render above water and parks (z-order bug fixed in PR #42)
  • Text is readable and properly positioned
  • Gradients blend smoothly at top/bottom
  • Aspect ratio is maintained (no distortion)
  • Line weights are consistent across zoom levels
  • Long city names don’t get cut off
  • Non-Latin scripts render correctly (test with Japanese/Arabic)
  • Custom coordinates override works
  • Invalid city/country shows helpful error
  • Network failures are handled gracefully
If possible, test on multiple platforms:
  • macOS
  • Linux
  • Windows
Focus on file path handling and font loading.

Test Coverage Areas

We don’t have formal unit tests yet (contributions welcome!), but manual testing should cover:
  1. Data Fetching: Verify OSMnx queries return expected data
  2. Rendering: Check layer composition and z-order
  3. Typography: Test Latin and non-Latin scripts
  4. Themes: Load all 17 themes successfully
  5. Caching: Confirm cache files are created and reused
  6. CLI Arguments: Test all flag combinations

Code Style Guidelines

Python Conventions

  • Formatting: Follow PEP 8 style guide
  • Line length: Max 120 characters (existing code uses ~100)
  • Docstrings: Use triple-quoted strings with clear descriptions
  • Type hints: Use when possible (see fetch_graph() return type at line 409)
  • Naming:
    • Functions: snake_case (e.g., get_edge_colors_by_type)
    • Classes: PascalCase (e.g., CacheError)
    • Constants: UPPER_CASE (e.g., FONTS_DIR, THEME)

Example Function

Comments

  • Use comments to explain why, not what
  • Complex algorithms should have explanatory comments
  • Reference issue numbers when fixing bugs:

Adding New Themes

Themes are the easiest way to contribute!

Creating a Theme

1

Design your color palette

Choose colors that work well together. Use tools like:Consider:
  • Background should contrast with roads
  • Water should be distinguishable from background
  • Road hierarchy should be visible (motorway darkest/lightest)
  • Text must be readable against background
2

Create JSON file

themes/my_theme.json
All fields are required. The theme won’t load if any are missing.
3

Test the theme

Test on cities with different characteristics:
  • Grid layouts (Barcelona, New York) - tests road hierarchy
  • Water-heavy (Venice, Amsterdam) - tests water/road contrast
  • Organic streets (Tokyo, Marrakech) - tests density rendering
4

Submit PR with examples

Include sample posters in your PR description:

Theme Design Tips

Road hierarchy matters! The difference between motorway and residential should be visually clear but not jarring. Aim for 15-20% brightness difference between adjacent levels.
Common mistakes to avoid:
  • Background and gradient color mismatch (causes visible seam)
  • Insufficient text contrast (hard to read city name)
  • Water too similar to background (loses definition)
  • All roads same color (loses street hierarchy)

Bug Fixes

Reporting Bugs

Before fixing a bug, check if it’s already reported in GitHub Issues. Good bug reports include:
  • MapToPoster version (check recent commits or tags)
  • Python version (python --version)
  • Operating system (macOS, Linux, Windows)
  • Full command you ran
  • Expected vs actual behavior
  • Error messages or stack traces
  • Sample poster showing the issue (if visual)

Example Bug Fix PR

See PR #42 for the road z-order fix: Problem: Roads were rendering below water/parks (issue #39) Solution: Adjusted z-order values:
Testing: Generated before/after posters for Venice (water-heavy) and Barcelona (road-heavy)

Common Development Tasks

Adding a New Map Layer

Example: Adding railway lines to posters
create_map_poster.py (after line 558)
Then render it (before roads, around line 594):
Don’t forget:
  1. Add "railway": "#...", to ALL theme JSON files (17 files)
  2. Update load_theme() fallback dict at line 186
  3. Update total in tqdm (line 526): total=4 instead of total=3
  4. Test with cities that have railways (Tokyo, Paris, London)

Modifying Road Styling

To change how roads are colored/sized:
  1. Color changes: Edit get_edge_colors_by_type() at line 255
  2. Width changes: Edit get_edge_widths_by_type() at line 289
  3. New road types: Add cases to both functions
Example - make motorways thicker:

Adjusting Typography

Text positioning uses normalized coordinates (0-1 range):
To move labels higher/lower, adjust the y values (second argument). Font sizes scale with poster dimensions (see create_map_poster.py:618-681):
To make text bigger, increase base_main, base_sub, etc.

Performance Optimization

If you’re working on performance improvements:

Profiling

Common Bottlenecks

  1. OSM data fetching: Already cached, but initial fetch is slow
    • Solution: No way around this, OSM API is the bottleneck
    • Use smallest effective distance
  2. Graph projection: ox.project_graph() can be slow for large graphs
    • Solution: Already optimized, but could cache projected graphs
  3. Matplotlib rendering: plt.savefig() at high DPI
    • Solution: Use lower DPI for previews, 300 DPI for final

Memory Usage

For very large cities (dist > 25km), memory usage can spike:

Getting Help

Stuck on something? Here’s where to ask:
  • GitHub Discussions: Best for questions about contributing, architecture, or design decisions
  • GitHub Issues: For bugs you’ve found (check existing issues first)
  • Code Comments: Read inline comments in create_map_poster.py - they explain complex logic
  • This Documentation: Architecture Overview has detailed technical info

Changelog & Version History

When your PR is merged, it will be added to CHANGELOG.md. See Keep a Changelog format. Recent significant changes:
  • v0.3.0 (2026-01-27): Custom coordinates, emerald theme, default theme changed to terracotta
  • v0.2.1 (2026-01-18): SVG/PDF export, variable dimensions, caching improvements
  • v0.1.0 (2026-01-17): Initial release with 17 themes
Community contributions (unreleased):
  • uv package manager support (PR #20)
  • Z-order bug fix (PR #42, fixes #39)
  • Text scaling for landscape orientations (#112)
See full history in CHANGELOG.md.

License & Attribution

MapToPoster uses data from OpenStreetMap contributors. All posters must include the OSM attribution (automatically added at bottom-right):
When contributing code, you agree to license it under the same terms as the project.

Thank You!

Every contribution - whether it’s a bug fix, new theme, documentation improvement, or feature enhancement - helps make MapToPoster better for everyone. Next Steps: Happy mapping! 🗺️