# Orbit Garden: a tiny universe on Yeeted

Plant a moon and watch a little solar system respond. Switch to **A sense of
scale** to visit Earth and the Moon, the inner planets, the asteroid belt,
Neptune and the Kuiper belt, a comet orbit, and our nearest stellar neighbors.

This example is plain HTML, CSS and browser JavaScript modules. There are no
packages to install, no build step, database, secret, external font or image
request. Yeeted detects the root `index.html` and serves it as a static app.
The root page is also the deployment health probe. Simulation state stays in
the current browser tab. Share a snapshot in a URL fragment to reopen it later;
fragments stay in the browser and are not sent to the hosting server.

## Play

- Drag from empty space in the direction you want to launch a moon. A longer
  arrow gives more speed. The garden pauses while you aim.
- **Plant an orbiting moon** gives keyboard and touch users a ready-made orbit.
- Change the moon mass, slow time, pause, hide trails or start fresh. Choose
  a quiet garden, a binary system, an inbound comet or a crowded moon swarm.
- Preview the first two seconds of a launch before you release it. The preview
  evolves a copy of the whole system with the same physics and ends on contact.
- Undo up to four launches to try another first push. Undo restores the system
  immediately before that launch, including simulated time, and pauses it.
- **Share garden** pauses the simulation and gives you a link containing the
  snapshot. Your visitor opens it paused at that moment. No account, storage
  service or upload is involved. A failed clipboard copy leaves a selectable link.
- In the scale explorer, choose a destination, scroll to zoom around the
  pointer, pinch with two fingers, or drag to pan. The field-of-view slider and
  zoom buttons work with a keyboard. **Back to our pale blue dot** recovers a lost view.
- Click a world or select it from **Meet a world** for a fact card with a NASA
  source. **Take a closer look** frames it with a stylized procedural surface:
  cloud bands, craters, continents and rings, with no image downloads.
- Take the five-stop guided tour from Earth's surface to nearby stars. It moves
  only when you choose the next stop; reduced-motion users get instant transitions.
- **Postcard** downloads the current canvas as a PNG. It is created locally.
  Camera controls are also on the canvas: plus/minus zoom, Home recenters,
  Space pauses the garden, and Escape cancels an aimed launch.
- Reduced-motion users start with the simulation paused. It also stops
  advancing when the tab is hidden or the scale explorer is open.

## Run and test locally

From this directory:

```sh
node --test test/*.test.mjs
python3 -m http.server 8000 --bind 127.0.0.1
```

Open `http://localhost:8000`. Use a current browser with ES modules and Canvas.
Node 22 or newer is needed only for the tests, not to run the app.

```sh
sh smoke.sh http://localhost:8000
```

Set `PLAYWRIGHT_CHANNEL=chrome` to use an installed Chrome instead of a
Playwright-managed browser.

The optional browser integration test uses an externally installed Playwright:

```sh
ORBIT_URL=http://localhost:8000 PLAYWRIGHT_MODULE=/absolute/path/to/playwright/index.mjs \
  node test/browser.mjs
```

It checks planting, pausing, resetting, touch-sized layout, reduced motion,
scale navigation, object visits, the tour, postcard downloads, undo, shared
snapshot restoration, invalid links and module loading errors. Physics tests cover momentum,
collision mass, bounded orbit drift, input limits and bounded trails. Atlas
tests check distance data, projection and zoom invariants.

## Deploy on Yeeted

Follow the [deployment walkthrough](getting-started.md). Deploy the
contents of this directory as the source root, not the enclosing examples
repository. Include `index.html`, `style.css` and every module in `src/`.
No `package.json`, Dockerfile or `yeeted.yaml` is needed.

Ask your agent: "Deploy Orbit Garden to Yeeted development from these files,
then run its smoke checks." A development preview expires; promote the tested
version explicitly if you want an always-on production site. The app is
stateless, so replicas need no shared datastore or session coordination.

```sh
sh smoke.sh "$PREVIEW_URL"
```

The repository's live examples suite includes `orbit-vanilla` and checks its
HTML, stylesheet and module endpoints. HTTP probes confirm serving; the
browser integration test verifies the actual controls and canvas rendering.

## How it works and its limits

`src/physics.js` implements softened pairwise gravity with fixed-step velocity
Verlet integration. All bodies move, including the suns. Touching bodies merge
while conserving mass and momentum. Adding a moon introduces new mass and
momentum from outside the simulation. This is a playful model in normalized
units, not a prediction of real celestial trajectories.

Work is capped at 32 bodies, 180 trail points per body, 16 physics steps per
frame and a device-pixel ratio of two. Predictions are limited to 360 steps
(240 in the UI) and recalculated at most once per 80 ms while aiming. Static
atlas views and paused gardens are redrawn only after an interaction or resize. Slow frames drop catch-up time, so wall
time and simulated time can diverge. Escaping bodies remain in the simulation
and count toward the limit; zoom out or reset to find them.

`src/universe.js` contains the educational atlas. Each view uses one linear
distance scale; the slider changes that scale logarithmically. Body dots are
enlarged when necessary to stay visible. Distances are approximate and positions
are schematic, not live ephemerides. Belt particles represent a population,
not individually cataloged objects. Comet positions and star directions are
illustrative. The Earth close-up is a stylized drawing, not satellite imagery.
There are no remote data calls or analytics.

`src/catalog.js` supplies sourced object facts and shared hit-testing geometry;
`src/celestial-art.js` draws bounded deterministic illustrations. `garden.js`
and `explorer.js` own their respective controls, while `app.js` handles the
canvas, gestures and animation loop.

`src/experiments.js` accepts versioned snapshot fragments up to 16 KiB, at most
32 bodies, finite bounded numbers, unique IDs and restricted names/colors.
It reconstructs fresh bodies rather than accepting arbitrary object properties.
Invalid links reset to a fresh garden with an explanation. Links preserve body
state and time, not trails or UI preferences. They are not encrypted: anyone
with the link can read its simulation state.

[All examples](index.md) · [Deploy an example](getting-started.md)
