Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/danizd/GeoSentinel/llms.txt

Use this file to discover all available pages before exploring further.

GeoSentinel’s local development environment runs PostgreSQL 16 + PostGIS 3.4 in Docker while the FastAPI backend and React frontend run directly on your machine — giving you fast reloads without rebuilding containers on every change. The backend is managed with uv for deterministic dependency resolution, and the frontend uses Vite for sub-second HMR. Two optional relay microservices (military flights and AIS vessel tracking) can be started independently when you need to test those data layers.

Prerequisites

Before you begin, make sure the following are installed and available on your PATH:

Step-by-Step Setup

1

Start PostgreSQL 16 + PostGIS 3.4

From the project root, spin up the database container defined in docker-compose.yml:
docker compose up -d
The compose file uses the official postgis/postgis:16-3.4 image and configures a healthcheck that polls pg_isready -U postgres every 5 seconds (5 retries, 5-second timeout). The database will be available on localhost:5432 once the healthcheck passes. You can confirm it is ready with:
docker compose ps
# STATUS should show "healthy" for the postgres service
Data is persisted in a named Docker volume (postgres_data) so it survives container restarts.
2

Install Python dependencies

uv sync reads backend/pyproject.toml and installs an exact, locked environment into the backend/.venv virtualenv:
cd backend
uv sync
You do not need to activate the virtualenv manually — all subsequent uv run commands target it automatically.
3

Install frontend dependencies

cd frontend
npm install
This installs the React, Vite, Mapbox GL JS, and TanStack Query packages listed in frontend/package.json.
4

Create the .env file

Create a .env file at the project root (the same directory as docker-compose.yml). The ingestors and API both load this file automatically at startup.
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/geosentinel
FIRMS_MAP_KEY=your_firms_api_key
GDELT_API_KEY=your_gdelt_api_key
ACLED_USERNAME=your_acled_email
ACLED_PASSWORD=your_acled_password
AISSTREAM_API_KEY=your_aisstream_api_key
OPENSKY_CLIENT_ID=your_opensky_client_id
OPENSKY_CLIENT_SECRET=your_opensky_client_secret
MILITARY_SOURCE=opensky
MILITARY_RELAY_URL=http://localhost:8002
VITE_MAPBOX_TOKEN=your_mapbox_token
Never commit .env to version control. It is already listed in .gitignore. See the Environment Variables reference for a description of every key.
5

Run database migrations

Apply all Alembic migrations to create the full schema (events_canonical, incidents, aoi, corrections_audit, events_quarantine, sources_metadata):
cd backend
uv run alembic upgrade head
Alembic reads backend/alembic.ini, which sets script_location to backend/alembic and prepends backend to sys.path. Re-running this command is safe — Alembic is idempotent and will skip already-applied revisions.
6

Start the FastAPI backend

Open a dedicated terminal and run Uvicorn in reload mode so the server restarts on every source change:
cd backend
uv run uvicorn backend.api.main:app --reload --host 0.0.0.0 --port 8000
The API will be available at http://localhost:8000.
7

Start the React frontend

Open a second terminal and start the Vite dev server:
cd frontend
npm run dev
The frontend will be available at http://localhost:5173 with hot module replacement enabled.
8

Verify everything is running

Confirm the backend is healthy:
curl http://localhost:8000/v1/health
Expected response:
{"status": "healthy"}
You can also check the database connection specifically:
curl http://localhost:8000/v1/health/db
Then open http://localhost:5173 in your browser — you should see the GeoSentinel dashboard with an empty Mapbox map.

Optional: Military Relay

The military flight relay is a separate FastAPI microservice that connects to the OpenSky Network API, filters for military aircraft using a monthly ICAO24 hex database (~10,000 entries), and exposes them on port 8002. It is only needed when testing the GET /v1/military-flights endpoint or the Mapbox military layer in the frontend. PowerShell (Windows):
$env:PYTHONPATH = "C:\path\to\GeoSentinel"
$env:MILITARY_SOURCE = "opensky"
$env:OPENSKY_CLIENT_ID = "your_client_id"
$env:OPENSKY_CLIENT_SECRET = "your_client_secret"
python -m services.military_relay.main
Bash (Linux / macOS):
export PYTHONPATH=$(pwd)
export MILITARY_SOURCE=opensky
export OPENSKY_CLIENT_ID=your_client_id
export OPENSKY_CLIENT_SECRET=your_client_secret
python -m services.military_relay.main
The relay listens on http://localhost:8002. At startup it checks data/military_hex.txt and automatically downloads the latest monthly OpenSky aircraft database (~108 MB from S3) if the file does not exist, is older than 30 days, or contains fewer than 1,000 entries. This background download does not block the relay from starting. A /debug endpoint is available at http://localhost:8002/debug for diagnosing filter coverage.
To force an immediate refresh of the military hex database without restarting the relay, run:
python -m services.military_relay.update_military_db

Optional: AIS Relay

The AIS relay microservice subscribes to the AISStream WebSocket feed and exposes real-time vessel positions on port 8003. It falls back to a mock data generator automatically when AISSTREAM_API_KEY is missing or the WebSocket connection drops.
export PYTHONPATH=$(pwd)
export AISSTREAM_API_KEY=your_aisstream_api_key
python -m services.ais_relay.main
The relay will be reachable at http://localhost:8003. The frontend polls this relay for vessel data displayed in the AIS map layer.

Seeding Test Data

To quickly populate the database with three representative incidents (a conflict event, an earthquake, and a wildfire) along with the sources_metadata entries for all configured ingestors, call the seed endpoint:
curl http://localhost:8000/v1/seed
This is idempotent — running it multiple times will upsert rather than duplicate the seed records.

Running Ingestors

Each ingestor is a standalone Python script that loads .env from the project root automatically. Run them from inside the backend/ directory so that uv picks up the correct virtual environment and all backend dependencies are available:
IngestorCommandNotes
USGS Earthquakesuv run python scripts/run_usgs.pyPulls last 24 h, minmagnitude=4.0, polling every 3 min
FIRMS Wildfiresuv run python scripts/run_firms.pyRequires FIRMS_MAP_KEY; filters by active AOI bounding boxes
GDELT Conflictsuv run python scripts/run_gdelt.pyRequires GDELT_API_KEY; 5-min window via GDELT Cloud v2
ACLED Conflictsuv run python scripts/run_acled.pyRequires ACLED_USERNAME + ACLED_PASSWORD; backfills 48 h
Clusteringuv run python scripts/run_clustering.pyDBSCAN spatio-temporal clustering; run after any ingestor
For example, to run the USGS ingestor:
cd backend
uv run python scripts/run_usgs.py
Always run the clustering job after ingesting new events. The clustering step is what groups raw events_canonical rows into the incidents that the API and frontend display.

Running Tests

Tests live in the tests/ directory at the project root. Run them from inside backend/ so that uv picks up the correct virtual environment:
cd backend

# Run all tests
uv run pytest

# Run with line-level coverage report
uv run pytest --cov=backend --cov-report=term-missing

# Run only normalizer tests
uv run pytest ../tests/normalizers/

# Run only clustering/lifecycle tests
uv run pytest ../tests/jobs/

Service URLs

ServiceURLNotes
FastAPI REST APIhttp://localhost:8000Main backend
Swagger UIhttp://localhost:8000/docsInteractive API explorer
ReDochttp://localhost:8000/redocOpenAPI schema browser
React Frontendhttp://localhost:5173Vite dev server with HMR
Military Relayhttp://localhost:8002Optional; requires OpenSky credentials
AIS Relayhttp://localhost:8003Optional; requires AISStream API key

Build docs developers (and LLMs) love