Signal Atlas is a hackathon demo for a global OSINT instability watchfloor. It ingests open RSS reporting, extracts instability-related signals, geolocates them with confidence scoring, and turns them into an interactive heatmap that helps analysts see where civil unrest or military instability may be intensifying.
- Pulls live RSS items from a curated catalog of international news, analysis, and official sources
- Pulls public Bluesky posts from targeted instability watch queries using the public AppView API
- Normalizes each item into a shared
SourceItemshape with provenance and feed metadata - Infers likely geography from article text and source hints, then rolls low-confidence results up to country level
- Classifies signals into civil unrest, military instability, and narrative-risk indicators
- Scores locations based on recency, severity, corroboration, and confidence
- Renders the results as an interactive globe or flat map with evidence bundles and next-step OSINT suggestions
- Data sources: live RSS feeds and public Bluesky watch queries
- Active source mix: international news, official advisories, and conflict-analysis feeds
- Output: a browser-based watchfloor showing hotspots, score splits, evidence, and trend direction
- Current goal: help analysts decide where to focus deeper OSINT next
npm run refresh:rssfetches the live RSS catalog and writes a normalized cache tosrc/generated/rss-cache.json.npm run refresh:blueskycollects public Bluesky posts for the watch catalog and writessrc/generated/bluesky-cache.json.npm run refresh:liveruns both live refresh steps together.npm run generate:datatransforms the cached items into signal events and location scores.npm run buildregenerates the dataset and copies the static app intodist/.npm run devserves the app locally so the watchfloor can be viewed in a browser.
npm run refresh:rss
npm run refresh:bluesky
npm run refresh:live
npm run build
npm run devThen open http://127.0.0.1:4173.
npm run refresh:rssfetches the live RSS catalog and snapshots normalized feed items intosrc/generated/rss-cache.json.npm run refresh:blueskyfetches public Bluesky watch results intosrc/generated/bluesky-cache.json.npm run refresh:liverefreshes both RSS and BlueSky caches in sequence.npm run generate:dataregenerates the dataset from any live RSS and Bluesky caches when present, otherwise it falls back to seeded demoSourceItemrecords.npm run buildregenerates data and copies the app intodist/.npm run build:liverefreshes both live caches, then rebuilds the app.npm testruns the geolocation, signal-classification, and hotspot-scoring tests.npm run devserves the repo locally on port4173.
- Geography is heuristic and backed by a small built-in gazetteer
- Signal classification is still taxonomy and keyword driven
- Bluesky coverage is targeted watch-query collection, not full-network firehose coverage