A real-time maritime vessel tracking and intelligence platform built for monitoring vessel movements, detecting anomalies, and generating alerts within the West Philippine Sea and surrounding Exclusive Economic Zones (EEZ).
The platform ingests live AIS (Automatic Identification System) data from multiple sources, processes and deduplicates vessel records through a streaming pipeline, and presents them on an interactive map with filtering, search, track history, and boundary visualization capabilities.
- Architecture Overview
- Technology Stack
- Features
- Prerequisites
- Installation
- Configuration
- Running the Application
- API Reference
- Testing
- Project Structure
- Contributing
- License
- Security
The platform follows a monorepo structure with three workspaces:
wps-maritime-intelligence/
shared/ Shared TypeScript types and interfaces
backend/ Fastify API server, data ingestion pipeline, alert engine
frontend/ React single-page application with Leaflet map
Data flows through the following pipeline:
- DataIngestor connects to AISstream.io (WebSocket) and optionally aisHub (UDP) to receive raw AIS messages.
- StreamProcessor deduplicates messages within a 10-second sliding window per vessel (MMSI), then persists records to both Redis and PostgreSQL.
- AlertEngine evaluates each vessel update against configurable rules (EEZ boundary crossing, AIS signal loss, speed anomaly, loitering) and publishes alerts via Redis Pub/Sub.
- WebSocket Server fans out vessel updates and alerts to connected browser clients in real time.
- React Frontend renders vessels on a Leaflet map with filtering, search, track history, and alert notifications.
Additional backend libraries: @fastify/websocket, @fastify/helmet, @fastify/rate-limit, ioredis, pg, pino, dotenv, uuid.
| Technology | Description |
|---|---|
| Component-based UI library | |
| Type-safe frontend development | |
| Fast build tool and development server | |
| Interactive map rendering |
| Technology | Description |
|---|---|
| Vitest | Unit and integration test runner |
| fast-check | Property-based testing |
| Testing Library | React component testing utilities |
| Static code analysis | |
| Prettier | Code formatting |
- Real-Time Vessel Tracking: Live AIS data ingestion from AISstream.io (WebSocket) and aisHub (UDP) with automatic reconnection and exponential backoff.
- AIS Message Parsing: Full ITU-R M.1371 compliant parser for message types 1, 2, 3 (position reports) and type 5 (static and voyage data), including 6-bit ASCII decoding, NMEA checksum validation, and multi-sentence assembly.
- Stream Processing Pipeline: 10-second sliding window deduplication per MMSI, retaining the most recent record before flushing to Redis and PostgreSQL.
- Alert Engine: Configurable rule-based alerting system with four detection rules:
- EEZ boundary entry/exit detection using point-in-polygon against GeoJSON boundaries
- AIS signal loss detection (30-minute threshold)
- Speed anomaly detection (deviation exceeding 5 knots from 1-hour rolling average)
- Loitering detection (vessel remaining within 1 NM radius for over 2 hours)
- Interactive Map: Leaflet-based map centered on the Philippine Sea with vessel markers, track polylines, and EEZ/WPS boundary overlays.
- Vessel Filtering: Filter by vessel type, flag state (ISO 3166-1 alpha-2), and speed range with persistent filter state via localStorage.
- Search: Search vessels by name or MMSI.
- Track History: Fetch and display historical vessel track positions as polylines on the map.
- Health Monitoring:
/healthand/metricsendpoints reporting Redis, PostgreSQL, and data source connectivity, ingestion rate, WebSocket connection count, and request latency percentiles (p50, p95, p99). - Security Hardening: Helmet security headers (CSP, HSTS, X-Frame-Options, X-Content-Type-Options), rate limiting (100 req/min per IP), HTTPS redirect hook, and input sanitization.
- Cache Fallback: Automatic fallback from Redis to PostgreSQL on cache failures with structured warning logs.
- Data Retention: Automated cleanup of position records older than 30 days via a PostgreSQL function (schedulable with pg_cron).
- Node.js >= 18.x
- npm >= 9.x
- PostgreSQL >= 14.x
- Redis >= 7.x
- Docker (optional, for running PostgreSQL and Redis as containers)
- Clone the repository:
git clone https://github.com/ramonloganjr/wps-tracker.git
cd wps-tracker- Install all workspace dependencies:
npm installCreate a .env file in the backend/ directory (a .env.example template is provided):
# AISstream.io WebSocket
AISSTREAM_WS_URL=wss://stream.aisstream.io/v0/stream
AISSTREAM_API_KEY=your_api_key_here
# aisHub UDP (optional second source)
# AISHUB_HOST=0.0.0.0
# AISHUB_PORT=9999
# PostgreSQL
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/wps_maritime
# Redis
REDIS_URL=redis://localhost:6379
# Server
PORT=3000| Variable | Required | Description |
|---|---|---|
AISSTREAM_WS_URL |
Yes | AISstream.io WebSocket endpoint |
AISSTREAM_API_KEY |
Yes | API key obtained from aisstream.io |
AISHUB_HOST |
No | Bind address for aisHub UDP listener |
AISHUB_PORT |
No | Port for aisHub UDP listener |
DATABASE_URL |
Yes | PostgreSQL connection string |
REDIS_URL |
Yes | Redis connection string |
PORT |
No | HTTP server port (default: 3000) |
Start PostgreSQL and Redis using Docker:
docker run -d --name wps-postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_USER=postgres \
-e POSTGRES_DB=wps_maritime \
-p 5432:5432 \
postgres:16-alpine
docker run -d --name wps-redis \
-p 6379:6379 \
redis:7-alpineRun the SQL migration files in order against the wps_maritime database:
psql -U postgres -d wps_maritime -f backend/migrations/001_create_vessels.sql
psql -U postgres -d wps_maritime -f backend/migrations/002_create_vessel_positions.sql
psql -U postgres -d wps_maritime -f backend/migrations/003_cleanup_job.sql
psql -U postgres -d wps_maritime -f backend/migrations/004_add_source_to_positions.sqlcd backend
npm run devThe backend server starts at http://localhost:3000 by default.
cd frontend
npm run devThe frontend development server starts at http://localhost:5173 with a proxy configured to forward /api and /ws requests to the backend.
| Method | Path | Description |
|---|---|---|
GET |
/api/vessels |
List all active vessels |
GET |
/api/vessels/:mmsi |
Get a single vessel by MMSI |
GET |
/api/vessels/:mmsi/track |
Get historical track positions for a vessel |
GET |
/api/boundaries/eez |
Get EEZ boundary GeoJSON |
GET |
/api/boundaries/wps |
Get WPS boundary GeoJSON |
GET |
/health |
Health check (Redis, PostgreSQL, DataIngestor status) |
GET |
/metrics |
Operational metrics (ingestion rate, latency percentiles, WebSocket connections) |
Connect to ws://localhost:3000/ws and send a subscribe message:
{ "type": "subscribe" }The server responds with:
- Snapshot:
{ "type": "snapshot", "vessels": [...] }-- initial state of all active vessels. - Vessel Update:
{ "type": "vessel_update", "vessel": {...} }-- real-time position and metadata updates. - Alert:
{ "type": "alert", "alert": {...} }-- triggered alert notifications.
Rate limit: maximum 10 client messages per second per connection. Exceeding this limit results in connection closure with code 1008 (Policy Violation).
Run all workspace tests:
npm testRun tests for a specific workspace:
cd backend && npm test
cd frontend && npm testThe test suites include:
- AIS NMEA parser unit tests (message types 1/2/3/5, checksum validation, multi-sentence assembly)
- Boundary point-in-polygon tests
- Redis and cache fallback tests
- Health monitor tests
- Shared type validation tests
- Frontend vessel store reducer tests
- WebSocket reconnection backoff property-based tests
wps-maritime-intelligence/
shared/
src/
types.ts Vessel_Record, Alert, TrackPosition, BoundaryData types
index.ts Public exports
backend/
data/
eez.geojson Philippine EEZ boundary
wps.geojson West Philippine Sea boundary
migrations/
001-004 SQL schema migrations
src/
ais/parser.ts ITU-R M.1371 AIS message parser
alerts/
AlertEngine.ts Rule evaluation orchestrator
rules.ts EEZ, AIS loss, speed anomaly, loitering rules
boundaries/
loader.ts GeoJSON boundary file loader
pointInPolygon.ts Ray-casting point-in-polygon algorithm
cache/
redis.ts Redis read/write, Pub/Sub, sorted set operations
fallback.ts Redis-to-PostgreSQL fallback logic
db/
pool.ts PostgreSQL connection pool singleton
queries.ts SQL query functions (upsert, insert, select)
migrate.ts Migration runner
health/
HealthMonitor.ts Component health checks and metrics
ingestor/
DataIngestor.ts AISstream.io WebSocket and aisHub UDP clients
processor/
StreamProcessor.ts Deduplication and persistence pipeline
server/
app.ts Fastify application factory
websocket.ts WebSocket handler with Pub/Sub fan-out
middleware/
sanitize.ts Input sanitization middleware
routes/
vessels.ts Vessel REST endpoints
boundaries.ts Boundary REST endpoints
health.ts Health check endpoint
metrics.ts Metrics endpoint
index.ts Application entry point
tests/ Backend test suites
frontend/
src/
components/
MapView.tsx Leaflet map container
VesselMarker.tsx Individual vessel marker component
VesselDetailPanel.tsx Vessel detail sidebar
TrackPolyline.tsx Historical track polyline overlay
BoundaryLayer.tsx EEZ/WPS boundary overlay
SearchBar.tsx Vessel search component
FilterPanel.tsx Vessel type, flag, and speed filters
AlertNotification.tsx Alert notification display
filter/
filterTypes.ts Filter type definitions and constants
filterVessels.ts Vessel filtering logic
store/
vesselStore.tsx React Context-based state management
websocket/
WebSocketManager.ts WebSocket client with exponential backoff
App.tsx Root application component
main.tsx Application entry point
tests/ Frontend test suites
Please read CONTRIBUTING.md for details on the contribution process, coding standards, and pull request guidelines.
This project is dual-licensed. See LICENSE.md for full details.
- Source code is licensed under the MIT License.
- Documentation and non-code assets are licensed under Creative Commons Attribution 4.0 International (CC BY 4.0).
For information on reporting vulnerabilities and the security policy for this project, please refer to SECURITY.md.