| name | worldmonitor-intelligence-dashboard |
| description | Real-time global intelligence dashboard with AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking |
| triggers | ["set up worldmonitor dashboard","add geopolitical monitoring to my app","integrate worldmonitor news feeds","build situational awareness dashboard","configure worldmonitor AI intelligence","self-host worldmonitor","add OSINT dashboard to project","worldmonitor map layers and data feeds"] |
World Monitor Intelligence Dashboard
Skill by ara.so — Daily 2026 Skills collection.
World Monitor is a real-time global intelligence dashboard combining AI-powered news aggregation (435+ feeds, 15 categories), dual map engine (3D globe + WebGL flat map with 45 data layers), geopolitical risk scoring, finance radar (92 exchanges), and cross-stream signal correlation — all from a single TypeScript/Vite codebase deployable as web, PWA, or native desktop (Tauri 2).
Installation & Quick Start
git clone https://github.com/koala73/worldmonitor.git
cd worldmonitor
npm install
npm run dev
No environment variables required for basic operation. All features work with local Ollama by default.
Site Variants
npm run dev:tech
npm run dev:finance
npm run dev:commodity
npm run dev:happy
Production Build
npm run typecheck
npm run build:full
npm run build
Project Structure
worldmonitor/
├── src/
│ ├── components/ # UI components (TypeScript)
│ ├── feeds/ # 435+ RSS/API feed definitions
│ ├── layers/ # Map data layers (deck.gl)
│ ├── ai/ # AI synthesis pipeline
│ ├── signals/ # Cross-stream correlation engine
│ ├── finance/ # Market data (92 exchanges)
│ ├── variants/ # Site variant configs (world/tech/finance/commodity/happy)
│ └── protos/ # Protocol Buffer definitions (92 protos, 22 services)
├── api/ # Vercel Edge Functions (60+)
├── src-tauri/ # Tauri 2 desktop app (Rust)
├── docs/ # Documentation source
└── vite.config.ts
Environment Variables
Create a .env.local file (never commit secrets):
VITE_OLLAMA_BASE_URL=http://localhost:11434
VITE_GROQ_API_KEY=$GROQ_API_KEY
VITE_OPENROUTER_API_KEY=$OPENROUTER_API_KEY
UPSTASH_REDIS_REST_URL=$UPSTASH_REDIS_REST_URL
UPSTASH_REDIS_REST_TOKEN=$UPSTASH_REDIS_REST_TOKEN
VITE_MAPTILER_API_KEY=$MAPTILER_API_KEY
VITE_SITE_VARIANT=world
Core Concepts
Feed Categories
World Monitor aggregates 435+ feeds across 15 categories:
import type { FeedCategory } from './types';
const FEED_CATEGORIES: FeedCategory[] = [
'geopolitics',
'military',
'economics',
'technology',
'climate',
'energy',
'health',
'finance',
'commodities',
'infrastructure',
'cyber',
'space',
'diplomacy',
'disasters',
'society',
];
Country Intelligence Index
Composite risk scoring across 12 signal categories per country:
import { CountryIntelligence } from './signals/country-intelligence';
const intel = new CountryIntelligence();
const score = await intel.getCountryScore('UA');
console.log(score);
intel.subscribe('UA', (update) => {
console.log('Risk update:', update);
});
AI Synthesis Pipeline
import { AISynthesizer } from './ai/synthesizer';
const synth = new AISynthesizer({
provider: 'ollama',
model: 'llama3.2',
baseUrl: process.env.VITE_OLLAMA_BASE_URL,
});
const brief = await synth.synthesize({
items: feedItems,
category: 'geopolitics',
region: 'Europe',
maxTokens: 500,
language: 'en',
});
console.log(brief.summary);
console.log(brief.signals);
console.log(brief.confidence);
Cross-Stream Signal Correlation
import { SignalCorrelator } from './signals/correlator';
const correlator = new SignalCorrelator();
const convergence = await correlator.detectConvergence({
streams: ['military', 'economic', 'disaster', 'escalation'],
timeWindow: '6h',
threshold: 0.7,
region: 'Middle East',
});
if (convergence.detected) {
console.log('Convergence signals:', convergence.signals);
console.log('Escalation probability:', convergence.probability);
console.log('Contributing events:', convergence.events);
}
Map Engine Integration
3D Globe (globe.gl)
import Globe from 'globe.gl';
import { getCountryRiskData } from '../signals/country-intelligence';
export function initGlobe(container: HTMLElement) {
const globe = Globe()(container)
.globeImageUrl('//unpkg.com/three-globe/example/img/earth-dark.jpg')
.backgroundImageUrl('//unpkg.com/three-globe/example/img/night-sky.png');
const riskData = await getCountryRiskData();
globe
.polygonsData(riskData.features)
.polygonCapColor(feat => riskToColor(feat.properties.riskScore))
.polygonSideColor(() => 'rgba(0, 100, 0, 0.15)')
.polygonLabel(({ properties: d }) =>
`<b>${d.name}</b><br/>Risk: ${(d.riskScore * 100).toFixed(0)}%`
);
return globe;
}
function riskToColor(score: number): {
(score > ) ;
(score > ) ;
(score > ) ;
(score > ) ;
;
}
WebGL Flat Map (deck.gl + MapLibre GL)
import { Deck } from '@deck.gl/core';
import { ScatterplotLayer, ArcLayer, HeatmapLayer } from '@deck.gl/layers';
import maplibregl from 'maplibre-gl';
export function initDeckMap(container: HTMLElement) {
const map = new maplibregl.Map({
container,
style: 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',
center: [0, 20],
zoom: 2,
});
const deck = new Deck({
canvas: 'deck-canvas',
initialViewState: { longitude: 0, latitude: 20, zoom: 2 },
controller: true,
layers: [
new ScatterplotLayer({
id: 'events',
data: getActiveEvents(),
: [d., d.],
: d. * ,
: (d.),
: ,
}),
({
: ,
: (),
: d.,
: d.,
: [, , ],
: [, , ],
: ,
}),
],
});
{ map, deck };
}
Finance Radar
import { FinanceRadar } from './finance/radar';
const radar = new FinanceRadar();
const composite = await radar.getMarketComposite();
console.log(composite);
const exchange = await radar.getExchange('NYSE');
const crypto = await radar.getCrypto(['BTC', 'ETH', 'SOL']);
const commodities = await radar.getCommodities(['GOLD', 'OIL', 'WHEAT']);
Language & RTL Support
World Monitor supports 21 languages with native-language feeds:
import { setLanguage, getAvailableLanguages } from './i18n';
const languages = getAvailableLanguages();
await setLanguage('ar');
await setLanguage('he');
await setLanguage('fa');
import { FeedManager } from './feeds/manager';
const feeds = new FeedManager({ language: 'ar', includeEnglish: true });
Protocol Buffers (API Contracts)
import { IntelligenceServiceClient } from './protos/generated/intelligence_grpc_web_pb';
import { CountryRequest } from './protos/generated/intelligence_pb';
const client = new IntelligenceServiceClient(
process.env.VITE_API_BASE_URL || 'http://localhost:8080'
);
const request = new CountryRequest();
request.setCountryCode('DE');
request.setTimeRange('24h');
request.setSignalTypes(['military', 'economic', 'political']);
client.getCountryIntelligence(request, {}, (err, response) => {
if (err) console.error(err);
else console.log(response.toObject());
});
Vercel Edge Function Pattern
import type { VercelRequest, VercelResponse } from '@vercel/node';
import { aggregateFeeds } from '../../src/feeds/aggregator';
import { getCachedData, setCachedData } from '../../src/cache/redis';
export const config = { runtime: 'edge' };
export default async function handler(req: VercelRequest, res: VercelResponse) {
const { category, region, limit = '20' } = req.query as Record<string, string>;
const cacheKey = `feeds:${category}:${region}:${limit}`;
const cached = await getCachedData(cacheKey);
if (cached) return res.json(cached);
const items = await aggregateFeeds({
categories: category ? [category] : undefined,
region,
limit: (limit),
});
(cacheKey, items, { : });
res.(items);
}
Desktop App (Tauri 2)
cargo install tauri-cli
npm run tauri:dev
npm run tauri:build
#[tauri::command]
async fn fetch_intelligence(country: String) -> Result<CountryData, String> {
Ok(CountryData::default())
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![fetch_intelligence])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
Docker / Self-Hosting
docker build -t worldmonitor .
docker run -p 3000:3000 \
-e VITE_SITE_VARIANT=world \
-e UPSTASH_REDIS_REST_URL=$UPSTASH_REDIS_REST_URL \
-e UPSTASH_REDIS_REST_TOKEN=$UPSTASH_REDIS_REST_TOKEN \
worldmonitor
docker compose up -d
version: '3.9'
services:
app:
build: .
ports: ['3000:3000']
environment:
- VITE_SITE_VARIANT=world
- REDIS_URL=redis://redis:6379
depends_on: [redis]
redis:
image: redis:7-alpine
volumes: ['redis_data:/data']
volumes:
redis_data:
Vercel Deployment
npm i -g vercel
vercel --prod
vercel env add GROQ_API_KEY production
vercel env add UPSTASH_REDIS_REST_URL production
vercel env add UPSTASH_REDIS_REST_TOKEN production
Common Patterns
Custom Feed Integration
import { FeedRegistry } from './src/feeds/registry';
FeedRegistry.register({
id: 'my-custom-feed',
name: 'My Intelligence Source',
url: 'https://example.com/feed.xml',
category: 'geopolitics',
region: 'Asia',
language: 'en',
weight: 0.8,
refreshInterval: 300,
parser: 'rss2',
});
Custom Map Layer
import { LayerRegistry } from './src/layers/registry';
import { IconLayer } from '@deck.gl/layers';
LayerRegistry.register({
id: 'my-custom-layer',
name: 'Custom Events',
category: 'infrastructure',
defaultVisible: false,
factory: (data) => new IconLayer({
id: 'my-custom-layer-deck',
data,
getPosition: d => [d.lng, d.lat],
getIcon: d => 'marker',
getSize: 32,
pickable: true,
}),
});
Site Variant Configuration
import type { SiteVariant } from './types';
export const myVariant: SiteVariant = {
id: 'my-variant',
name: 'My Monitor',
title: 'My Custom Monitor',
defaultCategories: ['geopolitics', 'economics', 'military'],
defaultRegion: 'Europe',
defaultLanguage: 'en',
mapStyle: 'dark',
enabledLayers: ['country-risk', 'events', 'supply-chains'],
aiProvider: 'ollama',
theme: {
primary: '#0891b2',
background: '#0f172a',
surface: '#1e293b',
},
};
Troubleshooting
| Problem | Solution |
|---|
| Map not rendering | Check VITE_MAPTILER_API_KEY or use free CartoBasemap style |
| AI synthesis slow/failing | Ensure Ollama is running: ollama serve && ollama pull llama3.2 |
| Feeds returning 429 errors | Enable Redis caching via UPSTASH_REDIS_REST_* env vars |
| Desktop app won't build | Ensure Rust + cargo install tauri-cli + platform build tools |
| RTL layout broken | Confirm lang attribute set on <html> by setLanguage() |
| TypeScript errors on build | Run npm run typecheck — proto generated files must exist |
| Redis connection refused | Check REDIS_URL or use Upstash REST API instead of TCP |
npm run build:full fails mid-variant | Build individually: npm run build -- --mode finance |
Ollama Setup for Local AI
curl -fsSL https://ollama.ai/install.sh | sh
ollama pull llama3.2
ollama pull mistral
ollama pull gemma2:9b
curl http://localhost:11434/api/tags
Verify Installation
npm run typecheck
npm run dev
curl http://localhost:5173/api/health
Resources