OVERVIEW
EYE pulls live data from multiple public APIs and WebSocket streams, proxies them through a lightweight Express backend with in-memory caching, then renders everything as billboard collections and entities on a CesiumJS 3D globe.
The HUD overlay is pure DOM — positioned above the Cesium canvas via z-index — and reacts to camera movement, entity hover, and layer toggle events wired in main.js.
SCREENSHOTS
DATA LAYERS
Each layer is an ES module class in layers/ with enable() / disable() lifecycle methods. All toggled via the HUD side panel.
Live global ADS-B from adsb.one. Canvas-drawn plane sprites in a BillboardCollection. Dead-reckoning interpolates positions each frame. Refreshes every 10 s.
TLE catalog from CelesTrak. SGP4 propagation via satellite.js, updated every 3 frames. Click to show orbital path polyline + next pass time.
Traffic cameras from TfL London, Austin TX, NSW AU, and Seattle WA. Image planes at <30 km; LIVE/OFFLINE dots from altitude. Hover previews live feed.
USGS all-day GeoJSON. Pulsing crosshair billboards sized by magnitude. Pulse animation via sine wave on preRender. Refreshes every 60 s.
AIS positions from AISStream WebSocket. Server connects in a 20-second burst collecting global PositionReport messages. Colored by AIS ship type code.
Pure DOM overlay above the Cesium canvas. UTC clock, camera coords, active shader mode, layer toggles, status panel, entity info panel, CCTV hover preview.
POST-PROCESS SHADERS
CesiumJS PostProcessStage GLSL fragments in shaders/, managed by postprocessor.js. One stage active at a time; Normal removes the active stage.
PostProcessor API
import PostProcessor from './postprocessor.js'; const pp = new PostProcessor(viewer); pp.setMode('CRT'); // activate shader pp.setMode('Normal'); // remove active stage pp.getActiveMode(); // → 'Normal' | 'NightVision' | 'FLIR' | 'CRT' | 'Anime'
BACKEND API
Express on port 3001. Vite proxies /api/* to it. All routes use node-cache to throttle upstream calls.
| Method | Endpoint | Description | Cache | Upstream |
|---|---|---|---|---|
| GET | /api/aircraft | All aircraft globally filtered for lat/lon. | 15 s | api.adsb.one |
| GET | /api/ships | 20-second AIS burst — all collected vessels. | 60 s | stream.aisstream.io |
| GET | /api/cctv | Merged cameras. Accepts ?country & ?source. | 5 min | TfL/Austin/NSW/Seattle |
| GET | /api/cctv/image | CORS proxy for camera JPEGs. ?url= | 60 s | Camera image hosts |
| GET | /api/satellites | TLE 3-line catalog. ?group=active default. | 2 hr | celestrak.org |
| GET | /api/proxy | Generic CORS proxy. ?url= — 5 s timeout. | — | Arbitrary |
Camera Schema
{ id: "tfl-00001.03777", name: "Trafalgar Square",
source: "tfl", country: "GB", region: "London",
latitude: 51.5080, longitude: -0.1281,
imageUrl: "https://...", available: true }Ship Schema
{ mmsi: "227000000", name: "FRENCH WARSHIP",
lat: 47.393, lon: -2.686, sog: 7.8, cog: 66.1,
heading: 65, status: 0, shipType: 35 }ARCHITECTURE
BillboardCollection vs Entity API: Aircraft, ships, satellites, and earthquakes use raw BillboardCollection for GPU-batched rendering. Only CCTV uses the Entity API because camera planes need per-entity distance display conditions.
Dead Reckoning: Aircraft and ships interpolate position each frame using last-known heading × speed × elapsed time, keeping motion smooth despite infrequent API calls.
AIS burst pattern: The ship route blocks for 20 s on first request collecting as many global position reports as possible, then caches for 60 s.
SETUP
Requires Node.js ≥ 20.19.0 (CesiumJS engine requirement).
- Clone & Install
Install root (frontend) and server packages separately.
git clone https://github.com/DevwithAnTic/eye.git cd eye && npm install cd server && npm install && cd ..
- Environment Variables
Create
server/.envwith the keys below.
| Variable | Required | Description |
|---|---|---|
| VITE_CESIUM_ION_TOKEN | OPTIONAL | Cesium Ion token. Falls back to OSM imagery without it. |
| AISSTREAM_KEY | OPTIONAL | AISStream.io API key. Free tier at aisstream.io. |
| NSW_TRANSPORT_API_KEY | OPTIONAL | NSW Transport key for Australian CCTV cameras. |
- Run Development
Starts Vite (port 5173) + Express (port 3001) concurrently.
npm run dev:all # or individually: npm run dev # Vite frontend npm run dev:server # Express backend