MapToPoster themes are defined as JSON files in the themes/ directory. Creating custom themes is simple and requires no code changes.
Theme Structure
Complete Schema
A theme JSON file contains 11 required properties:
{
"name" : "My Custom Theme" ,
"description" : "A brief description of the theme aesthetic" ,
"bg" : "#FFFFFF" ,
"text" : "#000000" ,
"gradient_color" : "#FFFFFF" ,
"water" : "#C0C0C0" ,
"parks" : "#F0F0F0" ,
"road_motorway" : "#0A0A0A" ,
"road_primary" : "#1A1A1A" ,
"road_secondary" : "#2A2A2A" ,
"road_tertiary" : "#3A3A3A" ,
"road_residential" : "#4A4A4A" ,
"road_default" : "#3A3A3A"
}
Property Reference
Display name of the theme (used in --list-themes output)
Brief description of the aesthetic and use case
Background color for the entire poster
Color for city name, country name, and coordinates text
Color used for top/bottom gradient fade effect. Usually matches bg for subtle fade.
Color for water features (rivers, lakes, ocean)
Color for parks and green spaces
Color for major highways and motorways (thickest roads)
Color for primary roads and main streets
Color for secondary roads
Color for residential streets (thinnest roads)
Fallback color for roads without specific classification
Creating a Custom Theme
Step 1: Create JSON File
Create a new .json file in the themes/ directory:
touch themes/my_theme.json
The filename (without .json) becomes the theme identifier used with --theme.
Step 2: Define Colors
Add your color palette:
{
"name" : "My Custom Theme" ,
"description" : "Dark background with vibrant green roads" ,
"bg" : "#1A1A1A" ,
"text" : "#FFFFFF" ,
"gradient_color" : "#1A1A1A" ,
"water" : "#0A2F3F" ,
"parks" : "#2A3A2A" ,
"road_motorway" : "#00FF00" ,
"road_primary" : "#00DD00" ,
"road_secondary" : "#00BB00" ,
"road_tertiary" : "#009900" ,
"road_residential" : "#007700" ,
"road_default" : "#009900"
}
Step 3: Use Your Theme
Reference by filename (without .json):
python create_map_poster.py -c "Paris" -C "France" -t my_theme
Design Guidelines
Road Hierarchy
Roads should follow a visual hierarchy from major to minor:
road_motorway → Most prominent (highways, interstates)
road_primary → Very visible (main streets)
road_secondary → Visible (major roads)
road_tertiary → Subtle (minor roads)
road_residential → Most subtle (local streets)
Visual Weight Strategies:
Gradient (Recommended)
Saturation
Opacity (via Alpha)
Two-Tone
Use a smooth gradient from dark to light: "road_motorway" : "#000000" , // Darkest
"road_primary" : "#2A2A2A" ,
"road_secondary" : "#555555" ,
"road_tertiary" : "#808080" ,
"road_residential" : "#AAAAAA" // Lightest
Best for: Most themes, creates natural depthUse a single hue with varying saturation: "road_motorway" : "#FF0000" , // Full saturation
"road_primary" : "#DD3333" ,
"road_secondary" : "#BB6666" ,
"road_tertiary" : "#AA8888" ,
"road_residential" : "#99AAAA" // Desaturated
Best for: Colorful themes, artistic aestheticsNote: Hex colors don’t support alpha in the current implementation. Use lightness instead: "road_motorway" : "#0066CC" , // Full color
"road_primary" : "#3385D6" , // Lighter
"road_secondary" : "#66A3E0" ,
"road_tertiary" : "#99C2EA" ,
"road_residential" : "#CCE0F4" // Very light
Use one color for major roads, another for minor: "road_motorway" : "#FF00FF" , // Accent color
"road_primary" : "#00FFFF" , // Accent color
"road_secondary" : "#00DDDD" , // Transition
"road_tertiary" : "#00BBBB" , // Base color
"road_residential" : "#009999" // Base color
Best for: Bold, high-contrast themes (cyberpunk, neon)
Contrast & Readability
Background vs. Roads:
Ensure sufficient contrast between bg and road colors
Test with both dense cities (many roads) and sparse cities (few roads)
Background vs. Text:
Text must be clearly readable against bg
Aim for WCAG AA contrast ratio (4.5:1 minimum)
Water & Parks:
Should be distinguishable from bg but subtle
Usually slightly lighter or darker than bg
Color Harmony
Use a single hue with varying lightness/saturation: {
"bg" : "#F5F8FA" , // Very light blue
"text" : "#1A3A5C" , // Dark blue
"water" : "#D0E0F0" , // Light blue
"parks" : "#E0EAF2" , // Very light blue
"road_motorway" : "#1A3A5C" , // Dark blue
"road_primary" : "#2A5580" ,
"road_secondary" : "#4A7AA8" ,
"road_tertiary" : "#7AA0C8" ,
"road_residential" : "#A8C4E0"
}
Examples: Monochrome Blue, Ocean
Use adjacent colors on the color wheel: {
"bg" : "#FDF5F0" , // Warm cream
"text" : "#C45C3E" , // Orange-red
"water" : "#F0D8D0" , // Pink
"parks" : "#F8E8E0" , // Peach
"road_motorway" : "#C45C3E" , // Orange-red
"road_primary" : "#D87A5A" , // Orange
"road_secondary" : "#E8A088" , // Peach
"road_tertiary" : "#F0B8A8" , // Light peach
"road_residential" : "#F5D0C8" // Very light peach
}
Examples: Sunset, Autumn, Terracotta
Use opposite colors on the color wheel: {
"bg" : "#E8F0F0" , // Light cyan
"text" : "#2A5A5A" , // Teal
"water" : "#C0D8D8" , // Light teal
"parks" : "#D8E8E0" , // Pale cyan
"road_motorway" : "#B87333" , // Copper (opposite of teal)
"road_primary" : "#5A8A8A" , // Teal
"road_secondary" : "#6B9E9E" ,
"road_tertiary" : "#88B4B4" ,
"road_residential" : "#A8CCCC"
}
Examples: Copper Patina
Maximum contrast for dramatic effect: {
"bg" : "#000000" , // Pure black
"text" : "#FFFFFF" , // Pure white
"water" : "#0A0A0A" , // Near black
"parks" : "#111111" , // Dark gray
"road_motorway" : "#FFFFFF" , // Pure white
"road_primary" : "#E0E0E0" ,
"road_secondary" : "#B0B0B0" ,
"road_tertiary" : "#808080" ,
"road_residential" : "#505050"
}
Examples: Noir, Contrast Zones
Example Themes
Example 1: Retro Gameboy
{
"name" : "Retro Gameboy" ,
"description" : "Classic Game Boy green screen aesthetic" ,
"bg" : "#9BBC0F" ,
"text" : "#0F380F" ,
"gradient_color" : "#9BBC0F" ,
"water" : "#8BAC0F" ,
"parks" : "#9BBC0F" ,
"road_motorway" : "#0F380F" ,
"road_primary" : "#306230" ,
"road_secondary" : "#0F380F" ,
"road_tertiary" : "#306230" ,
"road_residential" : "#8BAC0F" ,
"road_default" : "#306230"
}
Example 2: Vaporwave
{
"name" : "Vaporwave" ,
"description" : "Retro-futuristic pink and cyan aesthetic" ,
"bg" : "#2A0A3F" ,
"text" : "#FF71CE" ,
"gradient_color" : "#2A0A3F" ,
"water" : "#01CDFE" ,
"parks" : "#3A1A4F" ,
"road_motorway" : "#FF71CE" ,
"road_primary" : "#05FFA1" ,
"road_secondary" : "#B967FF" ,
"road_tertiary" : "#FFFB96" ,
"road_residential" : "#4A2A5F" ,
"road_default" : "#05FFA1"
}
Example 3: Sepia Vintage
themes/sepia_vintage.json
{
"name" : "Sepia Vintage" ,
"description" : "Old photograph sepia tones" ,
"bg" : "#F4E8D8" ,
"text" : "#5C4A3A" ,
"gradient_color" : "#F4E8D8" ,
"water" : "#D8C8B0" ,
"parks" : "#E8DCC8" ,
"road_motorway" : "#5C4A3A" ,
"road_primary" : "#7A6858" ,
"road_secondary" : "#988878" ,
"road_tertiary" : "#B8A898" ,
"road_residential" : "#D0C0B0" ,
"road_default" : "#988878"
}
Example 4: Matrix
{
"name" : "Matrix" ,
"description" : "Green terminal on black - hacker aesthetic" ,
"bg" : "#000000" ,
"text" : "#00FF41" ,
"gradient_color" : "#000000" ,
"water" : "#001A0A" ,
"parks" : "#002A0F" ,
"road_motorway" : "#00FF41" ,
"road_primary" : "#00DD38" ,
"road_secondary" : "#00BB2F" ,
"road_tertiary" : "#009926" ,
"road_residential" : "#00771D" ,
"road_default" : "#009926"
}
Example 5: Lavender Fields
{
"name" : "Lavender Fields" ,
"description" : "Soft purple and lavender tones" ,
"bg" : "#F8F5FC" ,
"text" : "#6B4F8A" ,
"gradient_color" : "#F8F5FC" ,
"water" : "#D8CEEA" ,
"parks" : "#E8E0F4" ,
"road_motorway" : "#6B4F8A" ,
"road_primary" : "#8A6FA8" ,
"road_secondary" : "#A88FC0" ,
"road_tertiary" : "#C0AFD8" ,
"road_residential" : "#D8CFEA" ,
"road_default" : "#A88FC0"
}
Testing Your Theme
Quick Test
Test with a well-known city:
python create_map_poster.py -c "Paris" -C "France" -t my_theme -d 10000
Test Multiple City Types
Test your theme with different urban patterns:
Grid City
Organic City
Waterfront City
Radial City
# Test with grid pattern (Manhattan)
python create_map_poster.py -c "New York" -C "USA" -t my_theme -d 12000
Validation Checklist
Contrast Check
Verify text is readable against background
Road Hierarchy
Ensure major roads stand out more than minor roads
Water Visibility
Check water features are distinguishable (test Venice or Amsterdam)
Park Visibility
Verify parks are visible but subtle (test Paris or London)
Dense vs. Sparse
Test with both dense cities (Tokyo) and sparse cities (suburbs)
Advanced Techniques
Gradient Fade Effect
The gradient_color creates a subtle fade at top and bottom of the poster:
// Same as background = no visible fade
"bg" : "#1A1A1A" ,
"gradient_color" : "#1A1A1A"
// Different = creates vignette effect
"bg" : "#FFFFFF" ,
"gradient_color" : "#F0F0F0" // Slightly darker fade
Color Temperature
Warm Themes (welcoming, vintage):
Use reds, oranges, yellows, warm browns
Examples: Sunset, Autumn, Terracotta
Cool Themes (modern, calm):
Use blues, cyans, purples, cool grays
Examples: Ocean, Blueprint, Midnight Blue
Neutral Themes (professional, versatile):
Use grays, beiges, balanced tones
Examples: Noir, Warm Beige, Pastel Dream
Accessibility
Ensure your theme works for colorblind users:
Use lightness/darkness variation (not just hue)
Avoid red/green as the only differentiator
Test with colorblind simulators
Troubleshooting
Theme not appearing in --list-themes
Ensure:
File is in themes/ directory
File has .json extension
JSON is valid (use a JSON validator)
All 11 properties are present
Common JSON mistakes: // ❌ Trailing comma
{
"name" : "My Theme" ,
"description" : "Test" , // <- Remove this comma
}
// ✅ No trailing comma
{
"name" : "My Theme" ,
"description" : "Test"
}
// ❌ Comments not allowed
{
"name" : "My Theme" , // This is my theme
"description" : "Test"
}
// ✅ No comments in JSON
{
"name" : "My Theme" ,
"description" : "Test"
}
Increase contrast between roads and background: // Before (low contrast)
"bg" : "#EEEEEE" ,
"road_motorway" : "#DDDDDD" // Too similar
// After (high contrast)
"bg" : "#EEEEEE" ,
"road_motorway" : "#333333" // Much darker
Ensure sufficient contrast: // Check contrast at https://webaim.org/resources/contrastchecker/
"bg" : "#FFFFFF" ,
"text" : "#000000" // High contrast
// Or use complementary colors
"bg" : "#1A3A5C" , // Dark blue
"text" : "#E8F4FF" // Light cyan
Increase the gradient range: // Before (too similar)
"road_motorway" : "#3A3A3A" ,
"road_primary" : "#404040" ,
"road_residential" : "#4A4A4A"
// After (wider range)
"road_motorway" : "#000000" ,
"road_primary" : "#2A2A2A" ,
"road_residential" : "#808080"
Sharing Your Theme
If you create a great theme:
Test thoroughly with multiple cities
Choose a descriptive name and write clear description
Consider contributing back to the project
Share screenshots on social media
Next Steps
Theme Gallery Browse all built-in themes for inspiration
Advanced Examples See advanced usage patterns and techniques