MarineWatcher
Marine Intelligence Platform — Technical Reference
Real-time maritime regulatory monitoring and intelligence platform. Aggregates news and regulatory updates from 17 industry sources (10 RSS + 7 HTML scrapers), classifies articles by IMO convention, vessel type, geographic zone and urgency level, and provides on-demand AI summaries via a local LLM. Integrates AIS-based fleet tracking to monitor vessel positions in real time, and visualises piracy incidents from the IMB Live Piracy Map on an interactive map with proximity alerts.
Architecture
┌─────────────────────────────────────────────────────────┐
│ React 18 + TypeScript + Tailwind │
│ Feed │ Timeline │ Sources │ Map │ Settings │ Detail │
├─────────────────────────────────────────────────────────┤
│ REST API + WebSocket (AIS stream) │
├─────────────────────────────────────────────────────────┤
│ FastAPI + SQLAlchemy 2.0 │
│ Scheduler │ Classifier │ Enrichment │ Notifier │ AIS │
├──────────────┬──────────────┬───────────────────────────┤
│ PostgreSQL │ Ollama │ AIS Stream API │
└──────────────┴──────────────┴───────────────────────────┘
Frontend — React 18, TypeScript, Vite 6, Tailwind CSS, Zustand, TanStack React Query. Leaflet map with CARTO dark tiles, zone-based urgency clustering, and live AIS vessel markers.
Backend — FastAPI, SQLAlchemy 2.0 async, Pydantic v2. APScheduler polls sources every 30 minutes. On-demand LLM enrichment via Ollama (no batch processing — summaries generated only when requested). Telegram Bot API for push notifications.
Data — PostgreSQL with GIN indexes for full-text search and array overlap queries. Feed deduplication via SHA256 GUID generation. AIS positions stored as upsert (latest position per vessel) with 12-hour track sampling for historical playback.
Installation
# Prerequisites: Docker, Docker Compose
# PostgreSQL instance accessible on the network
# Ollama with qwen2.5:32b (optional — only needed for AI summaries)
docker compose up -d
The init container creates the database and runs migrations automatically on first start.
- Frontend:
http://localhost:3006 - API:
http://localhost:8006 - Health:
http://localhost:8006/api/health
Configuration
Copy .env.example to .env:
MW_DATABASE_URL=postgresql+asyncpg://postgres:postgres@qm-db:5432/marinewatcher
MW_POLL_INTERVAL_MINUTES=30
MW_AIS_API_KEY=<your-aisstream-key>
Ollama is accessed via host.docker.internal:11434 from inside the container.
The app works without Ollama — AI summaries simply won't be available.
Tech Stack
| Layer | Technology |
|---|---|
| Frontend | React 18, TypeScript, Vite 6, Tailwind CSS |
| State | Zustand, TanStack React Query |
| Backend | FastAPI, SQLAlchemy 2.0 async, Pydantic v2 |
| Scheduling | APScheduler (AsyncIOScheduler) |
| Database | PostgreSQL 16, asyncpg, GIN indexes |
| LLM | Ollama (qwen2.5:32b), on-demand only |
| Maps | Leaflet, react-leaflet, CARTO tiles |
| AIS | WebSocket client (aisstream.io) |
| Notifications | Telegram Bot API |
| Deployment | Docker Compose (3 containers) |
Feed Aggregation
17 RSS and HTML sources polled every 30 minutes via APScheduler. New articles are deduplicated by SHA256(source_id:entry_id) and classified automatically on ingestion.
RSS/Atom Feeds (10)
- EMSA News & Publications
- gCaptain, Maritime Executive
- Seatrade, Hellenic Shipping News
- Splash247, Offshore Energy
- INTERTANKO
HTML Scrapers (7)
- IMO Press Briefings
- OCIMF Bulletins
- ReCAAP Incident Alerts
- MARAD Maritime Advisories
- UKMTO Warnings
- NATO Shipping Centre
- MDAT-GoA Advisories
Classification Engine
Every ingested article is classified across four dimensions using regex-based keyword matching.
Conventions (25+)
MARPOL, SOLAS, STCW, MLC, ISM, ISPS, IMSBC, IMDG, GHG, EU-ETS, EU-MRV, FuelEU, CII, EEXI, Polar Code, AFS, HNS, LL, COLREG, VETTING (SIRE, CDI, OCIMF, RightShip, TMSA, PSC).
Vessel Types
Bulk carriers, tankers (crude/product/chemical), containers, LNG/LPG, passenger/cruise, RoRo, offshore/FPSO, fishing, superyachts, tugs.
Geographic Zones (16)
EU, North Sea, Baltic, Mediterranean, Black Sea, Red Sea, Middle East, West Africa, SE Asia, Indian Ocean, Arctic, SECA, ECA, US, China, Global.
Urgency Levels
| Level | Triggers |
|---|---|
| Critical | ban, detention, vessel sank, missile strike, crew killed |
| High | mandatory requirement, deadline, piracy attack, sanctions |
| Medium | guidance, advisory, bulletin |
| Low | study, report, conference |
| Info | default for unmatched articles |
AI Enrichment
On-demand LLM summaries via local Ollama (qwen2.5:32b). No external API calls, no batch processing — the LLM is queried only when a user clicks “Get AI Summary” on a specific article.
The enrichment prompt extracts:
- 2–3 sentence summary
- Conventions, vessel types, zones (merged with keyword tags)
- Urgency assessment
- Effective date (regulatory entry-into-force, if mentioned)
Interactive Map
Leaflet map with CARTO dark tiles (no labels). Three layers:
Zone Clustering
Articles grouped by geographic zone, rendered as sized/coloured circles. Circle radius scales with article count, colour reflects highest urgency in the zone. Click to browse articles in that zone.
Piracy Incidents
Live piracy incident data from the IMB Live Piracy Map, displayed as red skull markers. Proximity alerts trigger Telegram notifications when a fleet vessel is within 50 NM of a reported incident.
Fleet Tracking (AIS)
Live AIS vessel positions as rotatable SVG arrow markers. Dashed polyline breadcrumbs from 12-hour track history. Fleet panel shows vessel status, speed, and time since last update.
Fleet Tracking
WebSocket connection to AIS stream API for real-time position updates:
- Position reports — lat/lng/speed/course/heading upsert to a single-row-per-vessel table
- Track points — sampled every 12 hours for historical playback
- Ship static data — IMO number, name, destination merged on receipt
- Connection recovery — exponential backoff (5, 10, 30, 60 seconds)
The fleet panel displays online/offline status, current speed, and destination for each tracked vessel.
Telegram Notifications
Configurable push alerts via Telegram Bot API:
- Urgency threshold — minimum urgency level to trigger alerts (e.g., “high” sends critical + high)
- Convention filter — only alert on specific conventions (empty = all)
- Zone filter — only alert on specific zones (empty = all)
- Rate limiting — max 10 messages per poll cycle, overflow summarised
- Test button — sends a verification message to confirm bot token and chat ID
Timeline
Regulatory deadlines extracted from articles with effective dates. Grouped by month, sorted chronologically, with “UPCOMING” badges for future dates. Useful for tracking convention entry-into-force dates, vetting inspection deadlines, and compliance cutoffs.
Sources
| Source | Type | Category |
|---|---|---|
| EMSA News | RSS | EU |
| EMSA Publications | RSS | EU |
| gCaptain | RSS | News |
| Maritime Executive | RSS | News |
| Seatrade Maritime | RSS | News |
| Hellenic Shipping News | RSS | News |
| Splash247 | RSS | News |
| Offshore Energy | RSS | News |
| INTERTANKO | RSS | Tanker Org |
| IMO Press Briefings | HTML | IMO |
| OCIMF Bulletins | HTML | Tanker Org |
| ReCAAP Alerts | HTML | Security |
| MARAD Advisories | HTML | Security |
| UKMTO Warnings | HTML | Security |
| NATO Shipping Centre | HTML | Security |
| MDAT-GoA | HTML | Security |
| IMB Piracy Map | API | Security |
API Reference
Paginated feed items with filters: search, conventions, vessel types, zones, urgency, effective date.
Single item with source metadata.
Mark item as read.
Request AI summary for one item (on-demand, via Ollama).
List active feed sources.
Dashboard counters: items today, critical alerts, active sources, upcoming deadlines.
Current vessel positions (real-time AIS data).
Historical vessel positions (configurable day range).
Piracy incidents from IMB Live Piracy Map.
Telegram notification configuration.
Update notification filters and credentials.
Send test Telegram message.
Database Schema
Six tables with GIN indexes for performant filtering:
| Table | Purpose | Key Columns |
|---|---|---|
sources | Feed definitions | name, url, feed_type (rss/atom/html), last_polled_at |
feed_items | Articles | title, summary, conventions[], vessel_types[], zones[], urgency, llm_summary, effective_date |
notification_settings | Telegram config | bot_token, chat_id, min_urgency, conventions[], zones[] |
vessel_positions | Current AIS position | mmsi (PK), lat, lng, speed, course, heading, destination |
vessel_tracks | Historical breadcrumbs | mmsi, lat, lng, speed, course, recorded_at |
piracy_incidents | IMB piracy reports | imb_id (PK), lat, lng, incident_type, vessel_name, description, date |
GIN indexes on conventions, vessel_types, and zones arrays enable sub-millisecond filtering via PostgreSQL array overlap operators. Trigram GIN indexes on title and summary support full-text search.
Dev Log
v0.0.1 — 7 March 2026
Public announcement. Baseline version.
Feed aggregation from 17 sources (10 RSS + 7 HTML scrapers), regex-based classification engine, on-demand AI enrichment via Ollama, interactive Leaflet map with zone clustering and piracy incident markers, AIS fleet tracking with proximity alerts, Telegram notification layer, regulatory timeline view. Full REST API with paginated filtering.