Documentation · v1.0

How the SnapCosmos Night Engine works

SnapCosmos's own recommendation engine: it scores every night for your observing goal from hourly forecasts, exact ephemerides and ten years of reanalysis, then returns one instruction with the evidence behind it.

This page is documentation, not marketing. It lists every input, states how each is weighted and why, publishes the validation method, and names the things the engine cannot do. If a claim on SnapCosmos is not traceable to something on this page, treat it as an error and tell us.

Current accuracy: 85% agreement across 600 scored location-nights, last run 2026-07-30. See the full breakdown.

Step 1

Inputs

Everything the engine reads before it decides anything.

Night Engine inputs and their sources
InputSourceHow it is used
Cloud coverOpen-Meteo, hourly, ~2–10 km gridAveraged across the observing window; also read hour by hour to find the best 60–120 minutes.
PrecipitationOpen-Meteo, hourlyAny measurable precipitation inside the window overrides everything else.
Astronomical darknessastronomy-engine, computed for your coordinatesHours with the Sun more than 18° below the horizon. Zero for weeks at high latitude in summer.
Moon illuminationastronomy-engineWeighted by the fraction of the dark window the Moon is actually above the horizon — a 90% Moon that sets at 22:40 costs almost nothing.
Target geometryastronomy-engineAltitude and transit time for planets, the Moon and the galactic centre.
ISS passesCelesTrak elements, SGP4 propagated locallyPass time, peak altitude, direction and magnitude, computed per request for your exact coordinates.
Geomagnetic activityNOAA SWPCPlanetary Kp and solar-wind Bz for aurora scoring.
Historical climateERA5 reanalysis via Open-Meteo archive, 10 yearsA ±10-day calendar window at your coordinates, used for percentile and superlative context.

Step 2

Weighting philosophy

Five decisions that shape every recommendation. They were chosen deliberately and each one is defensible.

Cloud is a gate, not a term
Cloud does not lose a few points, it multiplies the whole score. A 95% overcast night cannot be rescued by a new Moon and eight hours of darkness, and no weighting scheme that treats cloud as one term among many gets that right.
Moonlight is weighted by presence, not phase
The published phase percentage is nearly useless on its own. What matters is how much of your dark window has a lit Moon above the horizon, so illumination is multiplied by that overlap.
Darkness matters only to targets that need it
A full-Moon night is fatal to the Milky Way and irrelevant to Jupiter. Intent selects the weighting profile; the same night can honestly score 20 for one goal and 80 for another.
Tonight is always scored against the week
Every recommendation compares tonight to the next seven nights under the same weights. That comparison is what turns a score into an instruction: go, go now, wait, or skip.
Confidence is separate from quality
How good a night is and how sure we are are two different questions. Confidence comes from forecast agreement across hours, the length of the window, data freshness and the phenomenon's own predictability.

Step 3

Validation

The engine is tested, not asserted. Every release runs the production scoring code over about a hundred real locations with live forecasts.

The harness (scripts/validate-decisions.ts) pulls a live seven-night forecast for each location, computes darkness and Moon geometry with the same ephemeris the site uses, runs the real scoring functions, and compares each recommendation with an independent rule-based baseline built only from raw numbers. Disagreements are printed with their inputs so they can be inspected one by one.

Two failure classes are tracked separately. A soft disagreement is go versus wait — a judgement call. A hard disagreement is go versus skip — an opposite call, and the only kind that would genuinely waste someone's evening. Hard disagreements are the number we work to drive down.

Published results, by observing goal →

Step 4

Known limitations

What the engine does not know. Published because a recommendation engine that only lists its strengths should not be trusted.

Atmospheric transparency and seeing are not modelled
Public forecast models publish cloud, not haze, dust, smoke or aerosol load, and not astronomical seeing. A night can score well and still be soft and milky. Milky Way and astrophotography scores carry an explicit reliability haircut for this.
Light pollution is contextual, not measured
Sky brightness at your exact spot is not in any live feed. Location pages carry an editorially assigned Bortle class; the tonight engine does not adjust scores for it.
Meteor scoring is incomplete
Radiant altitude and current shower activity are not yet inputs. This is the engine's weakest domain and the accuracy page states it plainly.
Forecast skill decays with distance
Nights six and seven ahead are directional, not precise. The engine reflects this in confidence rather than in the score.
Local terrain is invisible to the model
Valleys, coastal fog banks, mountain shadowing and urban heat are all below the grid resolution of the weather model.

Step 5

Forecast uncertainty

Confidence is a published number, not a mood.

Confidence combines four things: how much the hourly forecast agrees with itself across the observing window, how long that window is, how fresh the underlying data is, and how predictable the phenomenon itself is. An ISS pass is close to deterministic; an aurora forecast three days out is not.

Below the headline number the engine publishes per-signal reliability — clouds, Moon, darkness, ISS and the target phenomenon are scored separately, so you can see which one is the weak link rather than guessing. Milky Way and astrophotography reliability is reduced explicitly because atmospheric transparency is not in any public model.

Step 6

Changelog

What changed, when, and why.

v1.0 — July 2026
Named release. Per-signal reliability, historical superlatives from ERA5, and the published machine-readable decision object.
Evidence Layer — July 2026
Every claim on the page became inspectable: confidence drivers, similar historical nights, and the reasoning behind wait versus skip.
Personal layer — July 2026
Intent, cloud tolerance and driving radius became inputs. Cloud changed from a weighted term to a multiplicative gate after validation showed overcast nights scoring above 50.
Verdict Engine 2.0 — 2026
One authoritative verdict object per night, replacing three separate scores that could disagree with each other.
Local SGP4 — 2026
ISS passes moved from a third-party pass API to orbital elements propagated in our own code, removing a runtime dependency.

Why we are different

Most sky sites answer "what are the conditions". We answer "should I go".

The difference is not the data — everyone can fetch a forecast. It is what happens after the data arrives.

A conventional sky-conditions site compared with the SnapCosmos Night Engine
A typical sky siteSnapCosmos
Shows the weather forecastTurns it into one instruction: go, wait or skip
Shows the Moon phaseExplains what that phase actually costs you tonight
Shows cloud coverRanks tonight against ten years of nights at your coordinates
Shows tonightCompares tonight with the next seven nights and names the better one
Generic for everyoneWeighted by what you came to see, and how far you will drive
States conditionsStates a confidence percentage and what would change it
No published accuracyPublishes its measured agreement, goal by goal, including where it is weak

Machine-readable

The methodology as a document, not a paragraph

Everything above is also published as a stable, versioned JSON document: inputs, decision rules, personalisation options, measured accuracy per observing goal, known limitations and data sources.

snapcosmos.com/night-engine.json — served with permissive CORS, cached for an hour, and free to quote with attribution. Each page's live recommendation is published the same way, as a NightDecision object inside script#night-decision.

Every source the engine reads

The engine reads upstream authorities directly wherever possible, and names them rather than the wrapper that delivered them.

Figures on this page last recomputed .

Related

Keep reading