Open-source project
hopechen067/MapStage avatar
hopechen067/MapStage

MapStage: a live tuner for MapLibre maps, globes and 3D terrain

MapStage live tuner: map/globe, satellite, hypsometric relief, region isolate, Mapterhorn DEM, JSON presets.

426 stars58 forksJavaScriptMIT

At a glance

What is it?
MapStage pairs a browser-based style tuner with an agent skill, so you tune a satellite or relief map by hand and hand the exported JSON preset to a coding agent. The catch is that tiles are fetched at runtime from providers you must clear yourself.
Who is it for?
MapStage fits teams that already build on MapLibre GL JS and want a visual way to dial in basemap, hillshade, terrain and camera before writing them into a scene, and it fits agent users who want a skill folder they can install with one command.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 16, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What MapStage is for, and who it is aimed at

MapStage solves a narrow but recurring problem: getting a MapLibre GL JS scene to look right before you commit the settings to code. The repository ships a browser tuner where you adjust projection, satellite imagery, hypsometric relief, hillshade, 3D terrain, water layers and a CSS color grade, then copy a JSON preset that captures the live camera and resource switches. The README describes the intended loop plainly: open the live demo, tune, hit Copy JSON, paste it to an agent.

The audience is therefore two overlapping groups. The first is GIS and web-map developers who already work with MapLibre and want to iterate on style visually rather than by editing a style object repeatedly. The second is agent users: the repository doubles as an installable skill, with a mapstage/ folder holding SKILL.md, references, schemas and the tuner itself. Topics on the repository include maplibre-gl-js, gis, historical-map, antique-map, china and hexi-corridor, which suggests the maintainers built it around historical and regional map work rather than generic web mapping.

A useful detail for judging scope: the README says the public repo was renamed to MapStage, and the live demo publishes mapstage/tuner to the GitHub Pages site root. So the tuner is not a separate product; it is the same folder you install as a skill.

How the tuner, the DEM and the presets fit together

The architecture is deliberately thin. There is no backend and no tile server in the repository. The tuner is a static front end that MapLibre GL JS renders, and everything visual comes from three runtime sources named in the README: EOX Sentinel-2 cloudless as the default raster basemap, Mapterhorn DEM for hillshade and 3D terrain using Terrarium encoding, and OpenFreeMap or OpenMapTiles vector layers for water. The README states that satellite and DEM tiles are fetched at runtime from configured URLs only, and that tiles are not bundled. That single sentence explains most of the project's operational constraints.

Configuration lives in two files. Defaults sit in tuner/map-tiles.config.js, which points at EOX plus Mapterhorn, and personal endpoints go in map-tiles.config.local.js, which is gitignored, with map-tiles.config.example.js as the template. The README notes that EOX public tiles are typically non-commercial with attribution at roughly 10 m, and that the project does not grant rights to any commercial map vendor.

The preset is the connective tissue between the two halves of the project. The README says a copied JSON includes the live camera and resource switches, and describes presets as version 3. On the agent side, SKILL.md and the references folder describe how to apply that preset to a scene, with the README's own example prompt mentioning jumpTo plus idle and terrarium encoding. The schemas folder exists to pin the preset shape, and the references include a parameter list, a tuner workflow document and a tested-config document. That is a sensible split: the tuner produces state, the schema constrains it, and the skill consumes it.

Installing the skill and running a first tuning pass

There are two distinct install paths, and conflating them is the most common mistake. Cloning the repository gets you the README, the preview images, the tuner and the mapstage/ skill folder, but the README warns explicitly that agents do not auto-discover that folder from a clone. To install the skill on its own, the README gives a single command that pulls only the skill folder:

bash
npx skills add hopechen067/MapStage --skill mapstage -g

If you prefer the GitHub CLI, the README lists a second option for version 2.90 and later:

bash
gh skill install hopechen067/MapStage mapstage --scope user

After either command, reload skills so SKILL.md is discovered. The README adds that on Windows you should append --copy to the npx command if symlink creation fails.

For the tuner itself, the README is explicit that you do not need a local server: the live demo on GitHub Pages already runs, and EOX satellite plus Mapterhorn DEM need internet access. Starting a server locally is only for editing files or previewing offline. From inside the tuner folder, either of these works:

bash
cd mapstage/tuner
python -m http.server
bash
cd mapstage/tuner
npx --yes serve

The README says to open the local URL printed in the terminal and not to use file://. There is also an optional check that requires Node on PATH:

bash
cd mapstage/tuner
node verify.mjs

A first real use is to open the demo, pick map or globe projection, switch satellite and relief independently, optionally enable region isolate to get a terrain island, adjust the CSS color grade, then copy the JSON. The README's suggested agent prompt is worth reading before you paste, because it names the pieces the agent is expected to wire up: jumpTo plus idle, and terrarium encoding. If your agent ignores the encoding, the terrain will not line up.

Where MapStage stops being the right tool

The runtime tile fetch is the limitation that matters most. If you need an air-gapped deployment, a reproducible build with pinned imagery, or a map that renders without contacting third-party hosts, this project does not give you that. The README is candid: tiles are not bundled, and satellite and DEM tiles are fetched at runtime from configured URLs only. You can point the local config at your own endpoints, but then you own the tile pipeline, the encoding and the attribution.

Licensing is the second boundary. The code and documentation are MIT, but the README separates demo media and third-party terms into LICENSE-EXCEPTIONS.md and NOTICE.md, and states that the images in showcases/ are All Rights Reserved demo media unless noted otherwise. So the permissive licence covers the software, not the pictures in the README and not the upstream tile services. Anyone planning to redistribute a build should read NOTICE.md, because the README asks you to keep third-party runtime licences when redistributing.

Third, this is a tuner, not a mapping application. It has no data loading, no styling language beyond what MapLibre accepts, no routing, no search, no server-side rendering. The city tiers it does expose (capital, large, medium, small, pass, station, ordos) come through HanCity3D and are oriented toward a particular style of regional and historical map, as the topic list suggests. If your project needs a general-purpose basemap stack, the tuner's opinions will be in your way rather than helping.

Finally, maintenance signals deserve a plain reading. The last push to the repository was on 2026-09-13, and the repository is not archived, so it is currently being worked on. No releases were retrieved, which means there is no tagged version to pin against; you track the master branch or a commit hash.

How it differs from hand-editing a MapLibre style

The natural alternative is not another tuner but the ordinary MapLibre workflow: write a style JSON by hand or generate it, load it in a page, and refresh until the camera, terrain exaggeration and color treatment look acceptable. The difference in approach is where the state lives. With hand-editing, the style file is the source of truth and the camera is usually code you keep separately. With MapStage, the live camera and the resource switches are captured into the exported preset, so the thing you tune and the thing you ship are the same artifact. That is a real reduction in translation error, particularly for terrain, where a mismatch between DEM encoding and the terrain source silently produces flat ground rather than an error.

The second alternative is to skip the tuner and use the skill alone, driving the agent from a written description of the look you want. That is faster to start and worse to verify, because the agent has nothing to reproduce except your prose. The README's own recommended workflow puts the tuner first for exactly this reason.

A third option is a commercial or hosted map style editor. Those typically bundle tiles and styling into one product with support attached. MapStage does the opposite: it is MIT-licensed code with no bundled data, and the README states it does not grant rights to any commercial map vendor. If you want a vendor relationship, MapStage is not competing for that job.

Maintenance, upgrading and licence boundaries

Upgrading the clone is a plain pull, and the README gives the commands:

bash
cd MapStage
git pull

Because there are no retrieved releases, there is no version number to reason about; a pull moves you to whatever is on master. The skill has its own update path through the same npx or gh commands, which reinstall the mapstage/ folder rather than the whole repository. Keep those two in step, because a skill that expects preset version 3 against an older tuner is the kind of mismatch that produces confusing agent output.

On cost, the honest answer is that the recurring expense is not the software. It is tile and DEM usage under whichever provider terms apply to you, plus the engineering time to point map-tiles.config.local.js at endpoints you are allowed to use. The README points readers to NOTICE.md before configuring tiles and notes that EOX public tiles are typically non-commercial with attribution. It also warns not to commit API keys or the local config file, and SECURITY.md is the place the project sends security questions.

The licence split is worth stating precisely, without reading it as legal advice: MIT covers code and documentation; LICENSE-EXCEPTIONS.md covers demo media, third-party components and user geodata; NOTICE.md covers third-party runtimes. If your legal team needs one file, it is not the LICENSE file alone.

Editorial conclusion

MapStage fits teams that already build on MapLibre GL JS and want a visual way to dial in basemap, hillshade, terrain and camera before writing them into a scene, and it fits agent users who want a skill folder they can install with one command. It is the wrong choice if you need bundled, offline-capable tiles or a turnkey commercial basemap, because satellite and DEM tiles are fetched at runtime from URLs you configure, and the README states the project does not grant rights to any commercial map vendor. Before adopting it, read NOTICE.md and LICENSE-EXCEPTIONS.md, confirm the EOX and Mapterhorn terms cover your use case, and run node verify.mjs in mapstage/tuner to see what the local check reports on your machine.

Frequently asked questions

What does the map() do in MapStage?

The README does not document a map() function. What it documents is a browser tuner built on MapLibre GL JS, where you adjust projection, satellite, relief, terrain and color grade, then copy a JSON preset that includes the live camera and resource switches.

What kind of information does the map in MapStage provide?

The map combines a configurable raster basemap, EOX Sentinel-2 cloudless by default, Mapterhorn DEM for hillshade and 3D terrain, and OpenFreeMap or OpenMapTiles vector water. The README also mentions HanCity3D city tiers such as capital, large, medium, small, pass, station and ordos.

Do I need to run a local server to use MapStage?

No. The README states the live demo already runs on GitHub Pages and that you do not start a server on your computer to use it. A local server is only needed if you want to edit files or preview offline, and the README warns against opening the tuner over file://.

Are the satellite and terrain tiles included with MapStage?

No. The README states that tiles are not bundled and that satellite and DEM tiles are fetched at runtime from configured URLs only. Defaults live in tuner/map-tiles.config.js, and personal endpoints go in the gitignored map-tiles.config.local.js.

How do I install MapStage as an agent skill?

The README gives two commands: npx skills add hopechen067/MapStage --skill mapstage -g, or gh skill install hopechen067/MapStage mapstage --scope user on GitHub CLI 2.90 and later. After installing, reload skills so SKILL.md is discovered, and add --copy to the npx command on Windows if symlink creation fails.

Official sources

  1. hopechen067/MapStage on GitHub
  2. Issues
  3. License: MIT
  4. Project website
  5. README
Community notes

Community notes