A single-page almanac for tonight's sky. It answers one question — is it worth going out tonight? — by combining real ephemeris math with weather data and a transparent scoring rule, then drawing the result as a chart you can read at a glance.
Most stargazing apps show you four widgets and leave you to do the cross-referencing in your head. This one commits to a number.
Three views, all reading from the same underlying data so the moon that's visible on one page is the moon that's visible on the others:
The Tonight Score combines four factors with named deductions:
Every deduction is shown alongside the score with its delta and a short reason. Hover any star, planet, deep-sky object, the moon, or the sun on any of the three views and you get a tooltip with name, magnitude, and a brief note; click it to open the Wikipedia article.
Hand-curated and consistent across all three views:
The catalogue lives in src/lib/astronomy/. Each star and DSO carries the
Wikipedia title for the click-through; the schema is small and easy to
extend.
A few decisions that aren't obvious from the code:
Astronomy library. astronomy-engine (Don Cross) is the same library
that backs several serious amateur tools. VSOP87 / NOVAS-style algorithms
with arcsecond accuracy, not the textbook sin/cos approximations. Planet
positions agree with JPL Horizons to a few arcseconds.
Hand-curated catalogue. The full HYG database is ~9 000 stars and looks impressive for one screenshot. After that it's noise. 125 stars covers every constellation people learn by name, renders in under a millisecond, and stays legible at any zoom. The deep-sky list is the same kind of choice — the brightest 28 objects rather than every Messier labelled in the same dim grey.
Score weights. Tuned to my own observing intuition: cloud cover
dominates, then darkness class, then the moon, then humidity. The
weightings live in tonight-score.ts as plain functions — treat them as
a starting point, not an oracle. The point of the score is that it's
defensible, not that it's correct in some absolute sense.
Two projections for two views. The planisphere uses a stereographic projection from the zenith — that's how a paper sky chart works when held overhead, with north up and east on the left. The Point at sky view uses a gnomonic projection from the current view direction, which is the natural projection for "look through a window at the sky": straight lines on the celestial sphere stay straight on screen.
Two fonts, no design system. Spectral for prose and JetBrains Mono
for numerical readouts. The mono font is doing real work —
font-variant-numeric: tabular-nums slashed-zero lines up digits in
the readouts so they scan like an instrument panel rather than a page
of text.
astronomy-engine
v2 (Don Cross, MIT).npm install
npm run dev
Build a production bundle:
npm run build
npm run preview
The whole app is client-side once it hydrates — there's no per-user
server data to fetch — so it's wired up for static export via
@sveltejs/adapter-static. npm run build writes a self-contained
build/ directory you can drop on any static host.
A GitHub Actions workflow at .github/workflows/deploy.yml builds the
site and publishes it to GitHub Pages on every push to main. The
included static/CNAME claims starmap.tandra.dev; change it (and the
DNS) to point at your own subdomain.
src/
├── lib/
│ ├── astronomy/ — ephemeris math, star + DSO catalogues, projections
│ ├── weather/ — Open-Meteo client and an in-memory forecast cache
│ ├── geo/ — geocoding and browser geolocation
│ ├── score/ — the Tonight Score function
│ ├── components/ — Svelte components (charts, dial, glyph, picker, …)
│ └── styles/ — global tokens
└── routes/
├── +page.svelte — Tonight dashboard
├── sky/+page.svelte — Planisphere with time slider
├── look/+page.svelte — Point-at-sky live view
└── +layout.svelte — Global styles + nav
MIT for the code. Data sources keep their own licences (see above).