Topographic terrain rendered with WebGL. Generate a land or turn a real place into a topographic terrain.
Open the playground · Docs · npm: topographic · npm: topographic-react
With a coding agent, install the topographic skill and ask for a terrain:
npx skills add yahyabedirhan/topographicBy hand:
npm install topographicnpx skills add yahyabedirhan/topographicThe second line installs the topographic skill for your coding agent.
topographic draws terrain as contour lines, from real elevation data or from a shape and a seed. The same settings draw the same land on every screen.
Each example below shows its code beside the terrain it draws.
Name a place, and topographic draws it from real elevation data.
import { createTopography } from 'topographic';
createTopography(el, {
location: 'everest',
}); |
![]() |
Ten places are built in.
![]() istanbul |
![]() cyprus |
![]() matterhorn |
![]() geirangerfjord |
![]() grand-canyon |
![]() yosemite |
![]() torres-del-paine |
![]() fuji |
![]() everest |
![]() kilimanjaro |
In the playground, open Map, frame any other area and click Apply. Its Map menu also holds about 100 more places to search, listed in docs/places.md. Export then gives you the code for it.
Without a place, topographic generates the land. A shape sets its form, and every seed is a new land of that form. Each step below adds to the one before.
Every picture here also sets dark paper and a light ink, theme: { paper: '#0b0b0d', ink: '#cfd8ea' }, and brighter lines, which the code leaves out.
The same land draws as a flat contour map or as a 3D terrain. Here the Grand Canyon goes from 2D to 3D, then takes a new look and more lines.
In 3D, camera sets the angle and the distance, and camera.motion moves it: orbit, push, flyover or drone.
The guide lists every 3D setting.
In plain HTML, use the web component:
<script type="module">import 'topographic/element';</script>
<topographic-view location="fuji" mode="3d"></topographic-view>In JavaScript, createTopography draws into an element and returns the instance:
import { createTopography } from 'topographic';
const topography = createTopography(document.querySelector('#terrain'), { shape: 'long-ridge' });
topography.update({ terrain: { peaks: 3 } });In React, install topographic-react too:
npm install topographic topographic-reactimport { Topography } from 'topographic-react';
<Topography location="yosemite" />The terrain fills the element you give it. The guide shows how to size it and how to put content over it.
A background can also blend between scenes, each with its own shape and line colour.
A new scene fades in, and with scenes set, a theme change fades between light and dark:
const topography = createTopography(el, {
scenes: [{ shape: 'drifting-lobes' }, { shape: 'long-ridge', ink: 'rgb(98% 50% 13%)' }],
scene: 0,
});
topography.update({ scene: 1 });The guide covers scenes, the dark amount, the centre column, the maxFps cap and setOptions.
In the playground, Install and Export give you this code with your settings filled in.
snapshot() draws a PNG at any size, or any part of the view.
record() draws a 3D video as MP4 or WebM.
Both draw off screen, so the page does not change while they run.
const png = await topography.snapshot({ width: 1920, height: 1080 });
const clip = await topography.record({ seconds: 6, motion: 'orbit', format: 'mp4' });The topographic skill teaches your coding agent the settings, the places and the code:
npx skills add yahyabedirhan/topographicThe playground has plain-text docs for AI tools at llms.txt.
In browsers that support WebMCP, an agent can use the playground directly: change the settings, choose a place, take a screenshot, record a video and get the code.
Without WebMCP, an agent can open a link with URL parameters, or call the same tools through a small stub; llms.txt shows how.
The guide lists every setting with its range and default, and covers colours and themes, server rendering and the WebMCP tools.
The web component, the React component and the playground all use the same code. One renderer draws both 2D and 3D.
2D and 3D use the same land and the same lines. 3D adds height and a camera.
A real place starts as elevation tiles. They are stitched, smoothed and turned into a grid of heights, which the renderer draws. The low-level design explains each part.
- An area framed on the map in the playground can be up to 300 km wide.
record()draws the 3D view only, up to 12 seconds a clip.- topographic needs WebGL. Without it, the element shows a plain colour.
- It stops drawing when it is off screen, and draws one still frame for people who turn on reduced motion. A scene fade runs to its end first.
- Scenes blend in 2D only, up to 8 at a time.
Issues and pull requests are welcome. You need Node.js 20 or later.
npm install
npm run dev # the playground, live
npm test # unit tests
npm run build # packages and the playground
npm run smoke # headless Chrome checks (set CHROME=/path/to/chrome)scripts/render-readme-assets.mjs draws the images in this README, the npm pages and the social cards with the library itself.
scripts/readme-shots.mjs retakes the playground screenshots in assets/screenshots/.
The code structure was inspired by Paper Shaders. Height data comes from Mapzen Terrain Tiles on AWS Open Data. Map images come from OpenFreeMap, OpenMapTiles and OpenStreetMap.
- Playground
- Docs
topographicandtopographic-reacton npm- Guide
The npm packages collect nothing. The playground site sends cookieless analytics and error reports; PRIVACY.md lists every event and how to opt out.
The code is licensed under the Apache License 2.0. See LICENSE and NOTICE. If you use or adapt it, please credit Yahya Bedirhan Pak with a link to yahyapak.dev.
The project name, the logo in assets/images/logo/, the screenshots in assets/screenshots/, the images in apps/playground/public/readme/ and assets/social/, and the social cards apps/playground/public/og.png and og-docs.png are not covered by this license and are all rights reserved.






















