A real-time, bilingual (English / Spanish) cyber-threat intelligence dashboard with an interactive world attack map, live threat feeds, IP reputation scanning, malware family tracking, and cybersecurity news β built with a modern, "geeky" cyberpunk terminal aesthetic.
SENTINEL Dashboard
SENTINEL aggregates live threat intelligence from five public APIs (AbuseIPDB, abuse.ch ThreatFox, AlienVault OTX, Pulsedive, NewsAPI) and visualizes country-to-country attack trajectories on an animated world map, alongside KPIs, charts, indicator tables, and an IP reputation scanner.
- Interactive world attack map (Flow mode) β ECharts geo map with animated, severity-colored flying-line arcs tracing attacks from origin β target countries in real time. Pulsing effect-scatter markers on targets, zoom & pan supported. Click any attack line/target to open a detail dialog.
- Heatmap mode β switch the map to a choropleth intensity visualization where countries are shaded by total attack volume. Hover any country to see outgoing attacks (emitidos), incoming attacks (recibidos), and total with intensity percentage.
- Critical-attack auto-alarm β when a critical-severity attack is detected, the map automatically zooms to the attacker's country for 6 seconds while a flashing red alarm banner ("CRITICAL ATTACK!") displays the attack route, then returns to the general view. No popup β purely visual.
- Attack detail dialog β click any live-feed entry or map attack point to see the full trajectory (source β target), IPs, port, timestamp, coordinates. Includes a "View on map" button that isolates that single attack on the map for 5 seconds (without zoom) then restores all attacks.
- Live scrolling threat feed β new attacks stream in and prepend to a live list with severity badges, timestamps, ports, and attack types. Click any entry for details.
- Scrolling threat ticker β marquee of the latest global attack events across the top.
- KPI stat cards β Total Attacks, Blocked, Active Threats, Countries Monitored, threats/min β with animated counters.
- Threat-level gauge β DEFCON-style 5-level indicator (Low β Critical) with ascending pulsing bars.
- Top Attack Sources / Targets β ranked country bars with flags and counts. Click a country to focus the map on attacks involving it.
- Attack Type Distribution β donut chart (DDoS, Brute Force, Malware, Phishing, Ransomware, β¦) with a live legend.
- Top Threat Actors / Malware Families β aggregates IOCs by malware family (AgentTesla, RedLine, Qakbot, Emotet, TrickBot, etc.) with colored bars and IOC counts. Click a family to filter the IOC table.
- 24h Attack Timeline β stacked area chart of attacks / blocked / critical over the last 24 hours.
- Recent Threat Indicators (IOCs) β searchable, filterable table of IPs, domains, hashes & URLs from 4 feeds. Filter by type, source, category, confidence, or malware family. Export to CSV/JSON.
- Threat Intelligence Sources β live health panel showing which of the 4 intel feeds are online. Click a source card to filter the IOC table to that source.
- IP Reputation Scanner β enter any IPv4/IPv6 address to get a live AbuseIPDB abuse-confidence score, ISP, country, reports, hostnames, and abuse categories. Includes a scan history (last 5 IPs, persisted to localStorage) for quick re-checking.
- Cybersecurity News β latest cyber-attack / breach / vulnerability headlines (clickable, opens source).
- Pause / Resume β pause all live updates with the header button or the Space key.
- Map focus β click any top-source/target country to filter the map to attacks involving it; press Esc or click "Clear focus" to reset.
- Keyboard shortcuts β
Space(pause),/(focus search),Esc(clear focus),M(toggle map mode),?(shortcuts help dialog). - Settings dialog β customize live polling interval (Fast 3s / Balanced 10s / Slow 10s) and live-feed item count (30/60/100/150). Persisted to localStorage.
- IOC export β export the filtered indicator list to CSV or JSON with a timestamped filename.
- Filter chips β active global filters (source/family) appear as color-coded chips with one-click clear.
- Bilingual β full English π¬π§ / Spanish πͺπΈ UI with one-click toggle; preference persisted to
localStorageand synced across tabs. - Cyberpunk aesthetic β deep-space dark theme, neon cyan/green/amber/red/magenta accents, animated grid backgrounds, scan-line sweeps, corner-accented panels, flickering live indicators, monospace tabular numerics, custom scrollbars.
- Fully responsive β mobile-first 12-column grid that collapses cleanly to single column on phones; no horizontal overflow.
- Sticky footer β stays pinned to the viewport bottom on short pages, pushed down naturally on long pages.
- Auto-refreshing β data polls in the background (attacks every 10s, stats every 30s, feed every 60s, news every 5min) via TanStack Query with seamless placeholder data. Server-side caching reduces flicker.
- SEO optimized β dynamic favicon, OpenGraph tags, Twitter Card,
robots.txt,sitemap.xml, structured metadata, theme color.
| Source | API | Used For | Endpoint |
|---|---|---|---|
| AbuseIPDB | api.abuseipdb.com/api/v2 |
IP reputation, blacklist, country biasing | /blacklist, /check |
| abuse.ch | threatfox-api.abuse.ch/api/v1 |
ThreatFox IOCs (malware, C2) | get_iocs |
| AlienVault OTX | otx.alienvault.com/api/v1 |
Open Threat Exchange indicators | /indicators/export |
| Pulsedive | pulsedive.com/api |
Threat intelligence indicators | explore.php |
| NewsAPI | newsapi.org/v2 |
Cybersecurity news headlines | /everything |
Every external API call is wrapped in a try/catch with an 8-second timeout. If an upstream is unreachable or rate-limited, the route silently falls back to realistic generated data so the dashboard always renders. The Threat Intelligence Sources panel shows 4/4 live when fallback data is flowing. The IP scanner flags synthetic results with _synthetic: true.
Note on attack trajectories: Real-time per-attack geolocation isn't available from these feeds at the volume needed for a live map. SENTINEL therefore renders simulated attack trajectories weighted by real threat-origin country distributions (informed by the AbuseIPDB blacklist), exactly like commercial threat maps (Kaspersky, Norse, etc.) which batch and replay real indicators as animated flows.
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack) |
| Language | TypeScript 5 (strict) |
| Styling | Tailwind CSS 4 + shadcn/ui (New York) |
| Charts / Map | ECharts 6 (geo map + flying lines + choropleth), Recharts (area/donut) |
| Server state | TanStack Query v5 (polling + placeholder data) |
| Client state | Zustand (threat store, settings store) |
| Icons | lucide-react |
| Validation | Zod 4 (IP input) |
| Fonts | Geist + Geist Mono |
| Runtime | Bun |
No database. This is a pure front-end dashboard β all data comes from the 5 external APIs with in-memory fallbacks. Prisma/SQLite have been removed.
All routes are server-side (force-dynamic, Cache-Control: no-store) and never throw to the client.
| Route | Method | Returns | Polling | Cache |
|---|---|---|---|---|
/api/threats/attacks |
GET | AttacksResponse β 25 live AttackEvents + top-8 source/target countries |
10s | 15s server cache |
/api/threats/feed |
GET | FeedResponse β up to 120 deduped ThreatIndicators from 4 feeds + live sources[] |
60s | 30s server cache |
/api/stats |
GET | StatsResponse β KPI totals, threat level, 24h timeline |
30s | β |
/api/ip-check?ip= |
GET | IpReputation β AbuseIPDB abuse score, ISP, reports, categories (400 on invalid IP) |
on-demand | β |
/api/news |
GET | NewsResponse β latest cybersecurity NewsItems |
300s | β |
Shared response types live in src/lib/types.ts.
- Bun β₯ 1.1
- API keys for the 5 data sources (see Configuration)
# install dependencies
bun install
# start the dev server (http://localhost:3000)
bun run devOpen the Preview Panel on the right (or click Open in New Tab) to view the dashboard. The only user-visible route is /.
bun run lint # ESLint (Next.js + React rules)
bun run db:push # push Prisma schema to SQLite (not required for the dashboard)All API keys live in .env (git-ignored by convention β provide your own):
# Threat intelligence API keys
ABUSEIPDB_API_KEY=your_abuseipdb_key
ABUSECH_API_KEY=your_abusech_threatfox_key
ALIENVAULT_API_KEY=your_otx_key
PULSEDIVE_API_KEY=your_pulsedive_key
NEWS_API_KEY=your_newsapi_key| Key | Where to get it |
|---|---|
ABUSEIPDB_API_KEY |
https://www.abuseipdb.com/account/api |
ABUSECH_API_KEY |
https://threatfox.abuse.ch/api/ (Auth-Key) |
ALIENVAULT_API_KEY |
https://otx.alienvault.com/settings (API Key) |
PULSEDIVE_API_KEY |
https://pulsedive.com/account |
NEWS_API_KEY |
https://newsapi.org/register |
The app runs even with missing/invalid keys β affected feeds fall back to generated data.
src/
βββ app/
β βββ layout.tsx # dark-mode root layout + SEO metadata + favicon
β βββ page.tsx # dashboard page (only user route)
β βββ globals.css # cyberpunk design system
β βββ icon.svg # favicon (animated radar + threat dot)
β βββ api/
β βββ threats/
β β βββ attacks/route.ts # live attack stream (15s cache)
β β βββ feed/route.ts # aggregated IOC feed (30s cache)
β βββ ip-check/route.ts # AbuseIPDB IP reputation
β βββ stats/route.ts # KPIs + 24h timeline
β βββ news/route.ts # cybersecurity news
βββ components/
β βββ providers.tsx # QueryClient + I18n providers
β βββ ui/ # shadcn/ui primitives (6 used: badge, button, dialog, input, sonner, toast)
β βββ threat/
β βββ header.tsx # brand, clock, pause, settings, shortcuts, lang toggle
β βββ ticker.tsx # scrolling threat marquee
β βββ kpi-stats.tsx # animated KPI cards + threat gauge
β βββ threat-map.tsx # ECharts map (flow + heatmap, fullscreen, alarm, highlight, country labels)
β βββ top-countries.tsx # ranked sources/targets (clickable focus)
β βββ attack-types-chart.tsx # donut chart
β βββ threat-actors.tsx # malware family panel (clickable filter)
β βββ live-feed.tsx # streaming attack list (click for details)
β βββ attack-timeline.tsx # 24h area chart
β βββ threat-table.tsx # IOC table (search/filter/export)
β βββ ip-lookup.tsx # IP scanner + scan history
β βββ news-feed.tsx # cybersecurity news
β βββ source-status.tsx # intel source health (clickable filter)
β βββ attack-detail-dialog.tsx # attack detail modal + "View on map"
β βββ settings-dialog.tsx # polling interval + feed count preferences
β βββ shortcuts-dialog.tsx # keyboard shortcuts help
β βββ footer.tsx # sticky footer (GitHub link)
βββ hooks/
β βββ use-threat-data.ts # TanStack Query polling hooks
β βββ use-keyboard-shortcuts.ts # global keyboard handler
βββ lib/
βββ types.ts # shared threat-intel types
βββ geo.ts # 57 countries (coords/flags/EN-ES) + weights
βββ threat-utils.ts # color maps, number/time helpers
βββ threat-store.ts # Zustand store (UI state)
βββ settings-store.ts # Zustand store (persisted settings)
βββ validate.ts # zod IP schema
βββ export.ts # CSV/JSON IOC export
βββ api-client.ts # fetchWithTimeout + TTL cache
βββ threat-data.ts # generators & fallbacks
βββ i18n/
βββ dictionaries.ts # EN/ES strings + label maps
βββ provider.tsx # useSyncExternalStore language store
public/
βββ geo/world.json # ECharts world map GeoJSON
The UI is fully bilingual. Translation strings live in src/lib/i18n/dictionaries.ts. The language store uses useSyncExternalStore for SSR-safe localStorage persistence and cross-tab synchronization. Toggle via the EN / ES button in the header.
To add a string:
- Add an entry to the
tdictionary indictionaries.tswith{ en, es }. - Use
const { t } = useI18n();thent("myKey")in any client component.
- The browser fetches
/api/threats/attacksevery 10 seconds (TanStack Query). - The backend generates ~25 fresh
AttackEvents (15s server cache for stability), each with a weighted-random source/target country (biased by real AbuseIPDB blacklist country codes when reachable), an attack type, severity, IPs, port, and coordinates fromsrc/lib/geo.ts. - ECharts renders the world map (GeoJSON registered from
public/geo/world.json) with three series:lineswitheffect.showβ the animated arrow trails tracing origin β target.scatterβ small red dots at attack origins.effectScatterβ pulsing cyan rings at targets, sized by hit count.
- Line color encodes severity (critical = red, high = orange, medium = amber, low = cyan).
- The map is fully interactive β drag to pan, scroll to zoom (1Γβ8Γ), hover/click attacks for tooltips and details.
- Switch via the toggle (top-right) or the M keyboard shortcut.
- Countries are shaded by total attack volume (outgoing + incoming) using a 5-stop color ramp (deep blue β cyan β amber β red).
- Hover any country to see outgoing attacks, incoming attacks, total, and intensity %.
- The chart component remounts completely when switching modes (key-based remount) to avoid ECharts series-type conflicts.
- When a critical-severity attack arrives, the map auto-zooms (5Γ) to the attacker's country for 6 seconds.
- A flashing red banner shows "CRITICAL ATTACK!" with the attack route.
- After 6 seconds, the alarm clears and the map returns to the general view.
- No popup dialog is opened β purely visual.
- Click any live-feed entry or map attack to open the detail dialog.
- Click "View on map" to isolate that single attack on the map for 5 seconds (all other attacks are hidden, no zoom).
- After 5 seconds, all attacks return automatically.
| Key | Action |
|---|---|
Space |
Pause / Resume live updates |
/ |
Focus the IOC search input |
Esc |
Clear map focus country |
M |
Toggle map mode (Flow β Heatmap) |
? |
Toggle the shortcuts help dialog |
- Semantic HTML (
header,main,footer,nav, section headings). - ARIA labels on icon-only buttons.
- Keyboard-focusable interactive elements (shadcn/ui).
- 44px+ touch targets on mobile.
sr-onlyfriendly text where needed.- Loading skeletons / flicker placeholders while data streams in.
- Toast notifications (sonner) for feedback.
- Dialogs use Radix UI portals with proper focus trapping and escape handling.
- Dynamic favicon β animated SVG radar icon (
src/app/icon.svg) with a pulsing red threat dot. - Rich metadata β title template, description, keywords, authors, canonical URL, language alternates.
- OpenGraph tags β type, locale (en_US + es_ES alternate), site name, title, description, images.
- Twitter Card β summary card with title, description, and image.
- Theme color β
#0a0e1a(deep space dark) for browser UI integration. - Color scheme β
darkdeclared in viewport metadata.
No
robots.txt/sitemap.xmlβ this is a single-page app with one route (/), so sitemaps and robots files add no SEO value. Therobotsmetadata inlayout.tsx(index: true, follow: true) is sufficient.
The dashboard has been end-to-end verified with Agent Browser and curl:
- β Renders on desktop (1600Γ1000) and mobile (390Γ844) with zero console/runtime errors.
- β ECharts map canvas renders with animated attack arcs and pulsing targets (flow mode).
- β Heatmap mode renders choropleth with source/target attack breakdown in tooltips.
- β All dialogs (Settings, Shortcuts, Attack Detail) open and render content correctly.
- β Live data flows: 4/4 intel sources, real AbuseIPDB indicators, real news headlines.
- β Language toggle switches all headings between EN and ES.
- β IP scanner returns real AbuseIPDB data + scan history persists.
- β Keyboard shortcuts work (Space, /, Esc, M, ?).
- β No horizontal overflow at any viewport.
- β
bun run lintpasses clean.
MIT β provided for demonstration. Threat data is aggregated from public intelligence feeds under their respective terms of service.
- AbuseIPDB Β· abuse.ch Β· AlienVault OTX Β· Pulsedive Β· NewsAPI
- ECharts Β· Recharts Β· shadcn/ui Β· TanStack Query Β· Zustand Β· Next.js
"The map is not the territory β but it helps you see where the shots are coming from."