worldmonitor-intelligence-dashboard by aradotso/trending-skills
npx skills add https://github.com/aradotso/trending-skills --skill worldmonitor-intelligence-dashboard技能来自 ara.so — Daily 2026 技能集。
World Monitor 是一个实时全球智能仪表板,集成了 AI 驱动的新闻聚合(435+ 个订阅源,15 个类别)、双地图引擎(3D 地球仪 + 带有 45 个数据层的 WebGL 平面地图)、地缘政治风险评分、金融雷达(92 个交易所)以及跨流信号关联——所有这些都来自一个单一的 TypeScript/Vite 代码库,可部署为 Web 应用、PWA 或原生桌面应用(Tauri 2)。
git clone https://github.com/koala73/worldmonitor.git
cd worldmonitor
npm install
npm run dev # 打开 http://localhost:5173
基本运行无需环境变量。默认情况下,所有功能都使用本地 Ollama。
npm run dev:tech # tech.worldmonitor.app 变体
npm run dev:finance # finance.worldmonitor.app 变体
npm run dev:commodity # commodity.worldmonitor.app 变体
npm run dev:happy # happy.worldmonitor.app 变体
npm run typecheck # TypeScript 验证
npm run build:full # 构建所有变体
npm run build # 构建默认(world)变体
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
worldmonitor/
├── src/
│ ├── components/ # UI 组件 (TypeScript)
│ ├── feeds/ # 435+ RSS/API 订阅源定义
│ ├── layers/ # 地图数据层 (deck.gl)
│ ├── ai/ # AI 合成管道
│ ├── signals/ # 跨流关联引擎
│ ├── finance/ # 市场数据 (92 个交易所)
│ ├── variants/ # 站点变体配置 (world/tech/finance/commodity/happy)
│ └── protos/ # Protocol Buffer 定义 (92 个 protos, 22 个服务)
├── api/ # Vercel Edge Functions (60+)
├── src-tauri/ # Tauri 2 桌面应用 (Rust)
├── docs/ # 文档源码
└── vite.config.ts
创建一个 .env.local 文件(切勿提交密钥):
# AI 提供商(全部可选 — Ollama 无需密钥即可工作)
VITE_OLLAMA_BASE_URL=http://localhost:11434 # 本地 Ollama 实例
VITE_GROQ_API_KEY=$GROQ_API_KEY # Groq 云端推理
VITE_OPENROUTER_API_KEY=$OPENROUTER_API_KEY # OpenRouter 多模型
# 缓存(可选,提升性能)
UPSTASH_REDIS_REST_URL=$UPSTASH_REDIS_REST_URL
UPSTASH_REDIS_REST_TOKEN=$UPSTASH_REDIS_REST_TOKEN
# 地图瓦片(可选,MapLibre GL)
VITE_MAPTILER_API_KEY=$MAPTILER_API_KEY
# 变体选择
VITE_SITE_VARIANT=world # world | tech | finance | commodity | happy
World Monitor 聚合了 15 个类别的 435+ 个订阅源:
// src/feeds/categories.ts 模式
import type { FeedCategory } from './types';
const FEED_CATEGORIES: FeedCategory[] = [
'geopolitics',
'military',
'economics',
'technology',
'climate',
'energy',
'health',
'finance',
'commodities',
'infrastructure',
'cyber',
'space',
'diplomacy',
'disasters',
'society',
];
每个国家跨 12 个信号类别的综合风险评分:
// 示例:访问国家风险评分
import { CountryIntelligence } from './signals/country-intelligence';
const intel = new CountryIntelligence();
// 获取国家的综合风险评分
const score = await intel.getCountryScore('UA');
console.log(score);
// {
// composite: 0.82,
// signals: {
// military: 0.91,
// economic: 0.74,
// political: 0.88,
// humanitarian: 0.79,
// ...
// },
// trend: 'escalating',
// updatedAt: '2026-03-17T08:00:00Z'
// }
// 订阅实时更新
intel.subscribe('UA', (update) => {
console.log('风险更新:', update);
});
// src/ai/synthesize.ts 模式
import { AISynthesizer } from './ai/synthesizer';
const synth = new AISynthesizer({
provider: 'ollama', // 'ollama' | 'groq' | 'openrouter'
model: 'llama3.2', // 任何 Ollama 兼容模型
baseUrl: process.env.VITE_OLLAMA_BASE_URL,
});
// 从多个订阅源条目合成新闻简报
const brief = await synth.synthesize({
items: feedItems, // FeedItem[]
category: 'geopolitics',
region: 'Europe',
maxTokens: 500,
language: 'en',
});
console.log(brief.summary); // AI 生成的摘要
console.log(brief.signals); // 提取的信号数组
console.log(brief.confidence); // 0-1 置信度分数
// src/signals/correlator.ts 模式
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);
console.log('升级概率:', convergence.probability);
console.log('贡献事件:', convergence.events);
}
// src/components/globe/GlobeView.ts
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/>风险: ${(d.riskScore * 100).toFixed(0)}%`
);
return globe;
}
function riskToColor(score: number): string {
if (score > 0.8) return 'rgba(220, 38, 38, 0.8)'; // 危急
if (score > 0.6) return 'rgba(234, 88, 12, 0.7)'; // 高
if (score > 0.4) return 'rgba(202, 138, 4, 0.6)'; // 升高
if (score > 0.2) return 'rgba(22, 163, 74, 0.5)'; // 低
return 'rgba(15, 118, 110, 0.4)'; // 最低
}
// src/components/map/DeckMap.ts
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(),
getPosition: d => [d.lng, d.lat],
getRadius: d => d.severity * 50000,
getFillColor: d => severityToRGBA(d.severity),
pickable: true,
}),
// 供应链弧线图层
new ArcLayer({
id: 'supply-chains',
data: getSupplyChainData(),
getSourcePosition: d => d.source,
getTargetPosition: d => d.target,
getSourceColor: [0, 128, 200],
getTargetColor: [200, 0, 80],
getWidth: 2,
}),
],
});
return { map, deck };
}
// src/finance/radar.ts 模式
import { FinanceRadar } from './finance/radar';
const radar = new FinanceRadar();
// 获取市场综合指数(7 信号)
const composite = await radar.getMarketComposite();
console.log(composite);
// {
// score: 0.62,
// signals: {
// volatility: 0.71,
// momentum: 0.58,
// sentiment: 0.65,
// liquidity: 0.44,
// correlation: 0.78,
// macro: 0.61,
// geopolitical: 0.82
// },
// exchanges: 92,
// timestamp: '2026-03-17T08:00:00Z'
// }
// 监控特定交易所
const exchange = await radar.getExchange('NYSE');
const crypto = await radar.getCrypto(['BTC', 'ETH', 'SOL']);
const commodities = await radar.getCommodities(['GOLD', 'OIL', 'WHEAT']);
World Monitor 支持 21 种语言,并提供本地语言订阅源:
// src/i18n/config.ts 模式
import { setLanguage, getAvailableLanguages } from './i18n';
const languages = getAvailableLanguages();
// ['en', 'ar', 'zh', 'ru', 'fr', 'es', 'de', 'ja', 'ko', 'pt',
// 'hi', 'fa', 'tr', 'pl', 'uk', 'nl', 'sv', 'he', 'it', 'vi', 'id']
// 切换语言(自动处理 RTL)
await setLanguage('ar'); // 阿拉伯语 — 触发 RTL 布局
await setLanguage('he'); // 希伯来语 — 触发 RTL 布局
await setLanguage('fa'); // 波斯语 — 触发 RTL 布局
// 配置订阅源语言过滤
import { FeedManager } from './feeds/manager';
const feeds = new FeedManager({ language: 'ar', includeEnglish: true });
// src/protos — 92 个 proto 定义,22 个服务
// 示例生成的客户端用法:
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());
});
// api/feeds/aggregate.ts — Edge Function 示例
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: parseInt(limit),
});
await setCachedData(cacheKey, items, { ttl: 300 }); // 5 分钟 TTL
return res.json(items);
}
# 安装 Tauri CLI
cargo install tauri-cli
# 开发
npm run tauri:dev
# 构建原生应用
npm run tauri:build
# 输出: .exe (Windows), .dmg/.app (macOS), .AppImage (Linux)
// src-tauri/src/main.rs — IPC 命令示例
#[tauri::command]
async fn fetch_intelligence(country: String) -> Result<CountryData, String> {
// Sidecar Node.js 进程处理订阅源聚合
// Tauri 处理渲染器与后端之间的安全 IPC
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 单容器
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 带 Redis
docker compose up -d
# docker-compose.yml
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:
npm i -g vercel
vercel --prod
# 在 Vercel 仪表板或通过 CLI 设置环境变量:
vercel env add GROQ_API_KEY production
vercel env add UPSTASH_REDIS_REST_URL production
vercel env add UPSTASH_REDIS_REST_TOKEN production
// 将自定义 RSS 订阅源添加到聚合管道
import { FeedRegistry } from './src/feeds/registry';
FeedRegistry.register({
id: 'my-custom-feed',
name: '我的情报源',
url: 'https://example.com/feed.xml',
category: 'geopolitics',
region: 'Asia',
language: 'en',
weight: 0.8, // 0-1,影响信号权重
refreshInterval: 300, // 秒
parser: 'rss2', // 'rss2' | 'atom' | 'json'
});
// 在 45 层系统中注册自定义 deck.gl 图层
import { LayerRegistry } from './src/layers/registry';
import { IconLayer } from '@deck.gl/layers';
LayerRegistry.register({
id: 'my-custom-layer',
name: '自定义事件',
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,
}),
});
// src/variants/my-variant.ts
import type { SiteVariant } from './types';
export const myVariant: SiteVariant = {
id: 'my-variant',
name: '我的监视器',
title: '我的自定义监视器',
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',
},
};
| 问题 | 解决方案 |
|---|---|
| 地图未渲染 | 检查 VITE_MAPTILER_API_KEY 或使用免费的 CartoBasemap 样式 |
| AI 合成缓慢/失败 | 确保 Ollama 正在运行:ollama serve && ollama pull llama3.2 |
| 订阅源返回 429 错误 | 通过 UPSTASH_REDIS_REST_* 环境变量启用 Redis 缓存 |
| 桌面应用无法构建 | 确保已安装 Rust + cargo install tauri-cli + 平台构建工具 |
| RTL 布局损坏 | 确认 setLanguage() 已在 <html> 上设置了 lang 属性 |
| 构建时出现 TypeScript 错误 | 运行 npm run typecheck — proto 生成的文件必须存在 |
| Redis 连接被拒绝 | 检查 REDIS_URL 或使用 Upstash REST API 替代 TCP |
npm run build:full 在变体构建中途失败 | 单独构建:npm run build -- --mode finance |
# 安装 Ollama
curl -fsSL https://ollama.ai/install.sh | sh
# 拉取推荐模型
ollama pull llama3.2 # 快速,质量好
ollama pull mistral # 替代方案
ollama pull gemma2:9b # 更大,质量更高
# 验证 Ollama 可访问
curl http://localhost:11434/api/tags
npm run typecheck # 应退出码为 0
npm run dev # 应打开 localhost:5173
# 导航到 /api/health 查看 API 状态
curl http://localhost:5173/api/health
每周安装量
323
代码仓库
GitHub 星标数
8
首次出现
6 天前
安全审计
已安装于
github-copilot320
codex320
kimi-cli320
amp320
cline320
gemini-cli320
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).
git clone https://github.com/koala73/worldmonitor.git
cd worldmonitor
npm install
npm run dev # Opens http://localhost:5173
No environment variables required for basic operation. All features work with local Ollama by default.
npm run dev:tech # tech.worldmonitor.app variant
npm run dev:finance # finance.worldmonitor.app variant
npm run dev:commodity # commodity.worldmonitor.app variant
npm run dev:happy # happy.worldmonitor.app variant
npm run typecheck # TypeScript validation
npm run build:full # Build all variants
npm run build # Build default (world) variant
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
Create a .env.local file (never commit secrets):
# AI Providers (all optional — Ollama works with no keys)
VITE_OLLAMA_BASE_URL=http://localhost:11434 # Local Ollama instance
VITE_GROQ_API_KEY=$GROQ_API_KEY # Groq cloud inference
VITE_OPENROUTER_API_KEY=$OPENROUTER_API_KEY # OpenRouter multi-model
# Caching (optional, improves performance)
UPSTASH_REDIS_REST_URL=$UPSTASH_REDIS_REST_URL
UPSTASH_REDIS_REST_TOKEN=$UPSTASH_REDIS_REST_TOKEN
# Map tiles (optional, MapLibre GL)
VITE_MAPTILER_API_KEY=$MAPTILER_API_KEY
# Variant selection
VITE_SITE_VARIANT=world # world | tech | finance | commodity | happy
World Monitor aggregates 435+ feeds across 15 categories:
// src/feeds/categories.ts pattern
import type { FeedCategory } from './types';
const FEED_CATEGORIES: FeedCategory[] = [
'geopolitics',
'military',
'economics',
'technology',
'climate',
'energy',
'health',
'finance',
'commodities',
'infrastructure',
'cyber',
'space',
'diplomacy',
'disasters',
'society',
];
Composite risk scoring across 12 signal categories per country:
// Example: accessing country risk scores
import { CountryIntelligence } from './signals/country-intelligence';
const intel = new CountryIntelligence();
// Get composite risk score for a country
const score = await intel.getCountryScore('UA');
console.log(score);
// {
// composite: 0.82,
// signals: {
// military: 0.91,
// economic: 0.74,
// political: 0.88,
// humanitarian: 0.79,
// ...
// },
// trend: 'escalating',
// updatedAt: '2026-03-17T08:00:00Z'
// }
// Subscribe to real-time updates
intel.subscribe('UA', (update) => {
console.log('Risk update:', update);
});
// src/ai/synthesize.ts pattern
import { AISynthesizer } from './ai/synthesizer';
const synth = new AISynthesizer({
provider: 'ollama', // 'ollama' | 'groq' | 'openrouter'
model: 'llama3.2', // any Ollama-compatible model
baseUrl: process.env.VITE_OLLAMA_BASE_URL,
});
// Synthesize a news brief from multiple feed items
const brief = await synth.synthesize({
items: feedItems, // FeedItem[]
category: 'geopolitics',
region: 'Europe',
maxTokens: 500,
language: 'en',
});
console.log(brief.summary); // AI-generated synthesis
console.log(brief.signals); // Extracted signals array
console.log(brief.confidence); // 0-1 confidence score
// src/signals/correlator.ts pattern
import { SignalCorrelator } from './signals/correlator';
const correlator = new SignalCorrelator();
// Detect convergence across military, economic, disaster signals
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);
}
// src/components/globe/GlobeView.ts
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');
// Load country risk layer
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): string {
if (score > 0.8) return 'rgba(220, 38, 38, 0.8)'; // critical
if (score > 0.6) return 'rgba(234, 88, 12, 0.7)'; // high
if (score > 0.4) return 'rgba(202, 138, 4, 0.6)'; // elevated
if (score > 0.2) return 'rgba(22, 163, 74, 0.5)'; // low
return 'rgba(15, 118, 110, 0.4)'; // minimal
}
// src/components/map/DeckMap.ts
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: [
// Event scatter layer
new ScatterplotLayer({
id: 'events',
data: getActiveEvents(),
getPosition: d => [d.lng, d.lat],
getRadius: d => d.severity * 50000,
getFillColor: d => severityToRGBA(d.severity),
pickable: true,
}),
// Supply chain arc layer
new ArcLayer({
id: 'supply-chains',
data: getSupplyChainData(),
getSourcePosition: d => d.source,
getTargetPosition: d => d.target,
getSourceColor: [0, 128, 200],
getTargetColor: [200, 0, 80],
getWidth: 2,
}),
],
});
return { map, deck };
}
// src/finance/radar.ts pattern
import { FinanceRadar } from './finance/radar';
const radar = new FinanceRadar();
// Get market composite (7-signal)
const composite = await radar.getMarketComposite();
console.log(composite);
// {
// score: 0.62,
// signals: {
// volatility: 0.71,
// momentum: 0.58,
// sentiment: 0.65,
// liquidity: 0.44,
// correlation: 0.78,
// macro: 0.61,
// geopolitical: 0.82
// },
// exchanges: 92,
// timestamp: '2026-03-17T08:00:00Z'
// }
// Watch specific exchange
const exchange = await radar.getExchange('NYSE');
const crypto = await radar.getCrypto(['BTC', 'ETH', 'SOL']);
const commodities = await radar.getCommodities(['GOLD', 'OIL', 'WHEAT']);
World Monitor supports 21 languages with native-language feeds:
// src/i18n/config.ts pattern
import { setLanguage, getAvailableLanguages } from './i18n';
const languages = getAvailableLanguages();
// ['en', 'ar', 'zh', 'ru', 'fr', 'es', 'de', 'ja', 'ko', 'pt',
// 'hi', 'fa', 'tr', 'pl', 'uk', 'nl', 'sv', 'he', 'it', 'vi', 'id']
// Switch language (handles RTL automatically)
await setLanguage('ar'); // Arabic — triggers RTL layout
await setLanguage('he'); // Hebrew — triggers RTL layout
await setLanguage('fa'); // Farsi — triggers RTL layout
// Configure feed language filtering
import { FeedManager } from './feeds/manager';
const feeds = new FeedManager({ language: 'ar', includeEnglish: true });
// src/protos — 92 proto definitions, 22 services
// Example generated client usage:
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());
});
// api/feeds/aggregate.ts — Edge Function example
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: parseInt(limit),
});
await setCachedData(cacheKey, items, { ttl: 300 }); // 5 min TTL
return res.json(items);
}
# Install Tauri CLI
cargo install tauri-cli
# Development
npm run tauri:dev
# Build native app
npm run tauri:build
# Outputs: .exe (Windows), .dmg/.app (macOS), .AppImage (Linux)
// src-tauri/src/main.rs — IPC command example
#[tauri::command]
async fn fetch_intelligence(country: String) -> Result<CountryData, String> {
// Sidecar Node.js process handles feed aggregation
// Tauri handles secure IPC between renderer and backend
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 single-container
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 with Redis
docker compose up -d
# docker-compose.yml
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:
npm i -g vercel
vercel --prod
# Set env vars in Vercel dashboard or via CLI:
vercel env add GROQ_API_KEY production
vercel env add UPSTASH_REDIS_REST_URL production
vercel env add UPSTASH_REDIS_REST_TOKEN production
// Add a custom RSS feed to the aggregation pipeline
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, // 0-1, affects signal weighting
refreshInterval: 300, // seconds
parser: 'rss2', // 'rss2' | 'atom' | 'json'
});
// Register a custom deck.gl layer in the 45-layer system
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,
}),
});
// src/variants/my-variant.ts
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',
},
};
| 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 |
# Install Ollama
curl -fsSL https://ollama.ai/install.sh | sh
# Pull recommended model
ollama pull llama3.2 # Fast, good quality
ollama pull mistral # Alternative
ollama pull gemma2:9b # Larger, higher quality
# Verify Ollama is accessible
curl http://localhost:11434/api/tags
npm run typecheck # Should exit 0
npm run dev # Should open localhost:5173
# Navigate to /api/health for API status
curl http://localhost:5173/api/health
Weekly Installs
323
Repository
GitHub Stars
8
First Seen
6 days ago
Security Audits
Gen Agent Trust HubFailSocketWarnSnykWarn
Installed on
github-copilot320
codex320
kimi-cli320
amp320
cline320
gemini-cli320
超能力技能使用指南:AI助手技能调用优先级与工作流程详解
40,300 周安装
小红书封面生成器 - 一键生成小红书风格封面图片,支持自定义主题,AI驱动
950 周安装
Scrapling官方网络爬虫框架 - 自适应解析、绕过Cloudflare、Python爬虫库
952 周安装
Manim Composer:AI 驱动的 3Blue1Brown 风格数学动画制作工具
946 周安装
GitHub PRD 撰写与提交指南:15分钟完成产品需求文档和Pull Request
952 周安装
PHP 8.x 最佳实践指南:51条规则掌握现代PHP开发、PSR标准与SOLID原则
957 周安装
Oracle CLI 工具:基于 GPT-5.2 Pro 的代码分析与智能问答助手,支持浏览器与 API 模式
312 周安装
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 |