Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

118 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FireWatch - Fire Intelligence Dashboard

Analyse wildfire perimeters on an interactive map, run geodesic proximity checks, and drill into incident context - built for the Geospatial Insight technical assessment.


Assessment alignment (required stack)

This solution follows the brief’s technical constraints:

Layer Requirement Implementation
Frontend Angular (latest) & OpenLayers Angular 21 SPA; OpenLayers map, layers, and interactions
Backend Python (FastAPI/Flask) or Node.js (TypeScript) Node.js with TypeScript and Express — typed handlers end-to-end with the Angular client
Database PostgreSQL + PostGIS PostgreSQL 16 with PostGIS for storage and metre-based spatial predicates
DevOps Fully Dockerized; **docker-compose** for local run docker-compose.yml orchestrates db, api, and frontend

Submission


Local setup

Reviewers should be able to run Compose and see the application without undocumented steps.

Step Action
1 Clone the repository and open the **fire-intelligence-dashboard** directory (Compose lives here).
2 Copy **.env.example** → **.env** (defaults are fine for local development).
3 Place **wildfire_data_spain.json** in **data/** (GeoJSON used by the ingest script).
4 Start the stack: **docker-compose up** — use **docker-compose up --build** the first time or after Dockerfile changes. Services: PostGIS, API on port 3000, Angular dev server on port 4200.
5 In a second terminal, ingest geometries: **docker-compose exec api npm run ingest**
6 Open **http://localhost:4200** for the dashboard. Health check: **http://localhost:3000/api/health**.

Optional Makefile shortcuts (POSIX make; Git Bash on Windows)

make up      # docker-compose up --build
make down    # docker-compose down -v
make ingest  # docker-compose exec api npm run ingest
make logs    # docker-compose logs -f api

Prerequisites: Docker Desktop (or Docker Engine + Compose plugin), Git. Node.js locally is optional when everything runs in containers.


Design & architectural reasoning

This section explains why the app is structured and presented this way - not only which libraries were used.

Backend and persistence

  • Node.js + TypeScript + Express were chosen over Python to keep one strongly typed language alongside Angular, shared mental models for DTOs validation (Zod), and a straightforward REST surface under **/api** that maps cleanly to GeoJSON consumers.
  • PostGIS holds authoritative geometries (4326 storage). Proximity is evaluated with **geography** types and **ST_DWithin** so distances are true metres on the spheroid, satisfying the brief’s projection accuracy requirement rather than approximating in planar Web Mercator degrees.

Map UX (Spain sample data)

  • The default view centres on Spain, matching the provided GeoJSON extent so evaluators land on meaningful ground truth immediately.
  • OpenLayers separates concerns into sources and layers: base map, fire polygons, a dedicated proximity buffer circle, and a highlight layer for query results — easy to toggle styles and clear between clicks.

Proximity interaction (Part B)

  • Translucent buffer: A circle geometry is drawn at the click location using the same radius (default 1 km) sent to the API so the on-screen disc matches the backend search radius.
  • Clear-on-new-click: Each map click clears the previous buffer and proximity highlights before issuing a new request, so only one active analysis context is shown at a time.
  • Semantic styling: Perimeters returned by **POST /check-proximity** are styled red on a dedicated highlight layer; the buffer ring uses a cool translucent blue so “search area” and “hit geometry” read distinctly at a glance.

Information density

  • A right-hand sidebar shows rich fire metadata when a perimeter is selected; an empty state guides users toward map clicks - prioritising map-first workflows before detailed panels.
  • FWI / area filters, layer toggles, and timeline-style exploration support analyst-style narrowing beyond the minimum task; they reuse the same GeoJSON pipeline so complexity stays in filters rather than duplicate endpoints.

Engineering hygiene

  • Modular Angular structure (feature pages, services, typed HTTP) and parameterised SQL on the server aim for review-friendly code and safe spatial queries under load (rate limiting on proximity).

Next steps (with more time)

Area Improvement
Hardening Contract tests for core map/proximity flows, performance budgets on large FeatureCollections
Product Authentication, roles, audit trails for operational use
Realtime Push or poll for newly ingested fires; operational alerting
Temporal Deeper timeline/compare tooling and export (video/GIF, reporting bundles)
Scale Partitioning large national datasets, caching heavy aggregates, read replicas
Ops Staging deploys, observability dashboards, chaos testing on DB failover

How the 1 km proximity logic works

The brief requires POST proximity search in metres, accounting for projections.

  1. Input: The client sends latitude, longitude, and optionally **radius_m** (integer metres). The default radius is 1000 (1 km) when omitted - aligned with Part A (3).
  2. Coordinates: Map clicks are transformed from display CRS (EPSG:3857) to EPSG:4326 before calling the API so stored geometries and query points share the same geographic CRS.
  3. Database: PostGIS **ST_DWithin(geom::geography, point::geography, radius_m)** restricts to perimeters within the geodesic distance. **ST_Distance** orders results; each feature carries **distance_m** for UI sorting and labels.
  4. Output: Matching perimeter geometries are returned as GeoJSON features for highlighting on the map.

Reference material

Features (beyond core brief)

  • Dashboard statistics and health indicators
  • FWI / minimum-area filters and operational layer toggles
  • Optional timeline / compare visuals where implemented
  • Dockerised ingest pipeline for the supplied GeoJSON

API summary

Base path: /api

Method Endpoint Purpose
GET /api/health Liveness and database connectivity
GET /api/stats Aggregate dashboard statistics
GET /api/fire-polygons GeoJSON FeatureCollection (filters optional)
GET /api/fire/:id Single fire feature
POST /api/check-proximity Perimeters within **radius_m** metres of **{ lat, lon }** (default 1000)

Project links

Resource Link
License LICENSE (MIT)
Contributing CONTRIBUTING.md
Security SECURITY.md
Code of Conduct CODE_OF_CONDUCT.md
Changelog CHANGELOG.md
Architecture (extended) docs/architecture.md

Security notes

Configuration via environment variables, constrained CORS for dev/prod, rate limiting on expensive proximity traffic, parameterised SQL, and hardened Compose defaults where applicable.


FireWatch · Geospatial Insight technical assessment submission

About

A geospatial fire intelligence platform for monitoring wildfire perimeters, risk indicators, and 1 km proximity checks.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages