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
+7 -141
View File
@@ -1,3 +1,5 @@
import { useLang } from '../context/LangContext'
function Section({ title, items }: { title: string; items: string[] }) {
return (
<div>
@@ -16,154 +18,18 @@ function Section({ title, items }: { title: string; items: string[] }) {
)
}
const SECTIONS = [
{
title: 'Device Management',
items: [
'CRUD for devices with credential profiles and SSH key management',
'Per-device poll intervals (minutes) or manual-only',
'Status tracking: planned / staged / active / decommissioning / offline / disabled',
'Vendor / model / OS auto-populated from NAPALM get_facts()',
'Site assignment with FK to structured Site records',
'AP Profile assignment for grouped OpenWRT config',
],
},
{
title: 'Discovery',
items: [
'ICMP ping sweep, SNMP scan, HTTP/HTTPS probing',
'Device fingerprinting: vendor + platform confidence scoring',
'FQDN resolution (reverse DNS)',
'Manual adoption from scan results — no auto-create to avoid inventory noise',
],
},
{
title: 'Supported Drivers',
items: [
'openwrt — OpenWRT access points',
'opnsense — OPNsense firewalls',
'proxmox — Proxmox VE hypervisors',
'linux — Generic Linux servers',
'procurve — HP ProCurve / Aruba switches',
'tplink_jetstream — TP-Link Jetstream managed switches',
'netgear — Netgear switches',
'fritzbox — AVM Fritz!Box routers',
'zyxel — Zyxel switches',
'openmediavault — OpenMediaVault NAS',
'sonos — Sonos speakers',
'Plus all built-in NAPALM drivers: Cisco IOS / IOS-XE / NX-OS, Arista EOS, Juniper JunOS',
],
},
{
title: 'Networking & Inventory',
items: [
'Interface browser with IPv4/IPv6 addresses, MAC, speed, MTU',
'LLDP neighbor discovery and topology graph',
'ARP table and DHCP lease browser per device',
'Subnet browser with interface-to-subnet assignments',
'VLAN list grouped by site; per-VLAN device membership view',
'SSID management with push to OpenWRT APs via UCI',
],
},
{
title: 'Configuration Management & Drift',
items: [
'Config drift detection: desired state (DB) vs device state (poll snapshot)',
'One-click drift fix stream with live SSH output in the browser',
'UCI-based config push for OpenWRT (VLAN names, SSID settings, radio config)',
'AP profile system: country code, HT/VHT mode, 802.11r, NTP, syslog, SSH port',
],
},
{
title: 'Scheduled Operations',
items: [
'Scheduled reboots for OpenWRT APs with per-site concurrency lock',
'Failback cron script written to device for netOrk-unreachable scenarios',
'Scheduled config drift fixes with time-window enforcement',
'Package update scheduling and one-click apply',
],
},
{
title: 'Monitoring & Health',
items: [
'SNMP health metrics (CPU, memory, interface counters) via get_health_metrics()',
'Per-device warning system with severity levels (error / warning / info)',
'Docker container and image status (Proxmox/Linux)',
'Service status and start/stop/restart (systemd)',
'VM/container list with OS device cross-linking (Proxmox)',
],
},
{
title: 'Security Integrations',
items: [
'Wazuh — agent enrollment tracking, vulnerability counts by severity, recent alert history, CIS benchmark scores, one-click agent install fix stream',
'Graylog — rsyslog forwarding status per device, one-click fix to write rule',
'CrowdSec — org-level decisions, remediation metrics, top attack scenarios',
],
},
{
title: 'DNS Management',
items: [
'DNS zone management with authoritative device assignment',
'Forward record provisioning (A records from device interfaces)',
'PTR record provisioning to reverse zones',
'Pending job queue for zone changes when device is unreachable',
],
},
{
title: 'Access Control (RBAC)',
items: [
'JWT authentication with remember-me (localStorage) or session-only (sessionStorage)',
'RBAC with four built-in roles: viewer / operator / engineer / administrator',
'Custom roles with any permission combination',
'Full audit log of all orchestration actions',
],
},
{
title: 'NetBox Sync',
items: [
'Pushes vendor, model, OS version, status to NetBox dcim.devices',
'Syncs interfaces, IP addresses, prefixes, VLANs',
'VM interfaces and disks for Proxmox hosts',
],
},
{
title: 'Compliance & Audit (NIS2)',
items: [
'Full audit log of all orchestration actions — who changed what, when (Art. 21 (2h))',
'RBAC with four built-in roles and custom permission sets — access control evidence',
'Per-device patch status and installed package list — patch management baseline (Art. 21 (2e))',
'Wazuh CVE counts by severity (critical / high / medium) linked to each device record',
'Config drift tracking: desired state vs. polled state — detect unauthorized changes',
'Security agent coverage report: which devices have Wazuh, Graylog, CrowdSec active',
'SNMP health metrics as continuous monitoring baseline (Art. 21 (2a))',
'Incident-relevant data per device: Wazuh alerts, CrowdSec decisions, syslog forwarding status (Art. 21 (2b))',
],
},
{
title: 'Developer Experience',
items: [
'OpenAPI / Swagger at /docs',
'Plugin system: new integrations follow a documented pattern',
'Celery task queue with dedicated queues per workload type',
'Docker Compose deployment (single command)',
'Alembic migrations run automatically on deploy',
],
},
]
export default function Features() {
const { t } = useLang()
return (
<div className="py-16 md:py-24">
<div className="max-w-7xl mx-auto px-6">
<div className="mb-16">
<h1 className="text-4xl md:text-5xl font-bold text-slate-100 mb-4">Features</h1>
<p className="text-base text-slate-400 leading-relaxed max-w-xl">
Complete reference for all netOrk capabilities.
</p>
<h1 className="text-4xl md:text-5xl font-bold text-slate-100 mb-4">{t.features.heading}</h1>
<p className="text-base text-slate-400 leading-relaxed max-w-xl">{t.features.sub}</p>
</div>
<div className="grid md:grid-cols-2 gap-12">
{SECTIONS.map((s) => (
{t.features.sections.map((s) => (
<Section key={s.title} title={s.title} items={s.items} />
))}
</div>