Update — October 2026: TopoLines now traces on GEDTM30 (30 m bare-earth) worldwide and on national lidar terrain models at 5–10 m in France, the US, Spain, England, Austria, Switzerland, Italy and parts of Germany, and exports GeoJSON and DXF in your CRS alongside SVG and PNG. Current docs: topolines.app/docs · GitHub. This post has been updated to match.
Hey DEV Community 👋
For the past few months I've been building TopoLines — a browser-based contour line generator that traces topographic contours from real, citable elevation data anywhere on Earth. You draw a box on a map, pick your settings, and it traces the contours of that exact area — exported as GeoJSON or DXF in the coordinate system of your choice, or as SVG and PNG.
This is a follow-up to my first post about the designer workflow. This time I want to go deeper on how it actually works under the hood, show a gallery of real places, and talk about the elevation data pipeline — because a lot of you asked.

The TopoLines editor — tracing the Brittany coastline, France, from IGN RGE ALTI 5 m elevation data.
Why contour lines are surprisingly hard to get
If you've ever needed contour lines for a real place — a site study, a GIS project, a CAD drawing, a laser-cut terrain model, a hiking map, a data visualisation or a design layout — you've probably hit the same wall I did:
-
Full GIS software like QGIS, ArcGIS or GRASS can do it, but first you have to find the right DEM (Digital Elevation Model), download and clip it, reproject it, run
gdal_contour, clean the noise, and style the output. That's a multi-hour job if you don't do it every day. - Static asset packs give you pre-made contour patterns — you can't change the location, the contour interval, or the resolution.
- Generative noise tools produce topographic-looking squiggles that don't correspond to any real terrain.
I wanted the contour step of a GIS workflow, with the data sourcing already done, and without installing anything. So I built it.
What TopoLines does
- Search any place on Earth — cities, mountains, coastlines, islands, valleys — using the built-in geocoder.
- Draw a bounding box on the map to define your area.
-
The best elevation model covering that zone is picked for you — and named in the editor:
- GEDTM30 30 m (free) — a worldwide bare-earth model: it follows the ground under forest, not the canopy.
- National terrain models at 5–10 m, mostly lidar — IGN RGE ALTI (France), USGS 3DEP (US), IGN España MDT, Environment Agency LIDAR (England), BEV (Austria), swissALTI3D (Switzerland), TINITALY (Italy), DGM1 (Bavaria, North Rhine-Westphalia).
- Your own GeoTIFF if you have survey data.
- Set the trace: contour interval (down to 5 m), index contours, smoothing, a minimum contour length to drop DEM-noise loops, auxiliary contours on flat ground, depression contours with inward hachures.
- Style it: elevation gradients, stroke width and taper, contour labels cut into the line, scale bar, north arrow and legend.
-
Export:
- GeoJSON — each feature carries its elevation and contour type; written in WGS 84, automatic UTM, Lambert-93, Web Mercator, British National Grid or ETRS89 UTM.
- DXF — one layer per contour type, same CRS options, for CAD and laser cutting.
- SVG — editable paths grouped by elevation, opens cleanly in Figma, Illustrator or Inkscape.
- PNG — up to 3200 px wide.
Every export carries the name of the dataset it was traced from and its licence credit in its metadata.
It runs in the browser, with no software to install. The free tier needs a Google or GitHub sign-in (no payment) and exports a real PNG.
The elevation data pipeline (for the curious)
The terrain comes from open elevation datasets:
-
GEDTM30 v1.2 (OpenGeoHub, CC BY 4.0) is a single global Cloud-Optimized GeoTIFF. I read just the window I need over HTTP range requests (
/vsicurl), so there's nothing to download or stitch. - National models are read from each agency's own web service — WMS, WCS, ArcGIS ImageServer, STAC + COG tiles — each with its own quirks (I wrote them up here). A national model is only used when the zone lies entirely inside its coverage, so a map is never stitched from two datasets.
-
AWS Terrain Tiles (
elevation-tiles-prod) is the fallback. -
OpenStreetMap coastlines (
natural=coastline) clip contours at the shore, because many elevation models report non-zero heights over the sea.
The processing chain is pure Python — rasterio to read and warp the DEM, scikit-image's marching squares to trace the iso-elevation contours, shapely for geometry and simplification, Pillow for the raster output, and rasterio's warp machinery again to reproject vector exports into your CRS. Each contour line is a true iso-line connecting points of equal altitude.
Everything is generated server-side, so what you download is a genuine vector file with real paths — not a traced bitmap.
A gallery of real places
All of these were generated straight from real elevation data, no manual editing:

Sarajevo, Bosnia and Herzegovina
Who it's for
- GIS and survey users who need contours for an area quickly, with a named source and CRS.
- Architects, landscape architects and engineers doing site studies — DXF in a projected CRS, on 5 m lidar where available.
- Cartographers and designers who want editable, correctly sourced vectors in Figma or Illustrator.
- Makers cutting layered terrain models, one DXF/SVG layer per elevation.
- Hikers and outdoor folks looking at the real terrain of a trail or a peak.
- Data visualisation people who want iso-lines grounded in real data.
Try it with a place you know
The best way to judge it is to trace a place you actually know — your city, the mountain you last climbed, the coastline you grew up on.
👉 topolines.app — free with a Google or GitHub account. Docs: topolines.app/docs · feedback and roadmap on GitHub.
I'd genuinely love feedback from this community: feature requests, edge cases, places that break it, formats or CRS you'd want. Drop a comment with the place you traced — I read every one. 🙏


Top comments (0)