feat: bilingual website (DE/EN) with language switcher
CI / TypeScript — type-check (push) Successful in 8s
CI / Publish — build & push image (push) Successful in 8s
CI / Deploy — pull & restart on host (push) Successful in 2s

Add LangContext with localStorage persistence (default: DE).
DE/EN toggle in Nav (top-right, before CTA button).

All pages translated:
- Home: all 8 sections incl. NIS2 block
- Features: all 13 sections with full German bullet points
- Drivers: headings and descriptions
- Getting Started (coming soon)
- Roadmap: bilingual data arrays inline (Planned + Under consideration)
- NIS2: full Art. 21 mapping, evidence blocks, coming-soon list

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Christian Manivong
2026-06-28 17:00:22 +02:00
co-authored by Claude Sonnet 4.6
parent f194c379e4
commit d48c7143aa
11 changed files with 1011 additions and 618 deletions
+156 -98
View File
@@ -1,98 +1,152 @@
type Item = {
title: string
detail: string
nis2?: boolean
}
import { useLang } from '../context/LangContext'
type Group = {
label: string
items: Item[]
}
type Item = { title: string; detail: string; nis2?: boolean }
type Group = { label: string; items: Item[] }
const GROUPS: Group[] = [
{
label: 'Planned',
items: [
{
title: 'CVE tracking per device',
detail:
'Cross-reference installed packages and OS versions against NVD / OSV. Surfaces "this device has 3 unpatched CVEs (CVSS ≥ 7)" without leaving netOrk.',
nis2: true,
},
{
title: 'Configuration backup & versioning',
detail:
'Git-backed config snapshots on every poll. Detect unauthorized changes between snapshots and provide rollback targets.',
nis2: true,
},
{
title: 'Compliance dashboard',
detail:
'Per-site Art. 21 checklist: asset coverage, patch status, security agent deployment, config drift, syslog forwarding, audit activity — aggregated into a single view.',
nis2: true,
},
{
title: 'Audit log export',
detail:
'PDF and CSV export of the audit log, filtered by date range, device, user, or action type. For NIS2 audit submissions and internal reviews.',
nis2: true,
},
{
title: 'Webhook engine',
detail:
'Outbound HTTP webhooks for events: device discovered, config change detected, job failed, alert threshold exceeded. HMAC-SHA256 payload signing. Integrates with n8n, Slack, PagerDuty.',
},
{
title: 'Live job log streaming',
detail:
'WebSocket endpoint for real-time Celery task output in the UI. Currently streamed via SSE for fix-flows; full job log streaming for all long-running operations.',
},
{
title: 'NetBox sync — manual trigger & status view',
detail:
'POST /api/v1/netbox/sync endpoint with progress feedback and a sync history view in the UI. Currently sync runs automatically; the manual trigger and status are missing.',
},
],
},
{
label: 'Under consideration',
items: [
{
title: 'Incident workflow',
detail:
'Structured incident record tied to devices and security events. Fristen-Tracker for NIS2 Art. 23 reporting windows (24 h early warning, 72 h full notification). Webhook to external ticketing systems.',
nis2: true,
},
{
title: 'EOL tracking for firmware and OS',
detail:
'Flag devices running end-of-life software via the endoflife.date API. Covers OPNsense, OpenWRT, Debian, Ubuntu, and more — matched to the OS versions netOrk already polls.',
nis2: true,
},
{
title: 'MFA (TOTP) for netOrk login',
detail:
'Time-based one-time passwords as a second factor for netOrk user accounts. Directly covers NIS2 Art. 21 (2i) MFA requirement for administrative access.',
nis2: true,
},
{
title: 'mDNS scanner',
detail:
'Discover media devices (Apple TV, Chromecast, Sonos) via mDNS/Bonjour without needing a NAPALM driver. Inventory visibility and firewall segmentation suggestions.',
},
{
title: 'Prometheus metrics + Grafana dashboards',
detail:
'Expose per-device SNMP health metrics as a Prometheus scrape endpoint. Pre-built Grafana dashboard for interface counters, CPU, memory, and poll lag.',
},
{
title: 'Kubernetes Helm chart',
detail:
'Helm chart for production-grade deployments: horizontal scaling for the API and worker pods, Secrets via Vault Agent Injector, Ingress with TLS termination.',
},
],
},
]
const GROUPS: Record<'en' | 'de', Group[]> = {
en: [
{
label: 'Planned',
items: [
{
title: 'CVE tracking per device',
detail: 'Cross-reference installed packages and OS versions against NVD / OSV. Surfaces "this device has 3 unpatched CVEs (CVSS ≥ 7)" without leaving netOrk.',
nis2: true,
},
{
title: 'Configuration backup & versioning',
detail: 'Git-backed config snapshots on every poll. Detect unauthorized changes between snapshots and provide rollback targets.',
nis2: true,
},
{
title: 'Compliance dashboard',
detail: 'Per-site Art. 21 checklist: asset coverage, patch status, security agent deployment, config drift, syslog forwarding, audit activity — aggregated into a single view.',
nis2: true,
},
{
title: 'Audit log export',
detail: 'PDF and CSV export of the audit log, filtered by date range, device, user, or action type. For NIS2 audit submissions and internal reviews.',
nis2: true,
},
{
title: 'Webhook engine',
detail: 'Outbound HTTP webhooks for events: device discovered, config change detected, job failed, alert threshold exceeded. HMAC-SHA256 payload signing. Integrates with n8n, Slack, PagerDuty.',
},
{
title: 'Live job log streaming',
detail: 'WebSocket endpoint for real-time Celery task output in the UI. Currently streamed via SSE for fix-flows; full job log streaming for all long-running operations.',
},
{
title: 'NetBox sync — manual trigger & status view',
detail: 'POST /api/v1/netbox/sync endpoint with progress feedback and a sync history view in the UI. Currently sync runs automatically; the manual trigger and status are missing.',
},
],
},
{
label: 'Under consideration',
items: [
{
title: 'Incident workflow',
detail: 'Structured incident record tied to devices and security events. Deadline tracker for NIS2 Art. 23 reporting windows (24 h early warning, 72 h full notification). Webhook to external ticketing systems.',
nis2: true,
},
{
title: 'EOL tracking for firmware and OS',
detail: 'Flag devices running end-of-life software via the endoflife.date API. Covers OPNsense, OpenWRT, Debian, Ubuntu, and more — matched to the OS versions netOrk already polls.',
nis2: true,
},
{
title: 'MFA (TOTP) for netOrk login',
detail: 'Time-based one-time passwords as a second factor for netOrk user accounts. Directly covers NIS2 Art. 21 (2i) MFA requirement for administrative access.',
nis2: true,
},
{
title: 'mDNS scanner',
detail: 'Discover media devices (Apple TV, Chromecast, Sonos) via mDNS/Bonjour without needing a NAPALM driver. Inventory visibility and firewall segmentation suggestions.',
},
{
title: 'Prometheus metrics + Grafana dashboards',
detail: 'Expose per-device SNMP health metrics as a Prometheus scrape endpoint. Pre-built Grafana dashboard for interface counters, CPU, memory, and poll lag.',
},
{
title: 'Kubernetes Helm chart',
detail: 'Helm chart for production-grade deployments: horizontal scaling for the API and worker pods, Secrets via Vault Agent Injector, Ingress with TLS termination.',
},
],
},
],
de: [
{
label: 'Geplant',
items: [
{
title: 'CVE-Tracking pro Gerät',
detail: 'CVE-Abgleich mit installierten Paketen und OS-Versionen über NVD / OSV. Zeigt „Dieses Gerät hat 3 ungepatchte CVEs (CVSS ≥ 7)" direkt in netOrk an.',
nis2: true,
},
{
title: 'Konfigurationsbackup & -versionierung',
detail: 'Git-basierte Konfigurationssnapshots bei jedem Poll. Erkennt nicht autorisierte Änderungen zwischen Snapshots und bietet Rollback-Ziele.',
nis2: true,
},
{
title: 'Compliance-Dashboard',
detail: 'Art. 21-Checkliste pro Standort: Asset-Abdeckung, Patch-Status, Security-Agent-Deployment, Config-Drift, Syslog-Weiterleitung, Audit-Aktivität — zusammengefasst in einer Ansicht.',
nis2: true,
},
{
title: 'Audit-Log-Export',
detail: 'PDF- und CSV-Export des Audit-Logs, gefiltert nach Datumsbereich, Gerät, Benutzer oder Aktionstyp. Für NIS2-Audit-Einreichungen und interne Reviews.',
nis2: true,
},
{
title: 'Webhook-Engine',
detail: 'Ausgehende HTTP-Webhooks für Events: Gerät entdeckt, Konfigurationsänderung erkannt, Job fehlgeschlagen, Warnschwelle überschritten. HMAC-SHA256-Payload-Signierung. Integrierbar mit n8n, Slack, PagerDuty.',
},
{
title: 'Live-Job-Log-Streaming',
detail: 'WebSocket-Endpunkt für Echtzeit-Celery-Task-Output in der UI. Aktuell wird via SSE für Fix-Flows gestreamt; vollständiges Job-Log-Streaming für alle lang laufenden Operationen geplant.',
},
{
title: 'NetBox-Sync — manueller Trigger & Statusansicht',
detail: 'POST /api/v1/netbox/sync-Endpunkt mit Fortschrittsfeedback und Sync-Verlaufsansicht in der UI. Derzeit läuft der Sync automatisch; manueller Trigger und Status fehlen noch.',
},
],
},
{
label: 'In Erwägung',
items: [
{
title: 'Incident-Workflow',
detail: 'Strukturierter Incident-Datensatz, verknüpft mit Geräten und Sicherheitsereignissen. Fristen-Tracker für NIS2 Art. 23 Meldepflichten (24 h Frühwarnung, 72 h vollständige Meldung). Webhook zu externen Ticketing-Systemen.',
nis2: true,
},
{
title: 'EOL-Tracking für Firmware und OS',
detail: 'Markiert Geräte mit End-of-Life-Software über die endoflife.date-API. Deckt OPNsense, OpenWRT, Debian, Ubuntu und weitere ab — abgeglichen mit den OS-Versionen, die netOrk bereits abfragt.',
nis2: true,
},
{
title: 'MFA (TOTP) für netOrk-Login',
detail: 'Zeitbasierte Einmalpasswörter als zweiter Faktor für netOrk-Benutzerkonten. Deckt direkt NIS2 Art. 21 (2i) MFA-Anforderung für administrativen Zugang ab.',
nis2: true,
},
{
title: 'mDNS-Scanner',
detail: 'Entdeckt Mediengeräte (Apple TV, Chromecast, Sonos) über mDNS/Bonjour ohne NAPALM-Treiber. Inventarsichtbarkeit und Empfehlungen zur Firewall-Segmentierung.',
},
{
title: 'Prometheus-Metriken + Grafana-Dashboards',
detail: 'Veröffentlicht gerätebezogene SNMP-Gesundheitsmetriken als Prometheus-Scrape-Endpunkt. Vorgefertigtes Grafana-Dashboard für Schnittstellenzähler, CPU, Speicher und Poll-Lag.',
},
{
title: 'Kubernetes Helm Chart',
detail: 'Helm Chart für produktionsreife Deployments: horizontale Skalierung für API- und Worker-Pods, Secrets via Vault Agent Injector, Ingress mit TLS-Terminierung.',
},
],
},
],
}
function Nis2Badge() {
return (
@@ -103,19 +157,23 @@ function Nis2Badge() {
}
export default function Roadmap() {
const { lang, t } = useLang()
const groups = GROUPS[lang]
return (
<div className="py-16 md:py-24">
<div className="max-w-4xl mx-auto px-6">
<div className="mb-12">
<h1 className="text-4xl md:text-5xl font-bold text-slate-100 mb-4">Roadmap</h1>
<h1 className="text-4xl md:text-5xl font-bold text-slate-100 mb-4">{t.roadmap.heading}</h1>
<p className="text-base text-slate-400 leading-relaxed max-w-xl">
What's being built and what's being evaluated. Items tagged{' '}
<Nis2Badge /> directly address NIS2 Art. 21 technical baseline requirements.
{t.roadmap.sub.split('NIS2')[0]}
<Nis2Badge />
{t.roadmap.sub.split('NIS2')[1]}
</p>
</div>
<div className="space-y-14">
{GROUPS.map((group) => (
{groups.map((group) => (
<div key={group.label}>
<h2 className="text-xl font-semibold text-slate-200 mb-6 pb-2 border-b border-slate-800">
{group.label}
@@ -123,7 +181,7 @@ export default function Roadmap() {
<div className="space-y-6">
{group.items.map((item) => (
<div key={item.title} className="flex gap-4">
<div className="mt-1 shrink-0 h-1.5 w-1.5 rounded-full bg-sky-500 mt-2" />
<div className="mt-2 shrink-0 h-1.5 w-1.5 rounded-full bg-sky-500" />
<div>
<div className="flex items-center gap-2 mb-1">
<span className="text-sm font-medium text-slate-200">{item.title}</span>