An interactive Streamlit app that pulls live TLE (Two-Line Element) data from CelesTrak, plots satellite ground tracks on a world map, and predicts when a satellite will be visible from a given observer location — complete with rise/set times in UTC.
Point it at the ISS, a weather satellite, or any tracked object, drop a pin on your location, and see exactly when to step outside and look up.
- Multi-satellite tracking — select several satellites at once via a multiselect; each gets a distinct colour on both the 2D map and 3D globe
- 2D ground track — Folium map showing each satellite's path with antimeridian splitting
- 3D orbit globe — orthographic Plotly globe, rotate with the mouse to see ground tracks on a dark Earth
- Sky map (polar plot) — azimuth/elevation view of the next pass, showing exactly where to look; zenith at centre, horizon at edge, North up
- Upcoming passes table — rise / peak / set times and maximum elevation for each satellite
- Pass alert — email notification via SMTP (configure credentials in Streamlit secrets); "Copy reminder text" button always available
- Custom TLE input — paste any 3-line (or 2-line) TLE to track an object not in the CelesTrak station list
- Historical / time-scrub mode — sidebar slider offsets ±120 minutes so you can replay where satellites were or preview where they'll be
- Live TLE data — fetched from CelesTrak, cached 1 hour
- UTC-normalised timestamps — no timezone guesswork
- Dockerised — run anywhere with one command
- Tested & linted — pytest + pytest-cov, flake8, black
- Codecov coverage badge — tracked on every push
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
streamlit run app/main.pyOpen http://localhost:8501.
docker compose up --build- Push this repo to GitHub (public or private)
- Go to share.streamlit.io → New app
- Select your repo, set Main file path to
app/main.py - Click Deploy — live in ~2 minutes at
https://<you>-satellite-ground-tracker-appmain-<hash>.streamlit.app
In your app's Settings → Secrets on Streamlit Community Cloud, add:
[smtp]
host = "smtp.gmail.com"
port = 465
user = "you@gmail.com"
password = "your-app-password" # generate at myaccount.google.com/apppasswordspytest -q --cov=app --cov-report=term-missing # tests + coverage
black --check app tests # formatting check
flake8 app tests # lintingSatellite_ground_tracker/
├── app/
│ ├── main.py # Streamlit entry-point; tabs, sidebar, alert
│ ├── orbital_math.py # ground_track, predict_passes, sky_track
│ ├── map_renderer.py # Folium multi-satellite map
│ └── ui_components.py # pass_table, sky_map_chart, globe_chart
├── tests/
│ ├── test_orbital_math.py
│ └── test_data_pipeline.py
├── .streamlit/
│ └── config.toml # headless server config for Community Cloud
├── .github/workflows/
│ └── ci.yml # lint → format → pytest --cov → Codecov upload
├── docker_compose.yaml
├── dockerfile.dockerfile
├── requirements.txt
└── README.md
- Python 3.11 / Streamlit — UI and app framework
- Skyfield — SGP4 orbital propagation and pass prediction
- CelesTrak — live TLE orbital data source
- Folium + streamlit-folium — 2D interactive maps
- Plotly — 3D orthographic globe and polar sky-map
- Docker — containerised deployment
- Multi-satellite view — multiselect with distinct track colours
- 3D orbit globe — orthographic Plotly globe
- Sky map (polar plot) — azimuth/elevation pass view
- Pass alerts — email notification via SMTP secrets
- Custom TLE input — paste any TLE directly in the sidebar
- Historical / time-scrub mode — ±120 min offset slider
- Deploy live — Streamlit Community Cloud (see above)
- CI pipeline — GitHub Actions running pytest/black/flake8 on every push
- Test coverage badge — pytest-cov + Codecov integration
- Satellite metadata panel — altitude, velocity, orbital period, NORAD ID
-
prefers-reduced-motion/ keyboard navigation for accessibility
Issues and PRs are welcome. Please run the quality checks above before submitting a pull request.
See LICENSE for details.