Describe your systems as a typed object. Get back indexes, routes and orbital positions over time — then draw the whole thing as SVG. Two libraries, and neither one of them wants to be your game engine.
import { createGalaxy, findRoute } from '@industrieh/starmap'
import { renderGalaxy } from '@industrieh/starmap-render'
const galaxy = createGalaxy({
systems: [
{ id: 'sol', name: 'Sol', x: 0, y: 0, star: { class: 'G', radius: 18 } },
{ id: 'alpha', name: 'Alpha', x: 400, y: 300, star: { radius: 14 } },
],
lanes: [{ from: 'sol', to: 'alpha' }],
})
findRoute(galaxy, 'sol', 'alpha') // ['sol', 'alpha']
renderGalaxy(galaxy) // '<svg …>'The picture above is that call, run while this page was built — not a screenshot.
0
dependencies
Neither package pulls anything in.
2
packages
The model, and the drawing. Take one or both.
SVG
output
A string. No DOM, no component, no framework.
MIT
license
Use it in anything, including a game you sell.
Query it
findRoute() walks the hyperlane network and gives you the systems, the jumps and the distance. Hand the result straight to the renderer and the path lights up.
The drawing beside this paragraph is Altair → Lyra: 3 jumps, 1,059 units, highlighted by passing the route back in.
Animate it
Give the renderer a time and it places every planet, moon and station where its period says it should be. The same two calls made both pictures; only the number changed.
There is no clock inside the library, and no Date. Your loop owns time — which is what lets it pause, scrub backwards, or run a simulation faster than real life.
Theme it
No colour lives in the data model: a planet has a type, never a color. What a type looks like is a decision of the project displaying it, so it enters through the theme.
A table you pass is merged over the default one key by key, so changing one colour keeps the other twenty — and a planet type you invented still gets drawn.
They ship separately on purpose. Take the model alone if you draw your own; take both if you want pixels without writing an SVG by hand.