An independent research project visualizing the Russo-Ukrainian war through interactive maps, timelines, and comprehensive conflict data.
Built to inform, not to sensationalize. This is an independent research project — not affiliated with any government, military, or news organization. It aims to provide accessible, data-driven insight into the human and material costs of the conflict.
The Russo-Ukrainian War Tracker is an independent, open-source research project that consolidates data from 15+ authoritative public sources into a single interactive experience. Users can explore territory control changes, equipment losses, casualty statistics, humanitarian impact, bilateral aid, energy infrastructure status, air defense performance, and strategic asset monitoring — all synchronized to a central timeline spanning the full duration of the war.
This project is not affiliated with any government, military organization, or news outlet. All data is sourced from publicly available APIs and datasets. The application does not generate original analysis or make claims beyond what the underlying sources report.
The entire interface is built around an explorable map rendered in muted dark tones, with data panels, counters, and visualizations layered on top. Every element is designed to put the data at the center of the experience.
- Full-screen MapLibre GL vector map with dark CartoDB base tiles
- Territory control overlays showing Russian-occupied areas over time
- Frontline visualization tracking the contact line
- Equipment loss markers — geotagged, categorized, and filterable by type and status
- Conflict event clusters showing ACLED battle and violence data
- Conflict event heatmap showing regional intensity by oblast
- Major battle locations with historical context
- Ukraine border and oblast boundary layers
- Nuclear power plants — 5 Ukrainian NPPs with operational status indicators
- Critical infrastructure — 6 dams, 4 bridges, and 9 ports
- NATO eastern flank — 14 bases and enhanced forward presence battlegroups
- Belarus military positions — 10 tracked entries near the Ukrainian border
- Ukrainian military bases — 18 major installations
- Russian military bases — 21 known positions near Ukraine
- Energy infrastructure — gas transit pipelines and power stations
- Troop movement arrows — 27 curated military operations with animated directional paths (cyan for Ukraine, orange for Russia)
- NASA FIRMS thermal anomalies — near-real-time satellite fire/strike detections (VIIRS)
- Custom canvas-drawn map icons for all infrastructure and military layers
- All layers independently toggleable via layer controls
- Scrubable timeline spanning February 24, 2022 to present
- Playback controls with adjustable speed (0.25x to 8x)
- Dynamic key events from Wikidata, ACLED, GeoConfirmed (post-ACLED period), and curated editorial sources
- Waveform visualization showing daily Russian loss intensity
- Calendar picker for jumping to specific dates
- URL state persistence — shareable timeline positions
- Animated counters for Russian military losses:
- Personnel, tanks, armored vehicles, artillery systems
- MLRS, UAVs, air defense systems, jets, helicopters
- Ships/boats, supply vehicles
- Sparkline trend charts showing recent daily trends
- Data sourced from the Ukrainian Ministry of Defence
- All statistics update dynamically during timeline playback
- Chronological event browser with dynamic events
- Filterable by category: Battles, Territory, Political, Military, Humanitarian, Milestones
- Filterable by conflict events from ACLED data
- Click-to-navigate: selecting an event jumps the timeline and map
- Auto-tracking during timeline playback
- Kiel Institute Ukraine Support Tracker data
- Total aid breakdown: Military, Financial, Humanitarian (EUR billions)
- Top donor countries ranked by total commitment (EU members highlighted)
- Monthly allocation trends with cumulative totals
- Top 15 weapons delivered by category
- UNHCR refugee data — total refugees by year, top destination countries, IDPs
- OCHA funding status — humanitarian appeal requirements vs. actual funding
- Civilian casualty data — OHCHR monthly statistics by oblast
- All humanitarian data updates during timeline playback with year-based interpolation
- Click any equipment marker for detailed information
- Equipment type, model, status (destroyed/damaged/captured/abandoned)
- Date, nearest location, and coordinates
- Color-coded by status: red (destroyed), orange (damaged), green (captured), purple (abandoned)
- Real-time electricity generation data from the ENTSO-E Transparency Platform
- Damaged capacity tracking — pre-war vs. current generation capacity
- Plant-level status for thermal, nuclear, hydro, and renewable facilities
- Gas transit monitoring — Ukrainian pipeline transit volumes via ENTSOG
- Data updates every 6-12 hours depending on source
- Missile and drone attack statistics aggregated from Ukrainian Air Force reports
- Interception rates by weapon type (cruise missiles, ballistic missiles, Shaheds)
- Attack history — 40 curated major attack waves from February 2022 through May 2025
- Integrated into the central timeline as filterable events
- Global alignment breakdown — 35 pro-Ukraine and 13 pro-Russia countries with proportional bar
- Support type badges — Military, Financial, Humanitarian, Political, Sanctions, Troops
- Aid totals per country and combined
- Country details with notable contributions and descriptions
- Data sourced from Kiel Institute and open records
- Casualty estimates compiled from multiple independent sources
- Mediazona confirmed — verified deaths by name (conservative minimum)
- Western intelligence — US, UK, and EU assessment figures
- OHCHR civilian casualties — UN-verified minimum
- Clear disclaimers about data uncertainty and methodology differences
- 27 curated sanctions packages across EU (14), US (6), UK (3), Canada, Japan, Australia, Switzerland
- Summary statistics — total packages, individuals, and entities sanctioned
- Imposer breakdown — color-coded bar chart by sanctioning body
- Key measures — 10 major bans (SWIFT, oil embargo, price cap, diamond ban, etc.)
- Timeline-aware — filters to show only sanctions imposed by the selected date
- Data sourced from EU Council, US Treasury OFAC, UK Government
- Timeline date, map position (lat/lng/zoom), and sidebar state persisted in URL
- Every view is shareable and bookmarkable via nuqs
| Category | Technology |
|---|---|
| Framework | Next.js 16 (App Router) |
| Language | TypeScript 5 |
| UI Library | React 19 |
| Styling | Tailwind CSS 4 |
| Components | shadcn/ui |
| Maps | MapLibre GL |
| Icons | react-icons (Tabler + Game Icons) |
| URL State | nuqs |
| Fonts | DM Sans + DM Mono |
| Linting | Biome |
| Git Hooks | Husky + commitlint |
| Versioning | Release Please |
| Deployment | Cloudflare Workers via OpenNextJS |
The application exposes the following API endpoints. All responses are cached with stale-while-refresh semantics.
| Route | Description | Cache |
|---|---|---|
/api/losses |
Russian equipment and personnel losses (MoD) | 1h |
/api/losses/recent |
Recent visually confirmed losses (WarSpotting) | 6h |
/api/casualties |
Civilian casualty data (OHCHR via HDX) | 4h |
/api/territory |
Territory control GeoJSON (DeepState) | 12h |
/api/events |
Key events (Wikidata SPARQL + curated) | 24h |
/api/acled |
Conflict events (ACLED) | 24h |
/api/refugees |
Refugee and IDP statistics (UNHCR) | 24h |
/api/humanitarian |
Funding appeal data (OCHA via HDX) | 24h |
/api/aid |
Bilateral aid commitments (Kiel Institute) | 7d |
/api/firms |
NASA FIRMS thermal anomalies (VIIRS satellite) | 3h |
/api/energy |
Electricity generation + plant status (ENTSO-E) | 6h |
/api/energy/gas |
Gas transit through Ukraine (ENTSOG) | 12h |
This project aggregates data from the following authoritative sources. All data is accessed through publicly available APIs and datasets. This is an independent research effort — the project is not endorsed by or affiliated with any of these sources.
| Source | Data Provided | Link |
|---|---|---|
| WarSpotting | Visually confirmed Russian equipment losses with geolocation | warspotting.net |
| Ukrainian Ministry of Defence | Official daily personnel and equipment loss reports | mil.gov.ua |
| Ukrainian Air Force | Missile and drone attack reports, interception statistics | t.me/kpszsu |
| DeepState Map | Territory control and frontline GeoJSON data | deepstatemap.live |
| ACLED | Armed conflict event data — battles, civilian targeting, protests | acleddata.com |
| Wikidata | Structured data on named events, battles, and offensives (via SPARQL) | wikidata.org |
| GeoConfirmed | OSINT photo/video-verified geolocated events (used to fill the post-ACLED gap) | geoconfirmed.org |
| HDX / OCHA | Humanitarian response data, funding status | data.humdata.org |
| OHCHR | UN-verified civilian casualty statistics | ohchr.org |
| UNHCR | Refugee and internally displaced persons statistics | data.unhcr.org |
| Kiel Institute | Ukraine Support Tracker — bilateral military, financial, and humanitarian aid | ifw-kiel.de |
| Mediazona / BBC | Confirmed-by-name Ukrainian casualty investigations | zona.media |
| VIINA | Territorial control derived from news coverage (Zhukov & Ayers) | github.com/zhukovyuri/VIINA |
| NASA FIRMS | Near-real-time satellite thermal anomaly detections (VIIRS) | firms.modaps.eosdis.nasa.gov |
| ENTSO-E | European electricity generation data (Transparency Platform) | transparency.entsoe.eu |
| ENTSOG | European gas transit flow data (Transparency Platform) | transparency.entsog.eu |
| Sanctions data | Curated from EU Council, US Treasury OFAC, UK Government sanctions lists | Various official sources |
| Wikipedia | Pre-invasion order of battle, force groupings, and buildup timeline | en.wikipedia.org |
| CSIS | Invasion axis analysis and satellite imagery assessment | csis.org |
All API responses use a multi-layer persistent caching system (file-based in development, Cloudflare KV in production) with stale-while-refresh semantics. A Cloudflare Worker cron runs every 6 hours to pre-warm all caches.
| Dataset | Cache Duration | Update Frequency |
|---|---|---|
| Equipment stats | 1 hour | Hourly |
| Recent losses | 6 hours | Multiple times daily |
| Casualty reports | 4 hours | Daily |
| Territory control | 12 hours | Daily |
| Conflict events (ACLED) | 24 hours | Daily |
| GeoConfirmed events | 24 hours | Daily (post-ACLED gap fill) |
| NASA FIRMS thermal anomalies | 3 hours | Near-real-time |
| Electricity generation (ENTSO-E) | 6 hours | Hourly |
| Gas transit (ENTSOG) | 12 hours | Daily |
| Key events (Wikidata) | 24 hours | Community-edited |
| Refugee/IDP data | 24 hours | Monthly |
| Humanitarian funding | 24 hours | Monthly |
| Civilian casualties | 24 hours | Monthly (OHCHR) |
| Bilateral aid | 7 days | Monthly releases |
| VIINA territory | Weekly | Weekly snapshots |
| Missile attack dataset | Static | Curated (40 major waves) |
| Sanctions data | 7 days | Curated (static, updated with new packages) |
| Pre-invasion mobilization | Static | Curated historical dataset (Mar 2021 – Feb 2022) |
This project does not generate original analysis. Instead, it consolidates, cross-references, and visualizes data from the sources listed above. Below is how each major data domain is constructed.
Territory Control & Frontline
Territory control is shown in two phases. From February 2022 through mid-2023, the VIINA dataset (Zhukov & Ayers, University of Michigan) provides weekly territorial control estimates derived from systematic monitoring of news reports from multiple Ukrainian and Russian outlets. The application converts VIINA's point-level observations into filled polygons using convex hull computation and Delaunay triangulation to approximate areas of control, and derives frontline geometry by walking the boundary between Russian-controlled and Ukrainian-controlled clusters. From mid-2023 onward, the DeepState Map provides higher-resolution daily GeoJSON polygons for both occupied territory and the frontline. The transition between sources is handled automatically based on the selected timeline date.
Russian Equipment Losses
Daily aggregate loss figures (personnel, tanks, armored vehicles, artillery, etc.) come from the Ukrainian Ministry of Defence's official reports. These are displayed as animated counters with sparkline trend charts. Individual geolocated equipment losses are sourced from WarSpotting, which catalogs visually confirmed losses from open-source imagery. Each loss is categorized by type, status (destroyed, damaged, captured, abandoned), and mapped to its confirmed location.
Ukrainian Losses
Ukrainian military casualties are sourced exclusively from the Mediazona/BBC News Russian Service investigation, which identifies fallen soldiers by name through obituaries, social media, and official records. Only confirmed-by-name figures are shown. The application does not display estimates or extrapolations. A disclaimer explains this methodology and notes that actual losses are likely significantly higher than the confirmed count.
Civilian Casualties & Humanitarian Data
Civilian casualty figures come from the UN Office of the High Commissioner for Human Rights (OHCHR), which publishes verified monthly reports. Refugee and internally displaced persons statistics come from UNHCR. Humanitarian funding data — including the UN Flash Appeal and Refugee Response Plan — comes from OCHA's Humanitarian Data Exchange (HDX). All figures are presented as reported by these organizations without modification.
Bilateral Aid
Military, financial, and humanitarian aid commitments to Ukraine are sourced from the Kiel Institute for the World Economy's Ukraine Support Tracker, which publishes structured datasets tracking bilateral aid by country, type, and amount. The International Support panel aggregates this data by donor country and support category.
Conflict Events
Battle locations, civilian targeting events, and protests are sourced from the Armed Conflict Location & Event Data Project (ACLED), which provides georeferenced event data updated daily. These are displayed as clustered points and heatmap overlays. Major named events shown in the timeline and event sidebar are sourced from Wikidata SPARQL queries filtered to the Russo-Ukrainian War, supplemented by curated editorial additions for events not yet reflected in Wikidata.
Energy Infrastructure
The Energy panel combines data from the ENTSO-E Transparency Platform (European electricity generation data) with a curated dataset of Ukrainian power plants and their wartime damage status. Historical energy snapshots are computed by tracking known strike dates against each facility. Gas pipeline status is derived from ENTSOG flow data and curated records of the Russia-Ukraine transit shutdown (January 2025) and TurkStream operations.
Infrastructure Status
Critical infrastructure — including dams, bridges, ports, nuclear plants, and thermal power plants — is tracked using a curated dataset with timestamped status changes. Each item's status (operational, damaged, destroyed, occupied) is computed relative to the selected timeline date using documented events. Nuclear plant data is cross-referenced with IAEA monitoring reports.
Air Defense Performance
Missile and drone attack data is curated from Ukrainian Air Force command reports, tracking interception rates by weapon type (cruise missiles, ballistic missiles, Shahed drones, guided bombs). Each major attack wave is logged with totals launched, intercepted, and the resulting interception percentage.
Sanctions
Sanctions data is curated from official published lists including EU Council regulations, US Treasury OFAC designations, and UK Government sanctions. The timeline tracks when each major sanctions package was adopted and what categories of restrictions it imposed.
Thermal Anomalies
Near-real-time fire and explosion detections come from NASA's Fire Information for Resource Management System (FIRMS), which provides satellite-detected thermal anomalies from the VIIRS instrument. These are displayed as map markers showing active fires and potential strike impacts.
Pre-Invasion Mobilization
The buildup layer visualizes the Russian military mobilization that preceded the full-scale invasion (March 2021 – February 2022). This data is curated from multiple open-source intelligence references since no single structured API exists for this historical period. Force grouping locations, troop estimates, battalion tactical group (BTG) counts, and equipment compositions are compiled from:
- Wikipedia Order of Battle — Structured table of 9 force groupings with staging locations, BTG counts, and parent army units
- Wikipedia "Prelude to the 2022 Russian invasion" — Timeline of troop movements and buildup milestones
- CSIS "Russia's Possible Invasion of Ukraine" (Jan 2022) — Analysis of three planned invasion axes with satellite imagery locations
- Zapad 2021 Exercise Documentation — 200,000-troop joint Russia-Belarus exercise across 14 training grounds
- IISS Military Balance 2022 — Force structure and equipment inventory reference data
All troop and equipment numbers shown are consensus estimates from open-source intelligence, not verified counts. The buildup is presented in three phases: Phase 1 (March–April 2021, initial deployment), Zapad 2021 (September 2021, joint exercise), and Phase 2 (October 2021–February 2022, final invasion positioning).
- Node.js 22+ (pinned via
.node-version) - npm 10+
git clone https://github.com/engelde/ukrainewar.git
cd ukrainewar
npm installCopy .env.example to .env.local and fill in the required values:
cp .env.example .env.local| Variable | Required | Description |
|---|---|---|
ACLED_EMAIL |
Yes | ACLED API email — register here |
ACLED_PASSWORD |
Yes | ACLED API password |
ENTSOE_TOKEN |
No | ENTSO-E Transparency Platform API token for energy data |
NASA_FIRMS_KEY |
No | NASA FIRMS API key for thermal anomaly detection (falls back to demo key) |
CACHE_REFRESH_SECRET |
Yes | Shared secret for the /api/cache/refresh endpoint used by the cron worker |
For Cloudflare Workers deployment, set secrets via Wrangler:
wrangler secret put ACLED_EMAIL
wrangler secret put ACLED_PASSWORD
wrangler secret put CACHE_REFRESH_SECRETnpm run devOpen http://localhost:3000 to view the application.
| Script | Description |
|---|---|
npm run dev |
Start development server (Turbopack) |
npm run build |
Production build |
npm run lint |
Run Biome linter |
npm run lint:fix |
Auto-fix linting issues |
npm run format |
Format code with Biome |
npm run typecheck |
TypeScript type checking |
npm run cache:warm |
Pre-warm persistent caches (ACLED data) |
npm run data:update |
Process all static data sources |
npm run build:worker |
Build for Cloudflare Workers |
npm run deploy |
Deploy to Cloudflare Workers |
npm run deploy:cron |
Deploy the data-refresh cron worker |
The application is deployed to Cloudflare Workers using OpenNextJS Cloudflare.
Create a KV namespace for the persistent cache layer:
wrangler kv:namespace create "CACHE"Copy the returned namespace ID and update wrangler.jsonc:
npm run build:worker
npm run deployA separate Cloudflare Worker handles scheduled data refresh via cron triggers (every 6 hours), pre-warming all API caches.
npm run deploy:cronContributions are welcome. Please note:
- This project uses conventional commits enforced by commitlint
- All code is linted and formatted by Biome (pre-commit hook)
- PRs must pass CI checks (lint, typecheck, build)
# Example commit
git commit -m "feat: add population displacement chart"
# Commit types: feat, fix, docs, style, refactor, perf, test, build, ci, choreThis project aggregates, cross-references, and visualizes publicly available conflict data. It does not generate original analysis or make claims beyond what the underlying sources report.
- Russian military losses are displayed from the Ukrainian Ministry of Defence daily reports. These are official claims and may differ from independently verified counts. WarSpotting data provides a separate, OSINT-verified count that is typically 30–50% of official figures — both are displayed with clear source attribution.
- Ukrainian military losses are not officially published by Ukraine. Estimates are compiled from Mediazona/BBC confirmed-by-name investigations (conservative minimums), Western intelligence assessments (US, UK, EU), and partial official disclosures. All estimates are presented with source attribution and uncertainty disclaimers.
- Territory control is derived from DeepState Map's daily GeoJSON releases, with coverage from July 2024 onward. Earlier periods use VIINA territorial assessments where available.
- Conflict events are sourced from ACLED's geocoded event database, filtered for events with 5+ fatalities. Key events combine Wikidata SPARQL queries with curated editorial selections for political and diplomatic milestones.
- Humanitarian data comes from UNHCR (refugees/IDPs), OCHA (funding appeals), and OHCHR (civilian casualties). Refugee and IDP figures are available as yearly snapshots; civilian casualties are monthly.
- Bilateral aid data is from the Kiel Institute's Ukraine Support Tracker, which tracks committed and disbursed military, financial, and humanitarian aid from 41 donor countries.
- Energy infrastructure data combines ENTSO-E electricity generation figures with curated plant-level status information. Gas transit volumes are sourced from ENTSOG's Transparency Platform, filtered for Ukrainian interconnection points.
- Thermal anomaly detections are sourced from NASA FIRMS using the VIIRS satellite instrument. Detections are filtered to the conflict zone and displayed as potential fire/strike indicators — not all detections represent military activity.
- Missile attack data is compiled from Ukrainian Air Force daily reports. The dataset includes 40 curated major attack waves from February 2022 through May 2025, with weapon types, quantities launched, and interception counts.
- Strategic asset positions (nuclear plants, dams, bridges, ports, NATO bases, Belarus military positions, Ukrainian and Russian bases) are sourced from curated geospatial datasets and updated as conditions change.
- International support alignment data tracks 48 countries across both sides, with aid figures sourced from the Kiel Institute's Ukraine Support Tracker and open records.
- OHCHR civilian casualty figures are considered conservative minimums — actual figures are likely higher
- Ukrainian military casualty estimates vary widely between sources (Mediazona confirms ~43,000 by name; Western intelligence suggests ~100,000). No single figure is definitive
- ACLED free-tier access has a 12-month recency restriction; older data may be limited
- Territory GeoJSON is only available from July 2024; earlier frontline positions are approximated
- Equipment loss markers only appear where geolocation data is available (a subset of confirmed losses)
- Refugee and IDP data updates yearly, not monthly — during timeline playback, the most recent available year's figures are shown
- Humanitarian funding data reflects UN-coordinated appeals only, not total global aid
- NASA FIRMS thermal detections include non-conflict sources (e.g., agricultural fires, industrial activity); not all anomalies indicate military strikes
- ENTSO-E generation data reflects grid-connected output only and may not capture off-grid or emergency generation
- Missile attack interception rates are based on Ukrainian Air Force claims, which may differ from independent assessments
- Strategic asset positions (NATO, Belarus) are based on publicly reported information and may not reflect all deployments
Created and maintained by David Engel
This is an independent, open-source research project. It is not affiliated with, endorsed by, or funded by any government, military organization, or news outlet. The project exists to make publicly available conflict data more accessible and understandable.
This project relies on publicly available data from the sources listed above. Each data source retains its own licensing terms. The ACLED dataset is used under CC-BY 4.0. Kiel Institute data is from the publicly available Ukraine Support Tracker. UNHCR and OCHA data are provided through their respective open data portals. NASA FIRMS data is freely available under NASA's open data policy. ENTSO-E and ENTSOG data are accessed through their public Transparency Platforms.
If you use this project in academic work, please cite:
Engel, D. (2026). Russo-Ukrainian War Tracker [Web application].
https://ukrainewar.app. Source code: https://github.com/engelde/ukrainewar
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
This means you are free to:
- Use — run the application for any purpose
- Study — read and learn from the source code
- Modify — adapt and build upon this work
- Share — distribute copies
Under the following conditions:
- Source disclosure — if you deploy a modified version, you must make the source code available
- Same license — derivative works must be licensed under AGPL-3.0
- Attribution — you must give appropriate credit
See LICENSE.txt for the full license text.
ukrainewar.app · Built with data, designed for understanding.
This project is an independent effort and is not affiliated with any government or military organization.