A FastAPI application with an interactive dashboard that provides astronomical and weather data for any location on Earth.
- Sun times: Dawn, sunrise, solar noon, sunset, dusk with civil/nautical/astronomical twilight
- Golden & blue hours: Photography-optimized time windows
- Moon phases: Current phase, illumination fraction, next new/full moon dates
- Moon rise/set times: Daily moonrise and moonset times with polar region handling
- Solar elevation: Hourly elevation series for the entire day
- Real-time sun position: Interactive arc visualization showing current sun position
- Timezone resolution: Offline IANA timezone lookup (privacy-friendly, no external calls)
- Current conditions: Temperature (°C/°F), feels-like, humidity, wind (km/h, mph, knots), pressure (mb, inHg), precipitation, UV index
- 3-day forecast: Daily high/low temps, conditions, rain/snow chance, wind speeds
- Unit tooltips: Hover over values for alternate units (wind in mph/knots, pressure in inHg)
- Auto-refresh: Weather updates every 15 minutes
- Location-aware: Automatically detects browser location or accepts manual coordinates
- Responsive design: Works on desktop, tablet, and mobile
- Dark mode: Toggle between light and dark themes with persistent preference
- Real-time updates: Clock, sun position, and "last updated" timestamps refresh every second
- 24-hour caching: Smart caching for astronomical data with background refresh
- Service links: Customizable quick links from YAML configuration
- Interactive controls: Collapsible location picker, manual coordinate entry, date selection
- Accessibility: ARIA labels, keyboard navigation, and semantic HTML
GET /— Interactive dashboard (HTML)GET /health— Health check with timestampGET /astro?lat={lat}&lon={lon}— Astronomical data- Optional:
date_str=YYYY-MM-DD,tz_override=Europe/London,elevation_m=0
- Optional:
GET /weather?lat={lat}&lon={lon}&days={0-10}— Weather data with optional forecastGET /links— Personal service links from YAMLGET /feeds— Stub for discovery pipeline integration
- Python 3.11+
- uv package manager
- WeatherAPI.com API key (free tier available at https://www.weatherapi.com/)
# Install dependencies
uv pip install -e .
# Create .env file with your API key
echo "WEATHERAPI_KEY=your_key_here" > .env
# Run development server
uvicorn app.main:app --reloadOpen http://127.0.0.1:8000 for the dashboard or http://127.0.0.1:8000/docs for API documentation.
Create a .env file in the project root:
# Required for weather functionality
WEATHERAPI_KEY=your_api_key_here
# Optional settings
APP_NAME=Astro API
DEBUG=false
ALLOWED_ORIGINS=["http://localhost:5173", "http://localhost:3000", "*"]
LINKS_FILE=app/sample_links.yamlapp/main.py: Core application with all route handlers and astronomical computationsapp/models.py: Pydantic models for request/response validationapp/settings.py: Configuration via environment variablesapp/sample_links.yaml: Personal service links configuration
web/template.html: Complete dashboard with vanilla JavaScript- Real-time updates: Sun position calculated every second using cached sunrise/sunset times
- Smart caching: 24-hour cache for astronomical data, 15-minute refresh for weather
- Local storage: Persistent cache and theme preference survives page reloads
- Dark mode: CSS variable-based theming with smooth transitions
- FastAPI: Web framework
- Astral: Sun/moon calculations
- timezonefinder: Offline timezone resolution
- httpx: Async HTTP client for weather API
- Pydantic: Data validation and settings
- No external calls: timezone resolution is local (
timezonefinder), so your coordinates never leave the box. - Input validation with Pydantic and
Querybounds; explicit 400s on bad input. - Polar edge-cases handled: if Astral cannot compute an event, fields are
null, not 500. - CORS restrict or widen via
ALLOWED_ORIGINS. For prod, avoid"*"unless you serve public data. - Non-root container, minimal base,
tzdatainstalled for correct conversions. - Observability: add structured logging (JSON) if you’re pumping into Loki/ELK; attach Prometheus via
prometheus-fastapi-instrumentatorif desired.
Edit app/sample_links.yaml to add your personal links:
- name: GitHub
url: https://github.com
icon: fab fa-github
group: dev
- name: Gmail
url: https://gmail.com
icon: fas fa-envelope
group: personalThe /feeds endpoint is a stub for integration with content discovery pipelines:
- SQLite/Redis export reader
- JSONL log tailer
- RSS aggregator
- Custom content sources
- Astronomy accuracy: for higher fidelity (rise/set at refraction, topocentric correction), consider
skyfield+jplephem(heavier), orpyephem(older, fast C but legacy). - Sunlight variants: expose
depressionquery param (6°, 12°, 18°) to return civil/nautical/astronomical twilight in one call. - Batching: add
POST /astro/batchaccepting an array of points for map UIs. - Rate limiting:
slowapior a reverse proxy (Traefik/Nginx) with IP limiting for public exposure. - Schema-first: publish an OpenAPI client; you can even host a typed SDK for your apps.
# Current location
curl "http://localhost:8000/astro?lat=52.831&lon=-1.285"
# Specific date (Tromsø summer solstice - midnight sun)
curl "http://localhost:8000/astro?lat=69.6492&lon=18.9553&date_str=2025-06-21"
# With timezone override
curl "http://localhost:8000/astro?lat=40.7128&lon=-74.0060&tz_override=America/New_York"# Current weather only
curl "http://localhost:8000/weather?lat=40.7128&lon=-74.0060"
# With 3-day forecast
curl "http://localhost:8000/weather?lat=40.7128&lon=-74.0060&days=3"# Build
docker build -t astro-api .
# Run
docker run -p 8000:8000 -e WEATHERAPI_KEY=your_key astro-api- Use a reverse proxy (Nginx/Traefik) for SSL termination
- Set
ALLOWED_ORIGINSto your production domains - Consider rate limiting with
slowapior at the proxy level - Add monitoring with Prometheus/Grafana
- Enable structured logging for centralized log aggregation
- Polar regions: Sun/moon events may be
nullduring polar day/night or when celestial bodies don't rise/set - Twilight: Returns civil (-6°), nautical (-12°), and astronomical (-18°) twilight times
- Moon illumination: Heuristic calculation, not precise photometry
- Moon rise/set: Calculated for the specified date; may be
nullin polar regions - Privacy: Timezone resolution is 100% offline - coordinates never leave your server
- Caching: Astronomical data cached for 24h, weather for 15min
- Theme preference: Dark/light mode saved to localStorage
- Hourly weather forecast (currently daily only)
- Air quality index integration
- Batch endpoint for multiple locations (
POST /astro/batch) - Customizable twilight depression angles
- Astronomy image of the day widget
- Moon arc visualization (similar to sun arc)
- Export/share feature for astronomical data
- Customizable units (metric/imperial toggle)
- ✅ Moon rise/set times: Added daily moonrise and moonset calculations with polar region handling
- ✅ Dark mode: Full dark theme support with toggle button and localStorage persistence
- ✅ Weather tooltips: Hover tooltips showing alternate units (mph, knots, inHg)
- ✅ Dual temperature display: Shows both Celsius and Fahrenheit for current weather and forecasts
A Dockerfile is included for containerized deployment:
docker buildx build --sbom=true --provenance=true --push --platform linux/arm64,linux/amd64 -t darkflib/launchpage:latest .