An interactive 3D globe visualising global whale sightings, migration routes, conservation zones, and shipping lane conflicts.
Live: whaledata.org Β· API: api.whaledata.org Β· π Full documentation at docs.whaledata.org
whaledata.org aggregates open ocean data from five global sources and renders it as an interactive 3D globe. Users can filter by species, toggle data layers, explore feeding grounds, and visualise where shipping traffic intersects whale habitats.
| Layer | Source | Records |
|---|---|---|
| π΅ Sightings | GBIF + OBIS | 7,590 |
| π΄ Strandings | NOAA via OBIS | 12,000 |
| π£ Acoustics | NOAA PACM via OBIS | 750 |
| π’ iNaturalist | iNaturalist.org | 3,298 |
| π‘ Historical | GBIF pre-1950 | 1,496 |
Total: ~25,000 records across 6 species
- Feeding grounds β 14 known foraging areas per species with hover details
- Sonar exercise zones β 9 naval exercise areas with risk ratings
- 3D globe with auto-rotate on load, stops on interaction
- Species filter β fly-to animation takes globe to species habitat on selection
- Cluster mode β dots merge at world zoom, expand as you zoom in
- Animated dashed migration routes with hover detail panel
- 32 global shipping corridors with glow effect and traffic weight
- Year range filter β slide to filter sightings by date
- Share button β encodes current view into a URL
- Near me β flies globe to your location
- Keyboard shortcuts β
1β6select species,0all,Spacetoggle rotation,Escclose panels
Full admin β live DB stats, species editor, sightings manager, manual sync triggers for all 6 data sources, full sync logs.
| Species | Sightings | IUCN | Trend |
|---|---|---|---|
| Humpback whale | 1,213 | LC β Least Concern | Increasing |
| Blue whale | 1,202 | EN β Endangered | Increasing |
| Grey whale | 1,200 | LC β Least Concern | Stable |
| Orca | 1,270 | DD β Data Deficient | Unknown |
| Sperm whale | 688 | VU β Vulnerable | Unknown |
| Fin whale | 2,001 | VU β Vulnerable | Increasing |
- Vue 3 β Composition API
- @maptiler/sdk β MapLibre GL JS v5, globe projection
- Syne + DM Mono β typography
- FastAPI β REST API, auto docs at
/docs - PostgreSQL + PostGIS β spatial data
- psycopg2 β database driver
- GBIF β Global Biodiversity Information Facility
- OBIS β Ocean Biodiversity Information System
- NOAA PACM β Passive Acoustic Cetacean Map
- iNaturalist β citizen science (research-grade only)
- Coolify β self-hosted deployment
- Docker β all services containerised
- VPS: Debian, 2 vCPU / 2GB RAM minimum
- Cloudflare β DNS, SSL, redirects
whaledata/
βββ api/ # FastAPI backend β api.whaledata.org
β βββ app/
β β βββ main.py # App entry, all routers registered
β β βββ database.py # PostGIS connection (RealDictCursor)
β β βββ middleware.py # API usage logging
β β βββ routers/
β β β βββ species.py
β β β βββ sightings.py
β β β βββ routes.py
β β β βββ strandings.py
β β β βββ acoustics.py
β β β βββ inaturalist.py
β β β βββ historical.py
β β β βββ layers.py # Unified layer summary endpoint
β β β βββ alerts.py # Email alerts + contact form
β β βββ admin/ # Admin panel (HTTP Basic Auth)
β β βββ admin.py
β β βββ templates/
β βββ schema.sql # Base schema (6 tables)
β βββ schema_phase2.sql # Phase 2 additions (4 tables)
β βββ schema_full.sql # Consolidated single-file schema
β βββ Dockerfile
β
βββ map/ # Vue 3 frontend β whaledata.org
β βββ components/
β β βββ GlobeMap.vue # All map layers, interactions, auto-rotate
β β βββ Sidebar.vue # Species filter + detail panel
β β βββ LayersPanel.vue # Data + conservation layer toggles
β β βββ ShipLanes.js # 32 shipping corridor GeoJSON
β β βββ ConservationLayers.js # Feeding grounds + sonar zones
β βββ App.vue # Root, data fetching, share/nearme/keyboard
β βββ style.css # Global dark ocean theme
β βββ Dockerfile
β
βββ jobs/ # Sync workers β Coolify scheduled tasks
β βββ app/
β β βββ sync_gbif.py # Weekly Sun 3am
β β βββ sync_obis.py # Weekly Sun 4am
β β βββ sync_strandings.py # Monthly 1st 3am
β β βββ sync_acoustics.py # Monthly 1st 4am
β β βββ sync_inaturalist.py # Weekly Wed 3am
β β βββ sync_historical.py # Yearly Jan 1st
β βββ Dockerfile
β
βββ docs/ # Docs site β docs.whaledata.org
β βββ index.html # Home
β βββ why.html # Why this project
β βββ data.html # Data sources
β βββ conservation.html # Conservation layers
β βββ technology.html # Technology stack
β βββ build.html # The build journey
β βββ benchmarks.html # Performance benchmarks
β βββ roadmap.html # Roadmap
β βββ nginx.conf # Extensionless URL routing
β βββ DEPLOYMENT.md
β βββ API.md
β βββ DATABASE.md
β
βββ ATTRIBUTION.md
βββ CHANGELOG.md
βββ README.md
βββ .gitignore
GET /health
GET /species
GET /sightings/?species=&from_date=&to_date=&limit=5000
GET /sightings/species-summary
GET /routes/
GET /strandings/?species=&limit=2000
GET /strandings/summary
GET /acoustics/?species=&limit=2000
GET /acoustics/summary
GET /inaturalist/?species=&limit=2000
GET /inaturalist/summary
GET /historical/?species=&from_year=&to_year=&limit=2000
GET /historical/summary
GET /layers/summary
Full reference: docs/API.md Β· Interactive: api.whaledata.org/docs
| Source | Cron | Frequency |
|---|---|---|
| GBIF | 0 3 * * 0 |
Weekly β Sundays 3am |
| OBIS | 0 4 * * 0 |
Weekly β Sundays 4am |
| Strandings | 0 3 1 * * |
Monthly |
| Acoustics | 0 4 1 * * |
Monthly |
| iNaturalist | 0 3 * * 3 |
Weekly β Wednesdays |
| Historical | 0 5 1 1 * |
Yearly |
git clone https://github.com/Kyraweb/whaledata.git
cd whaledata
# PostGIS
docker run -d --name whaledata-db \
-e POSTGRES_DB=whaledata \
-e POSTGRES_USER=whaledata_user \
-e POSTGRES_PASSWORD=yourpassword \
-p 5432:5432 postgis/postgis:17-3.5-alpine
# Schema
psql -h localhost -U whaledata_user -d whaledata -f api/schema.sql
psql -h localhost -U whaledata_user -d whaledata -f api/schema_phase2.sql
# API
cd api && pip install -r requirements.txt
cp .env.example .env # fill in DB_* and ADMIN_* vars
uvicorn app.main:app --reload
# Frontend
cd ../map && npm install
cp .env.example .env # fill in VITE_API_URL and VITE_MAPTILER_KEY
npm run dev
# Seed data
cd ../jobs && pip install -r requirements.txt
cp .env.example .env
python -m app.sync_gbif
python -m app.sync_obis
python -m app.sync_strandings
python -m app.sync_inaturalist
python -m app.sync_historicalFor full Coolify self-hosting: docs/DEPLOYMENT.md
| Service | Variable | Description |
|---|---|---|
| API + Jobs | DB_HOST |
PostGIS hostname |
| API + Jobs | DB_PORT |
Port (default: 5432) |
| API + Jobs | DB_NAME |
Database name |
| API + Jobs | DB_USER |
Username |
| API + Jobs | DB_PASSWORD |
Password |
| API | ADMIN_USER |
Admin panel username |
| API | ADMIN_PASSWORD |
Admin panel password |
| Map | VITE_API_URL |
Full API URL (buildtime) |
| Map | VITE_MAPTILER_KEY |
MapTiler API key (buildtime) |
| Key | Action |
|---|---|
1β6 |
Select species (Humpback, Blue, Grey, Sperm, Fin, Orca) |
0 |
All species |
Space |
Toggle globe auto-rotation |
Esc |
Close open panels |
- GBIF β gbif.org β CC BY 4.0
- OBIS β obis.org β CC BY 4.0
- NOAA PACM β pacm.fisheries.noaa.gov β Public Domain
- iNaturalist β inaturalist.org β CC BY-NC 4.0
- Species photos β Wikimedia Commons (CC BY / Public Domain)
- Whale audio β NOAA / National Park Service (Public Domain)
- Map tiles β MapTiler
whaledata.org is free and open source. If you build on it, a shoutout and a link back to whaledata.org is appreciated β not required, but it means a lot.
See ATTRIBUTION.md for details.
Personal hobby project by Monarch / KyraWeb. Built to explore geospatial development with real open ocean data.
