We're building a web application that generates beautifully stylized map posters from real geographic data. Users select a location, choose an artistic style, customize colors and typography, then export high-resolution images suitable for large-format printing.
Think of it as a cartographic art tool - turning real OpenStreetMap/terrain data into gallery-worthy prints.
![]() |
![]() |
|---|---|
| Chesapeake Bay | Denver |
![]() |
![]() |
| DMV Area | Salt Lake City |
![]() |
![]() |
| Hawaii | Reggio Calabria |
![]() |
![]() |
| Washington DC (Artistic) | Washington DC (Artistic 2) |
- Search/Select Location - User enters a place name or coordinates, map centers on that location
- Adjust Bounds - User can pan/zoom to frame exactly what they want on the poster
- Choose Style - Select from predefined artistic styles (see Style Library below)
- Customize - Tweak colors, toggle layers, adjust typography
- Preview - See the poster as it will appear with text overlay
- Export - Download high-DPI image (PNG/PDF) ready for printing
- Next.js 14+ with App Router
- TypeScript
- Tailwind CSS for UI styling
- MapLibre GL JS for map rendering (open-source, no API key required for basic usage)
- React Map GL (Maplibre fork) for React integration
- OpenStreetMap via vector tiles (OpenFreeMap, MapTiler free tier, or self-hosted)
- Terrain/Elevation: Mapbox Terrain RGB tiles, or open terrain tile sources
- Consider Protomaps for serverless PMTiles hosting
- For high-DPI export, we'll render the map at a higher resolution than screen display
- MapLibre's
preserveDrawingBuffer: trueenables canvas export - Composite the map canvas with text overlays using HTML Canvas API or a library like
html-to-image - Target export sizes: up to 24x36 inches at 300 DPI (7200x10800 pixels)
Each style is essentially a MapLibre style JSON definition plus metadata about recommended color palettes and typography.
- Streets only, no fills
- Monochromatic or duotone
- Clean, modern aesthetic
- Good for: Cities with interesting street patterns
- Typography: Sans-serif, bold, modern (e.g., Inter, Helvetica Neue)
- Elevation contour lines as primary visual element
- Optional street overlay
- Good for: Mountainous regions, coastal areas, anywhere with terrain
- Typography: Clean and technical, or vintage naturalist style
- Parchment/cream backgrounds
- Warm sepia and ink tones
- Decorative, hand-drawn feel
- Good for: Historic cities, sentimental pieces
- Typography: Serif, ornate, possibly with flourishes (e.g., Playfair Display, IM Fell)
- White or cyan lines on deep blue background
- Grid overlays, coordinate markers
- Precise, architectural feel
- Good for: Urban areas, architectural landmarks
- Typography: Monospace or drafting-style (e.g., IBM Plex Mono, Courier)
- Soft edges, color bleeds
- Parks and water as color washes
- Organic, artistic interpretation
- Good for: Gift pieces, areas with parks/water features
- Typography: Hand-lettered or script style
- Dark backgrounds (black, navy, charcoal)
- Luminous/glowing streets
- Dramatic, cinematic
- Good for: Urban areas, modern aesthetic
- Typography: High contrast, metallics, modern sans-serif
- Buildings rendered with height
- Model/diorama appearance
- Good for: Dense urban cores with skylines
- Typography: Floating or on separate plane
- Note: More complex, may require building height data from OSM
- Map data as raw material for art
- Neighborhoods as color blocks, stylized shapes
- Less literal, more expressive
- Good for: Artistic interpretation, less about navigation
- Typography: Integrated into composition
Each style should have 3-5 preset color palettes, plus custom color picker for:
- Background color
- Primary line/feature color
- Secondary/accent color
- Water color
- Green space color
- Text color
- Location name (large, prominent)
- Optional subtitle (coordinates, country, custom text)
- Font family selection (curated list per style)
- Font size/weight adjustments
- Text position (top, bottom, centered)
- Streets (major/minor)
- Buildings
- Water bodies
- Parks/green space
- Terrain/contours
- Labels (usually off for art prints)
- Aspect ratio presets: 2:3, 3:4, 4:5, 1:1, custom
- Orientation: Portrait/Landscape
- Border/margin options
- Preview: Screen resolution, fast rendering
- Print Export:
- Small (12x18"): 3600x5400px at 300 DPI
- Medium (18x24"): 5400x7200px at 300 DPI
- Large (24x36"): 7200x10800px at 300 DPI
- Custom dimensions with DPI selector
- PNG: Default, transparent background option
- PDF: Vector where possible, better for some print shops
- SVG: If feasible for simpler styles (may be complex)
- User clicks Export
- Show export options modal (size, format, DPI)
- Show loading state with progress if possible
- Render map at target resolution (may need to tile/stitch for very large)
- Composite text overlays
- Trigger download
interface PosterLocation {
name: string;
subtitle?: string;
center: [number, number]; // [lng, lat]
bounds: [[number, number], [number, number]]; // SW, NE corners
zoom: number;
}interface PosterStyle {
id: string;
name: string;
description: string;
thumbnail: string;
mapStyle: MapLibreStyle; // Full MapLibre style spec
defaultPalette: ColorPalette;
palettes: ColorPalette[];
recommendedFonts: string[];
layerToggles: LayerToggle[];
}
interface ColorPalette {
id: string;
name: string;
background: string;
primary: string;
secondary: string;
water: string;
greenSpace: string;
text: string;
}interface PosterConfig {
location: PosterLocation;
style: PosterStyle;
palette: ColorPalette;
typography: {
titleFont: string;
titleSize: number;
titleWeight: number;
subtitleFont: string;
subtitleSize: number;
position: 'top' | 'bottom' | 'center';
};
format: {
aspectRatio: string;
orientation: 'portrait' | 'landscape';
margin: number;
};
layers: {
streets: boolean;
buildings: boolean;
water: boolean;
parks: boolean;
terrain: boolean;
labels: boolean;
};
}+------------------------------------------+
| Logo [Location Search] [Export]|
+----------+-------------------------------+
| | |
| Style | |
| Panel | Map Preview |
| | (Live updating) |
| -------- | |
| Colors | |
| -------- | [Location Name] |
| Text | [Subtitle/Coords] |
| -------- | |
| Layers | |
| | |
+----------+-------------------------------+
- Simplified flow, bottom sheet for controls
- May limit export resolution options
- Location search with geocoding (Nominatim or similar)
- Map display with MapLibre
- 2-3 initial styles (Minimal, Dark Mode, Blueprint)
- Basic color customization
- Text overlay with location name
- PNG export at fixed resolution
- Full style library
- Multiple palettes per style
- Typography customization
- Layer toggles
- Format/aspect ratio options
- Multi-resolution export options
- Progress indicator for large exports
- PDF export
- Possibly tiled rendering for very large outputs
- Save/load poster configurations
- Share links
- Gallery of examples
- Print partner integration (optional)
- Base styles will need to be created/modified for each aesthetic
- Consider using style expressions for dynamic color swapping
- May need to self-host or adapt existing open styles
- High-res export is CPU/memory intensive
- Consider Web Workers for export processing
- May need to warn users about export time for large sizes
- Debounce style updates during customization
- Need reliable, free-tier-friendly tile sources
- OpenFreeMap: Free, no API key, based on OpenMapTiles schema
- MapTiler: Free tier with API key, good style support
- Stadia Maps: Free tier available
- Protomaps: PMTiles format, can self-host
- Google Fonts for web display
- Need to embed fonts in export (may need canvas font loading strategy)
- Terrain data: Best source for contour/elevation data that's free and global?
- Building heights: OSM has some, but coverage varies - how to handle missing data?
- Export approach: Canvas-based vs. server-side rendering for very large exports?
- State management: URL-based state for shareability? Local storage for persistence?
- Mapbox Studio style editor (for style authoring patterns)
- Grafomap, Mapiful (commercial map poster products)
- Stamen maps (Toner, Watercolor - artistic map styles)
- OS OpenData stylesheets (cartographic design)
Optional configuration for Nominatim geocoding API (in frontend/.env.local):
# User-Agent header for Nominatim API requests
# Format: "app-name (contact-url-or-email)"
# Example: NOMINATIM_USER_AGENT=carto-art (https://yourdomain.com)
NOMINATIM_USER_AGENT=
# From email header for Nominatim API requests (optional but recommended)
# Nominatim prefers contact information for API usage
# Example: NOMINATIM_FROM_EMAIL=you@yourdomain.com
NOMINATIM_FROM_EMAIL=These are optional - defaults will work for development. For production, it's recommended to set these to comply with Nominatim's usage policy.
- Set up Next.js project with TypeScript and Tailwind
- Integrate MapLibre GL JS with React
- Implement location search with Nominatim API
- Create first style definition (recommend starting with Minimal Line Art)
- Build basic UI shell with map preview and controls panel
- Implement text overlay system
- Add PNG export functionality
- Iterate from there







