Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
An open-source spaceflight simulator in a browser tab. The Milky Way is the real one — 7,123 cataloged systems within 150 light years, the rest from a seed.
GamesTypeScript · JavaScriptGitHub @jonjaquesOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
An open-source, browser-based 6-DoF simulation of the Milky Way — from galactic distances down to inch-scale interaction on a planetary surface, with no loading screens and no scale seams.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
An open-source, browser-based 6-DoF simulation of the Milky Way — from
galactic distances down to inch-scale interaction on a planetary surface, with no
loading screens and no scale seams.
The first milestone, a vertical architectural proof, is complete. The current
build adds measured Solar System bodies, streamed terrain, a planetarium,
portable photographs, cinematic playback and a calibrated stellar population
with diffuse sky and dust. Flight remains a simulation foundation; the
exploration reward loop and ship subsystems are still design work.Read the full README ↗An open-source, browser-based 6-DoF simulation of the Milky Way — from galactic distances down to inch-scale interaction on a planetary surface, with no loading screens and no scale seams.
Quick start · What it does · Architecture · Development · Documentation · Contributing
The first milestone, a vertical architectural proof, is complete. The current build adds measured Solar System bodies, streamed terrain, a planetarium, portable photographs, cinematic playback and a calibrated stellar population with diffuse sky and dust. Flight and on-foot surface movement are playable; the exploration reward loop and ship subsystems are still design work.
The hard problems in a game at this scale are precision, determinism and identity, and all three are solved and demonstrated here rather than asserted. You can fly from the galactic center to a mountainside, resolve an inch, save the session as compact references and dynamic state, and get the same answer twice when the seed, catalog and generation versions agree.
Status: pre-alpha, single maintainer, no release. Flight and surface traversal work; the exploration reward loop is unimplemented.
docs/roadmap.mdsays what is deliberately not built and where each piece will attach.
| Requirement | Version | Why |
|---|---|---|
| Node.js | 26 or newer | The headless runner executes the TypeScript sources directly through type stripping — that is how pnpm sim works with no build step |
| pnpm | 12 (12.3.4 pinned) | The lockfile is pnpm's, and packages/* are source-only workspace links |
| A browser with WebGPU | Chrome, Edge or Safari 26+ | The client renders through WebGPURenderer with TSL. WebGL 2 is a retained fallback, so Firefox runs — without extended-range HDR output, which it cannot do at all |
| git | any |
Nothing else. There is no native toolchain, no Python, no database, and
packages/* have zero third-party runtime dependencies — a rule the build
enforces rather than documents.
The version of pnpm is pinned in package.json's packageManager field, and
any pnpm from 10 on reads that pin and runs the pinned version in this tree, so
which pnpm is installed globally does not matter. Node 26 does not bundle
Corepack, so install one directly:
mise use -g npm:pnpm # or: npm install -g pnpm
For Node itself, any version manager works. With mise:
mise use -g node@26
or with nvm:
nvm install 26 && nvm use 26
Check both:
node --version # v26.x or newer
pnpm --version # 12.x
git clone [email protected]:jonjaques/inertialref.git
cd inertialref
pnpm install --frozen-lockfile
pnpm build # creates the assets directory the Worker serves
pnpm dev # → http://localhost:5173
One command starts both halves — Astro on 5173 and the Cloudflare Worker on 8787,
with /api and /ws proxied to it. pnpm dev:client and pnpm dev:server are
the halves if you want one without the other. After a fresh install,
pnpm docs:build && pnpm dev:client starts the client without a full build;
combined development also needs the Worker assets produced by pnpm build.
pnpm preview builds and then
serves the result through the real Worker, which is the closest thing to
production that runs locally.
That is the whole setup. No environment variables you have to set, no services to start, no API keys — the universe is generated from a seed, and solo simulation does not need a live server. A warmed production build can also start offline, subject to its cached assets.
Neither is needed to run the game, the tests or the build.
pnpm media:pull), never committed. Without it the cutscene
plays silent, which is what a fork gets and is a supported outcome rather than
a failure. scripts/media.mjs has the reasoning.pnpm catalog:fetch re-downloads them if you want to
rebuild.Open /play/solo, then the browser console. The whole simulation is scriptable
from there once the scene is ready:
ir.help() // everything the harness can do
ir.targets() // everywhere you can go, nearest first — start here
ir.goTo('b:2') // system or body; accepts the forms a human types
await ir.selfTest() // the twelve milestone capabilities, executed
await ir.scenario('surface') // land on the first solid world
ir.status() // full structured state
Start with ir.targets() — every other verb takes an address and none of them
will tell you one. The same verbs are on the author's instruments, opened from
the IR menu at the bottom center, so anything you can do by clicking is
reproducible in a test.
The harness object also drives the headless runner, so a scenario that reproduces a bug in Chrome can be replayed without a browser:
pnpm sim --self-test # no browser, no DOM, no WebGL
pnpm sim --targets --goto b:2 # the same navigation, from a terminal
pnpm sim --help # all flags
One gotcha. Chrome throttles
requestAnimationFramein backgrounded tabs, so a freshly reloaded page that is not focused sits at tick 0 until you click it. That is the browser, not the clock.
observed or projected; the game never claims a generated
planet is real.Sirius, Alpha Centauri,
Tau Ceti, 61 Cygni — with every alternate designation searchable, and one
stable address per system whatever the catalog calls it next year.The first milestone had twelve things to demonstrate (the full list, with what
each measures). They are executable rather
than described — await ir.selfTest() in the browser, or pnpm sim --self-test
in Node:
12/12 capabilities proven
PASS 1. Deterministic generation — HIP 38 identical across runs, differs by seed
PASS 2. Stable addressing — 129 bodies addressed and round-tripped
PASS 3. Astronomical distances — Sol to Alpha Centauri: 4.3209 ly
PASS 4. Movement within a system — 6.81 km under thrust in 10 s
PASS 5. Approach a planet — fell 16.65 m in 60 s at 0.0092 m/s², within 0.03% of free fall
PASS 6. Frame transitions — entered b:g:milky-way/s:SOL/b:0 after traveling 8 Mm
PASS 7. Precision near the surface — 1 inch resolved to 9.4 µm, 8.18 kpc from the galactic center
PASS 8. Meter-scale rendering — 1 m separation survives float32 at 8.18 kpc
PASS 9. Origin rebasing — 500 rebases, 2560 km of origin travel, zero drift
PASS 10. Worker task — 4761 elevations and 33800 cover bytes generated in a worker, identical to local generation
PASS 11. Save round trip — 1041 bytes restored to an identical state hash
PASS 12. Frame-rate independence — identical state hash 55d4dba1 at tick 513
This example is the Node run from 9 Sep 2026. The twelve checks cover the
architectural foundation; they do not establish visual quality, galaxy
photometry, GPU performance or every offline asset. Dedicated suites and
recorded measurements cover those areas. CI runs the self-test on every pull
request, alongside pnpm check.
UniverseVector (sector + offset) canonical position, sub-millimeter anywhere
↓ reference frames semantics of motion; identity-preserving
frame-local Vec3 what gameplay and physics work in
↓ floating origin rebased on a 1024 m grid, exactly
render space small numbers, float32-safe
↓ LOD + depth compression angular size preserved, depth compressed
Three.js
Five decisions carry most of the weight:
Full reasoning, alternatives and consequences are in docs/adr/.
apps/
game Astro shell, React + R3F runtime, WebGPU/TSL renderer
headless Node runner — no DOM, no React, no WebGL
ingest turns published catalogs into the packed star asset
server the Cloudflare Worker — the only place Cloudflare appears
packages/
shared units, invariants, structured logging (layer 0)
spatial UniverseVector, frame graph, floating origin (1)
procedural PRNG, hierarchical seeds, noise (1)
physics Kepler, rigid body, atmosphere, thrusters (2)
universe addressing, catalog, generation, terrain (3)
simulation clock, entities, flight, streaming, snapshots (4)
protocol versioned, validated wire and save schemas (4)
workers typed tasks, transport ports, job pool (5)
persistence save/load, migrations, store port (5)
net authority port, local authority (5)
rendering canonical→render bridge, LOD, terrain meshing (5)
devtools inspection, capability checks, harness (6)
data/catalog/ the packed star catalog, committed, CC BY-SA 4.0
docs/ concepts, ADRs, guides, and the design bible — published
design/ the working half: plans, tooling reports, brand sources
scripts/ the graph check, the dev orchestrator, the browser driver,
the brand build, the media sync and the documentation build
Every package below apps/ runs unchanged in the browser main thread, a Web
Worker and Node. A package may depend only on strictly lower layers, and
pnpm graph enforces it — along with rejecting any third-party runtime dependency
in packages/*.
| Command | What it does |
|---|---|
pnpm dev | Astro on :5173 and the Worker on :8787, in one terminal |
pnpm dev:client | Just the Astro development server on :5173 |
pnpm dev:server | Just cf dev, the Worker on :8787 |
pnpm preview | Build, then serve it through the real Worker on :8787 |
pnpm test | Vitest, Node environment only — no DOM is ever registered |
pnpm test:gpu | The shader suite, on the real GPU through Dawn — not in pnpm check |
pnpm typecheck | The six type projects, in parallel — a group of pnpm check; see below |
pnpm lint | oxlint, not eslint (oxlint --fix applies autofixes) |
pnpm graph | Dependency layering + cycle check, and prints the graph |
pnpm brand | Re-render every icon, the share card and the crawler files |
pnpm docs:build | Render docs/ and every export of packages/* into the site's /docs |
pnpm build | Optional media pull, docs:build, typecheck, then Astro and emitted HTML checks |
pnpm check | The gate, as one graph: graph, spelling, brand, presets, format, lint, typecheck, test, test:slow, sim, build. |
pnpm sim --self-test | Headless run plus the twelve capability checks |
pnpm vitest run <substring> | A single test file |
pnpm drive --help | Drive Chrome over the DevTools Protocol — --js, --shot, --sample |
Do not report a task complete without pnpm check passing. CI runs exactly
that command, so there is no separate list of CI stages to drift out of step.
tsconfig.json covers packages/* with
no DOM lib (the core must run in a browser, a worker, and Node),
apps/game/tsconfig.json adds DOM/WebWorker/JSX, apps/headless/tsconfig.json
adds Node types, plus the Worker and the catalog ingest. Why references were
rejected is in development.strict, noUncheckedIndexedAccess, erasableSyntaxOnly and
verbatimModuleSyntax are all on. So: no enum, no parameter properties,
import type for type-only imports, and local imports carry their .ts
extension — Node runs the sources directly.useMemo/useCallback memoization. (useMemo for a stable Three.js object is
a different thing and is fine.)fast-check property tests for anything mathematical —
several real bugs here were found that way and would not have been found
otherwise.packages/* are source-only workspace links. There is no build step between
an edit and a test.AGENTS.md is the working card. Each rule in it exists because violating it is a rewrite later rather than a refactor — for example:
Vec3. UniverseVector is the only thing
that may claim to be one.Math.random(), Date.now() or performance.now() in anything
canonical. Wall clock enters at exactly one call.Read it before changing anything. Agents should continue in docs/agents/. Humans should continue in docs/.
docs/ is the map. Voice and where each audience should look
are in STYLE.md.
Every page below is also readable at
/docs — the same markdown, rendered
by pnpm docs:build alongside a generated reference for every export of
packages/*, and read over a live scene rather than beside a screenshot of one.
The markdown in this repository is the source; the site has no copy of its own.
| Getting started | Run it, drive it, and five things to try |
| Vision and scope | What this is for, and the principles behind it |
| Architecture | The system in one sitting |
| Concepts | How each mechanism works, and why |
| ADRs | Twenty-six decisions that are expensive to reverse |
| Development | Commands, toolchain, conventions |
| The harness | The scriptable API, in full |
| Testing | Property tests, golden vectors, state hashes |
| Extending | Adding a body type, a task, a save field |
| Roadmap | What is deliberately not built yet, and the seam for each |
| Spikes | Five questions that needed a measurement, and the numbers that came back |
Stated plainly, because discovering these by surprise is worse than reading them:
pnpm sim --terrain-baseline prints all of it; the
roadmap has the seams.Contributions are welcome, and the design's shape makes some kinds much easier than others.
pnpm check must be green, and any meaningful architectural change should
be reflected in the ADRs and in CONTEXT.md.Good first areas: terrain and LOD work, physics and orbital mechanics, the
procedural generators, and anything in docs/spikes.md marked
as still needing hardware. Harder: anything touching coordinates, determinism or
addressing — not because contributions are unwelcome there, but because the
invariants are subtle and the ADRs should be read carefully first.
There is no CONTRIBUTING.md or CODE_OF_CONDUCT.md yet; both are
acknowledged gaps.
The project is non-commercial, but it is deliberately not licensed with a non-commercial clause — such a clause is not an open source license under the OSI definition and would make the project ineligible for most package ecosystems. The right way to be non-commercial is a genuine open license and simply not commercializing it. The reasoning is in sustainability.
data/catalog/ is a derived database and is not covered by the Apache
license. It is CC BY-SA 4.0. The terms were verified rather than assumed
(spike 4):
| Source | Terms |
|---|---|
| HYG database v4.4 | CC BY-SA 4.0. Share-alike reaches the packed catalog, which ships as its own asset with its own notice |
| NASA Exoplanet Archive | No license stated; operated by Caltech under NASA contract. Its requested acknowledgment is carried |
| Gaia (ESA) | CC BY-NC 3.0 IGO — non-commercial. Deliberately unused, for exactly that reason |
Share-alike attaches to the database and not to the software that reads it —
CC BY-SA 4.0 § 4(b) says "but not its individual contents" — so Apache-2.0 on
packages/* and CC BY-SA 4.0 on the catalog cover different works and do not
conflict. See NOTICE, data/catalog/LICENSE.md, and
the catalog guide.
Built by Jon Jaques · Issues and discussion at jonjaques/inertialref
pnpm test:gpu on a
physical adapter is what proves that bound; the twelve checks prove the pool —
with the worker pool as fallback, and shaded from the body's own geology: seven
deposits laid down in order, a sea drawn as a refracting sheet over its own
seabed, crater rays, and the archive's published photograph on the
bodies that have one. It refines to cells of a third of a meter, with boulders
addressed as o: objects lying on it — and the ground the ship lands on and
the ground you can see are two functions 1.25 m apart, measured and written
down.controls,
telemetry, perf and graphics behind a disclosure — that call the harness
and nothing else, so anything you can do by clicking is reproducible in a test.| Design bible | What the game is, and why each mechanic is shaped that way |
| Agent handbook | How coding agents should work here |
| CONTEXT.md | Build log: what exists, what was decided, which bugs must not return |