Every celestial event from 1900 to 2099, timed to the second.
The Swiss Ephemeris computes it. NASA JPL HORIZONS checks it. Your browser recomputes it for your exact coordinates, on-device and offline.
STARMAP is a second-accurate almanac of the sky. It solves every sign ingress, lunation, eclipse, planetary station, and aspect from 1900 to 2099 and serves them as a static site: one crawlable page per year, plus a live hub for the current year. Two centuries. One page each. No server.
Two things set it apart.
It is correct to the second. Every timestamp is solved with the Swiss Ephemeris 2.10.03 on the JPL DE441 ephemerides, then cross-checked against NASA JPL HORIZONS through a separate code path. The 2026 dataset holds 5,261 events. The generator reproduces that dataset bit-for-bit, from source, in about five seconds.
It recomputes in your browser. "Personal Sky" ships a WebAssembly build of the Swiss Ephemeris to the client and re-solves topocentric event times for your exact coordinates on-device. No server round-trip. No location leaves the machine. It works offline.
Live: https://starmap.puddystudios.com/
- 200 years, one page each - 1900 through 2099, each a prerendered, crawlable static page with prev/next navigation.
- Second-accurate times - Swiss Ephemeris 2.10.03 compute, NASA JPL HORIZONS cross-check, every per-event delta recorded.
- Personal Sky - Client-side topocentric recompute for any location, via the Swiss Ephemeris compiled to WebAssembly, running in a Web Worker.
- Offline-first PWA - Installable, service-worker cached, works with no network across all 200 years.
- Every event class - Ingresses (Sun, Moon, planets, and the major asteroids), the four lunar phases, solar and lunar eclipses, retrograde and direct stations, and aspects.
- Any timezone - Render times in any IANA zone, with optional on-device geolocation for topocentric refinement.
- Zero-dependency build - The entire site generator is pure Python standard library. No pip install to build the site.
- SEO and structured data - Per-page canonical URLs, Open Graph and Twitter cards, and JSON-LD (Dataset, FAQPage, Breadcrumb).
One Python program builds the whole site. There is no runtime server and no database.
data/events-<year>.json ──► scripts/render.py ──► index.html + <year>/index.html + PWA files
(ephemeris output) (pure stdlib) (crawlable, offline-capable static site)
Compute. scripts/generate_all.py drives the Swiss Ephemeris (pyswisseph) and solves every event in a year to the whole second by root-finding on apparent ecliptic longitude, then writes data/events-<year>.json. scripts/horizons.py queries NASA JPL HORIZONS for an independent second opinion.
Render. scripts/render.py reads the event JSON and emits the hub, one page per year, sitemap.xml, robots.txt, the PWA manifest, and a content-hashed service worker. It imports the Python standard library and nothing else.
Personalize. In the browser, personal-sky.js loads the Swiss Ephemeris WebAssembly build (vendor/sweph/) into a Web Worker and re-solves topocentric times for the visitor's coordinates. Entirely on-device.
The full data flow, the root-finding math, the timezone model, and the WebAssembly integration are documented in ARCHITECTURE.md.
The site builds with Python 3.9 and nothing else. No third-party packages.
git clone https://github.com/cubedivisiondev/starmap.git
cd starmap
# Build the hub + current-year page from the committed dataset
python3 scripts/render.py --year 2026
# Serve it
python3 -m http.server 5192
# open http://localhost:5192/The repository ships the 2026 dataset (data/events-2026.json) and a multi-century prior (data/events-major.json), so the hub builds out of the box with no external data.
The 200-year archive needs each year's dataset, regenerated from the ephemeris. This is the one place a dependency appears: pyswisseph, to run the engine.
pip install -r requirements.txt # pyswisseph only
for y in $(seq 1900 2099); do
python3 scripts/generate_all.py --year "$y"
done
python3 scripts/render.py --base / --site https://starmap.puddystudios.com/python3 scripts/ephemeris.py # engine smoke test (loads ephemerides, prints longitudes)
python3 scripts/generate_all.py --year 2026 # regenerate 2026 (~5s; reproduces the committed dataset)
python3 scripts/verify_topo.py # proves the topocentric math two independent waysThe in-browser WebAssembly engine agrees with pyswisseph to sub-millisecond. The full record is in validation/RESULTS.md.
Correctness is the product. Every number carries an independent check.
| Check | Method | Where |
|---|---|---|
| Ephemeris | Swiss Ephemeris 2.10.03 (JPL DE441), apparent positions of date | scripts/ephemeris.py |
| Cross-engine | NASA JPL HORIZONS, same instants, fully independent code path | scripts/horizons.py, reference-2026.md |
| Topocentric | Parallax model prediction vs two independent topocentric ephemerides | scripts/verify_topo.py |
| Browser engine | Swiss Ephemeris WebAssembly vs pyswisseph, byte-faithful ephemeris data |
validation/RESULTS.md |
| Reproducibility | The generator reproduces the committed 2026 dataset bit-for-bit | CI, generate_all.py |
Most events agree with NASA JPL HORIZONS to sub-second. A few do not, and STARMAP says which. A slow, near-stationary body (an outer-planet sign ingress, for one) can drift by a few seconds, because a tiny longitude uncertainty maps to a large time interval near zero angular velocity. Every per-event delta is written down in reference-2026.md, not rounded away.
starmap/
├── scripts/
│ ├── render.py # static-site generator (pure stdlib): hub + 200 year pages + PWA files
│ ├── generate_all.py # ephemeris event solver (pyswisseph) -> data/events-<year>.json
│ ├── ephemeris.py # Swiss Ephemeris wrapper + longitude root-finders
│ ├── horizons.py # NASA JPL HORIZONS cross-check client
│ └── verify_topo.py # topocentric-math verification
├── data/
│ ├── events-2026.json # committed current-year dataset
│ ├── events-major.json # multi-century major-event prior (NASA cross-checked)
│ ├── zone1970.tab # IANA timezone reference points
│ └── ephe/ # Swiss Ephemeris data files (JPL DE441): seas/semo/sepl_18.se1
├── vendor/sweph/ # Swiss Ephemeris WebAssembly build + license + provenance
├── source/ # AGPL complete corresponding source (compliance archive)
├── validation/ # Swiss Ephemeris WASM vs pyswisseph cross-validation harness
├── personal-sky.js # in-browser topocentric recompute (controller)
├── personal-sky-worker.js # Web Worker that loads + runs the WASM engine
├── icons/ og/ favicon.* # PWA icons and social cards
├── reference-2026.md # human-readable 2026 reference table with per-event deltas
├── requirements.txt # pyswisseph (only needed to regenerate data)
└── package.json # convenience build/serve scripts
Generated output (index.html, <year>/, sitemap.xml, manifest.json, sw.js, per-year datasets, per-year cards) is git-ignored and rebuilt by render.py and generate_all.py.
- Generator: Python 3 standard library. Zero third-party dependencies to build the site.
- Ephemeris engine: Swiss Ephemeris 2.10.03, as
pyswissephon the server and a WebAssembly build in the browser. - Cross-check: NASA JPL HORIZONS.
- Frontend: hand-written HTML, CSS, and JavaScript. No framework. An installable PWA with a content-hashed service worker.
STARMAP is licensed AGPL-3.0-or-later (LICENSE).
It serves a WebAssembly build of the Swiss Ephemeris, which Astrodienst AG dual-licenses. STARMAP takes the free AGPL-3.0 option, not the paid commercial one, and ships full compliance:
- Complete corresponding source for the served binary lives in
source/and is offered from the live origin at https://starmap.puddystudios.com/source.html. - The calling code (
personal-sky.js,personal-sky-worker.js) carries AGPL-3.0 headers and is included in the archive. - Upstream attribution and license texts are preserved in
vendor/sweph/.
The AGPL's network-use clause applies to modified versions. The full third-party inventory is in NOTICE. A commercial Swiss Ephemeris license comes from Astrodienst AG (swisseph@astro.com).
Issues and pull requests are welcome. Read CONTRIBUTING.md and the Code of Conduct. Report a security or accuracy issue privately per SECURITY.md.
- Swiss Ephemeris - Astrodienst AG (https://www.astro.com/swisseph/).
- swisseph-wasm - The WebAssembly wrapper by prolaxu (https://github.com/prolaxu/swisseph-wasm).
- NASA JPL HORIZONS - Jet Propulsion Laboratory, California Institute of Technology.
- IANA Time Zone Database - Timezone reference coordinates.
Copyright © 2026 PUDDY Inc. Licensed AGPL-3.0-or-later. STARMAP is a product of PUDDY Inc.
