Stargazing planner for any site and date: weather-based observing scores, ranked deep-sky targets and planets, altitude and sky charts, and a light-pollution map modelled from VIIRS satellite data.
翻訳待ち
暮らしPython · TypeScriptGitHub @RyGuy907オンライン所有者未確認
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Loading the full README. The saved excerpt is shown below.
Given a date and a location: is this night worth going out, and what should I
point at? See PLAN.md for the full spec.
Status: all phases (0-5) complete. See PHASES.md for per-phase state.
The code is MIT licensed (LICENSE). The bundled star catalogue is
not -- see THIRD_PARTY_NOTICES.md.
On first run the DE440s ephemeris (~32 MB) is downloaded once into a cache
directory and never re-fetched:
Override with ASTRO_EPHEM_DIR. Set ASTRO_EPHEM_NO_DOWNLOAD=1 to make a
missing cache a hard error instead of a network fetch — useful for confirming
the engine runs fully offline.Read the full README ↗Given a date and a location: is this night worth going out, and what should I point at? See PLAN.md for the full spec.
Status: all phases (0-5) complete. See PHASES.md for per-phase state.
The code is MIT licensed (LICENSE). The bundled star catalogue is not -- see THIRD_PARTY_NOTICES.md.
python -m venv .venv
.venv/Scripts/python.exe -m pip install -e ".[dev]"
On first run the DE440s ephemeris (~32 MB) is downloaded once into a cache directory and never re-fetched:
| Platform | Cache location |
|---|---|
| Windows | %LOCALAPPDATA%\astro-night-planner\ephemeris\ |
| Linux / macOS | $XDG_CACHE_HOME/astro-night-planner/ephemeris/ (or ~/.cache/...) |
Override with ASTRO_EPHEM_DIR. Set ASTRO_EPHEM_NO_DOWNLOAD=1 to make a
missing cache a hard error instead of a network fetch — useful for confirming
the engine runs fully offline.
planner night --date 2026-09-15 --location home
planner targets --date 2026-09-15 --limit 8
planner tonight
planner events --days 90
planner planets
planner log start && planner log suggest
Run the API and web UI together:
.venv/Scripts/python.exe -m uvicorn api.main:app --port 8000
npm --prefix web run dev
--date defaults to tonight and --location to the configured default.
"Tonight" follows PLAN.md §3.1: before 06:00 local you are mid-session, so the
night in progress is the one that began yesterday.
Also available: planner locations.
On first use of planner targets, the vendored OpenNGC CSV is parsed once into
a SQLite cache next to the ephemeris. Both are local file reads.
The web app runs at https://astrolabe.ryanjrusson.com: uvicorn behind
Caddy on a small EC2 instance, deployed from main by CI through S3 and SSM.
deploy/README.md has the server setup and the deploy
path.
A public server must not turn somebody else's flood into its own, so the
services it calls are protected at two layers (engine/ratelimit.py):
| Layer | Limit |
|---|---|
| Open-Meteo (forecast, place search, elevation share one allowance) | 60 a minute and 1,000 a day -- a tenth of its free tier; a forecast counts as 2 |
| 7Timer | 10 a minute, 300 a day |
| A service answering 429 or 503 | left alone for its Retry-After (1-60 min; 10 by default) |
| Three failures in a row | left alone for 5 minutes |
| One visitor (IPv6 by /64) | 300 API requests a minute; 40 to the five that can reach out -- /api/night, /api/week, /api/geocode, /api/elevation, /api/sites/resolve |
Over a service's budget the app behaves as it does offline, and says why: the forecast reads "today's Open-Meteo request budget is spent", not "unreachable". A visitor over theirs gets a 429 with Retry-After. Forecasts are cached for three hours per ~1 km, and place searches and elevations for the life of the process, so ordinary use never comes near any of it. Map tiles and survey images are fetched by each visitor's browser, from their own address.
api/ FastAPI adapter over the engine; computes no astronomy and stores
nothing -- every request carries the site it is about
db/ SQLite for the CLI: its sessions and observations, and sites saved
by older versions (the API only ever reads these)
web/ React + TypeScript + Vite; sites and history live in the browser
deploy/ server setup, the systemd unit, the Caddy block, the deploy script
engine/ pure Python; no web imports, no I/O beyond local caches
timeutil.py tz-aware-UTC invariant, "tonight" resolution
locations.py locations.yaml -> Location, timezone from coordinates
ephem.py Skyfield setup, night_window(), altaz_series()
equipment.py limiting magnitude, extinction, airmass
targets.py filters, detectability, ranking, grouping
planets.py apparitions, oppositions, elongations, next visibility
events.py meteor showers, lunar eclipses, conjunctions
scoring.py dual deep-sky/planetary condition scores
outlook.py the week ahead: several nights scored side by side
weather.py Open-Meteo + 7Timer (networked; degrades to unavailable)
geocode.py place name -> coordinates (networked; degrades to empty)
horizon.py obstruction horizon profiles
session.py the hours you plan to be outside, and the default (dusk-01:00)
showpieces.py the curated "popular targets" list, and why each entry is on
it or not
reference.py distances, discovery credits and planet constants: the facts
no ephemeris can derive
constellations.py sky regions, plus marks_toward() for measuring a horizon
by naming what you can see
skybrightness.py coordinate -> SQM from an optional local atlas
catalog/ OpenNGC ingest (vendored CSV -> SQLite) and lookup
cli/ Typer front end; the only layer that converts UTC to local
config/ locations.yaml, equipment.yaml
tests/
| CLI | API | Web UI | |
|---|---|---|---|
| Night window, twilights, moon | planner night | /api/night | The night |
| Condition scores + breakdown | planner tonight | /api/night | Score panel |
| The next seven nights | — | /api/week | Next 7 nights, in the score panel |
| Deep-sky targets | planner targets | /api/targets | Targets |
| Planets and apparitions | planner planets | /api/planets | Planets |
| Showers, eclipses, conjunctions | planner events | /api/events | Upcoming events |
| Altitude vs time | — | /api/altitude | Altitude chart |
| Observation log | planner log … | — | History (in the browser) |
This is the beginning of the README. Read the rest at the original. Read the full README ↗