The site felt old, unfocused and bloated: 11 pages, a features page of 171 bullets, a homepage of 830 words in card grids around seven mockup-style screenshots, and no single thing it wanted a visitor to understand. - Message: control instead of drift. Audience: IT departments in small and mid-sized companies. Goal: buy a licence — netOrk itself is free, the licence adds vulnerability data and image updates. - Home is under 400 words: the drift comparison of a real access point, three steps, the hardware it runs on, vulnerabilities with a licence, what else is in the box, one closing band. Features, Drivers and Roadmap are gone; their URLs redirect (router and nginx 301). - New Pricing page: the free core, Starter / Pro / Enterprise on request with the plan differences from the licence server, four questions; buttons go to the licence portal. The unit-less KB request limit is left out. - Persona pages are one template; NIS2 and Plugins are cut to half or less. Impressum and Datenschutz exist as marked placeholders; the unsupported "MIT licence" claim is gone from the footer. - Look: light paper and ink, the dark product on a stage, Inter self-hosted, split sections and ruled lists instead of cards. Four real, cropped screenshots replace eight full-window ones. - Language follows the browser until someone chooses; <html lang> is set. Scroll-to-top on navigation, a catch-all route, no dead /docs/architecture. - CLAUDE.md, DESIGN.md, PAGES.md and PRODUCT.md describe the new rules. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
58 lines
1.8 KiB
TypeScript
58 lines
1.8 KiB
TypeScript
import { useLang } from '../context/LangContext'
|
|
import { usePageTitle } from '../lib/usePageTitle'
|
|
import { linkify } from '../lib/glossary'
|
|
import Shot from '../components/Shot'
|
|
import { ButtonLink, CtaBand, H2, PageHeader, Section, Split, Status } from '../components/ui'
|
|
|
|
export default function Nis2() {
|
|
const { t } = useLang()
|
|
const n = t.nis2
|
|
usePageTitle(t.meta.nis2)
|
|
|
|
return (
|
|
<>
|
|
<PageHeader eyebrow={n.eyebrow} title={n.title} lead={linkify(n.lead)} />
|
|
|
|
<Section className="pt-0 md:pt-0">
|
|
<H2>{n.tableTitle}</H2>
|
|
<dl className="mt-10">
|
|
{n.requirements.map((r) => (
|
|
<div
|
|
key={r.article}
|
|
className="grid gap-x-8 gap-y-2 border-t border-line py-5 md:grid-cols-[6rem_16rem_1fr_8rem]"
|
|
>
|
|
<dt className="font-mono text-sm text-accent">Art. 21 {r.article}</dt>
|
|
<dt className="text-h3 text-ink">{r.label}</dt>
|
|
<dd className="text-ink-soft">{linkify(r.body)}</dd>
|
|
<dd className="md:text-right">
|
|
<Status coverage={r.coverage} label={n.coverage[r.coverage]} />
|
|
</dd>
|
|
</div>
|
|
))}
|
|
</dl>
|
|
</Section>
|
|
|
|
<Section band>
|
|
<Split aside={<H2>{n.evidenceTitle}</H2>}>
|
|
<ul>
|
|
{n.evidence.map((e) => (
|
|
<li key={e} className="border-t border-line py-4 text-ink-soft first:border-t-0 first:pt-0">
|
|
{linkify(e)}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</Split>
|
|
<div className="mt-14">
|
|
<Shot name="audit-log" alt={t.shots.auditLog} caption={n.auditCaption} />
|
|
</div>
|
|
</Section>
|
|
|
|
<CtaBand
|
|
title={t.personas.cta.title}
|
|
body={t.personas.cta.body}
|
|
action={<ButtonLink to="/pricing">{t.personas.cta.button}</ButtonLink>}
|
|
/>
|
|
</>
|
|
)
|
|
}
|