MBO-Tech-IT-Webseite/docs/superpowers/plans/2026-06-29-pakete-vpn.md

572 lines
22 KiB
Markdown

# Pakete & Preise — Service-Übersicht + Zero-Trust-VPN
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Die `/pakete`-Seite zur Service-Übersicht mit 2 klickbaren Kacheln umbauen; bestehenden Nextcloud-Inhalt auf `/pakete/nextcloud` verschieben; neue VPN-Seite `/pakete/vpn` anlegen.
**Architecture:** Drei Next.js Server Components. `/pakete` wird zur Übersichtsseite, die zwei Unterseiten per `<Link>` verknüpft. Kein Client-State nötig. Bestehende Design-Token (`bg-[#18212f]`, `text-orange-400`, `.btn-primary`) und Layout-Muster aus der aktuellen Pakete-Seite werden übernommen.
**Tech Stack:** Next.js 15 App Router, TypeScript (strict), Tailwind CSS, `next/link`, `next/navigation`
## Global Constraints
- Kein `"use client"` — alle drei Seiten sind Server Components
- Importpfade via `@/`-Alias (z. B. `@/components/Logo`)
- `ReactElement` statt `JSX.Element` (Next.js 15 / React 19)
- Alle Preise zzgl. MwSt., Link für CTAs immer `/#contact`
- `npm run build` muss fehlerfrei durchlaufen
- Nach jedem Task: `npx tsc --noEmit` grün
---
## Datei-Übersicht
| Datei | Aktion |
|---|---|
| `app/pakete/page.tsx` | Umbau: wird zur Übersichtsseite |
| `app/pakete/nextcloud/page.tsx` | Neu: bestehender Pakete-Inhalt |
| `app/pakete/vpn/page.tsx` | Neu: Zero-Trust-VPN Seite |
---
### Task 1: Nextcloud-Unterseite anlegen
**Files:**
- Create: `app/pakete/nextcloud/page.tsx`
- Modify: `app/pakete/page.tsx` (Zurück-Link anpassen, Inhalt entfernen — in Task 3)
**Interfaces:**
- Produces: Route `/pakete/nextcloud` — vollständige Nextcloud + Paperless Pakete-Seite
- [ ] **Step 1: Datei anlegen — Inhalt aus aktuellem `/pakete/page.tsx` kopieren**
Erstelle `app/pakete/nextcloud/page.tsx` mit exakt dem Inhalt von `app/pakete/page.tsx`, aber mit diesen zwei Änderungen:
1. Metadata anpassen:
```tsx
export const metadata: Metadata = {
title: "Nextcloud + Paperless | Pakete & Preise",
description:
"Nextcloud + Paperless-ngx auf Docker, Kubernetes oder Proxmox: Installation, Hosting und Wartung in Crailsheim. Individuelle Angebote auf Anfrage.",
openGraph: {
title: "Nextcloud + Paperless | MBO-Tech-IT",
description:
"Nextcloud + Paperless-ngx auf Docker, Kubernetes oder Proxmox: Installation, Hosting und Wartung in Crailsheim.",
url: "https://mbo-tech-it.de/pakete/nextcloud",
},
alternates: {
canonical: "https://mbo-tech-it.de/pakete/nextcloud",
},
};
```
2. „← Zurück"-Link zeigt auf `/pakete` statt `/`:
```tsx
<Link
href="/pakete"
className="flex items-center gap-2 text-slate-600 dark:text-slate-400 hover:text-orange-400 transition-colors text-sm font-medium"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
Zurück
</Link>
```
Die Funktion heißt `NextcloudPage` statt `PaketePage`:
```tsx
export default function NextcloudPage() {
```
- [ ] **Step 2: TypeScript prüfen**
```bash
npx tsc --noEmit
```
Erwartet: keine Fehler
- [ ] **Step 3: Im Browser prüfen**
```bash
npm run dev
```
Öffne `http://localhost:3000/pakete/nextcloud` — Seite muss identisch mit dem alten `/pakete` aussehen. Zurück-Button führt zu `/pakete` (404 noch ok, kommt in Task 3).
- [ ] **Step 4: Commit**
```bash
git add app/pakete/nextcloud/page.tsx
git commit -m "feat: move Nextcloud packages to /pakete/nextcloud"
```
---
### Task 2: VPN-Unterseite anlegen
**Files:**
- Create: `app/pakete/vpn/page.tsx`
**Interfaces:**
- Produces: Route `/pakete/vpn` — Zero-Trust-VPN Detailseite mit 3 Preiskarten
- [ ] **Step 1: Datei `app/pakete/vpn/page.tsx` erstellen**
```tsx
import type { Metadata } from "next";
import Link from "next/link";
import Logo from "@/components/Logo";
export const metadata: Metadata = {
title: "Zero-Trust-VPN | MBO-Tech-IT",
description:
"Managed Netbird VPN mit WireGuard für Ihr Unternehmen — sicherer Fernzugriff, DSGVO-konform, Server in Deutschland. Feste Monatspauschale ab 89 €.",
openGraph: {
title: "Zero-Trust-VPN | MBO-Tech-IT",
description:
"Managed Netbird VPN mit WireGuard — sicherer Fernzugriff, DSGVO-konform, Server in Deutschland. Ab 89 €/Monat.",
url: "https://mbo-tech-it.de/pakete/vpn",
},
alternates: {
canonical: "https://mbo-tech-it.de/pakete/vpn",
},
};
const vpnPackages = [
{
name: "Starter",
users: "bis 5 Nutzer",
devices: "15 Geräte",
price: "89",
setup: "490",
highlight: false,
includes: [
"Einrichtung & Client-Rollout",
"Sicherer Fernzugriff (WireGuard)",
"Monitoring & Updates",
"E-Mail-Support",
],
},
{
name: "Business",
users: "bis 20 Nutzer",
devices: "50 Geräte",
price: "149",
setup: "790",
highlight: true,
includes: [
"Alles aus Starter",
"Mehrere Standorte",
"Zugriffs-Protokollierung",
"Telefon-Support",
],
},
{
name: "Professional",
users: "bis 50 Nutzer",
devices: "150 Geräte",
price: "249",
setup: "1.290",
highlight: false,
includes: [
"Alles aus Business",
"SLA 4h Reaktionszeit",
"NIS2-Dokumentation",
"Hochverfügbarkeit",
],
},
];
export default function VpnPage() {
return (
<div className="min-h-screen bg-[#f0f4f8] dark:bg-[#18212f]">
{/* Header */}
<header className="bg-white dark:bg-[#111925] border-b border-slate-200 dark:border-gray-800">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex items-center justify-between">
<Link href="/" className="flex items-center gap-3 group">
<Logo className="h-8 w-auto" />
<div className="flex flex-col leading-tight">
<span className="font-black text-slate-900 dark:text-white text-base tracking-wider uppercase">
MBO-<span className="bg-gradient-to-r from-blue-400 to-blue-600 bg-clip-text text-transparent">TECH-IT</span>
</span>
<span className="text-[9px] font-semibold tracking-[0.2em] text-orange-400/70 uppercase hidden sm:block">
Digital Denken. Lokal Handeln.
</span>
</div>
</Link>
<Link
href="/pakete"
className="flex items-center gap-2 text-slate-600 dark:text-slate-400 hover:text-orange-400 transition-colors text-sm font-medium"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
Zurück
</Link>
</div>
</header>
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
{/* Hero */}
<div className="text-center mb-16">
<span className="text-orange-400 font-mono text-xs font-bold tracking-[0.25em] uppercase">
NEU: Zero-Trust-VPN
</span>
<h1 className="text-4xl sm:text-5xl font-black text-slate-900 dark:text-white mt-3 mb-4">
Ihre Mitarbeiter. Überall.<br className="hidden sm:block" /> Sicher verbunden.
</h1>
<p className="text-slate-600 dark:text-slate-400 text-lg max-w-2xl mx-auto">
Kein offener Port. Kein VPN-Konzentrator. Keine Fritzbox-Bastelei.
Von uns eingerichtet, betrieben und überwacht.
</p>
</div>
{/* Was ist das? */}
<div className="grid md:grid-cols-2 gap-6 mb-16">
<div className="p-6 rounded-2xl bg-white dark:bg-gray-900 border border-slate-200 dark:border-gray-800">
<div className="w-12 h-12 rounded-xl bg-orange-500/10 text-orange-400 flex items-center justify-center mb-4">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
</svg>
</div>
<h3 className="text-slate-800 dark:text-white font-bold text-lg mb-2">Zero Trust</h3>
<p className="text-slate-600 dark:text-slate-400 text-sm leading-relaxed">
Jeder Mitarbeiter sieht nur, was er darf Buchhalter kommt nicht ans Lager,
Monteur nicht in die Buchhaltung. Granulare Rechteverwaltung statt
einmal drin = alles sehen" wie beim klassischen VPN.
</p>
</div>
<div className="p-6 rounded-2xl bg-white dark:bg-gray-900 border border-slate-200 dark:border-gray-800">
<div className="w-12 h-12 rounded-xl bg-blue-500/10 text-blue-400 flex items-center justify-center mb-4">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
</div>
<h3 className="text-slate-800 dark:text-white font-bold text-lg mb-2">WireGuard</h3>
<p className="text-slate-600 dark:text-slate-400 text-sm leading-relaxed">
Modernes VPN-Protokoll der nächsten Generation: schneller und sicherer als
klassisches IPSec oder OpenVPN. Militärgrade-Verschlüsselung,
kein Datenverkehr über fremde Server, DSGVO-konform mit
Server-Standort Deutschland.
</p>
</div>
</div>
{/* Pakete */}
<h2 className="text-3xl font-black text-slate-900 dark:text-white mb-3 text-center">
Unsere Pakete
</h2>
<p className="text-slate-600 dark:text-slate-400 text-center mb-10 max-w-xl mx-auto">
Monatliche Pauschale, keine versteckten Kosten — egal wie viele Mitarbeiter
sich einwählen.
</p>
<div className="grid lg:grid-cols-3 gap-6 mb-16">
{vpnPackages.map((pkg) => (
<div
key={pkg.name}
className={`relative rounded-2xl p-6 border transition-all duration-300 ${
pkg.highlight
? "bg-orange-500/5 border-orange-500/50 shadow-lg shadow-orange-500/10"
: "bg-white dark:bg-gray-900 border-slate-200 dark:border-gray-800"
}`}
>
{pkg.highlight && (
<div className="absolute -top-3 left-1/2 -translate-x-1/2 px-4 py-1 bg-orange-500 rounded-full text-white text-xs font-black tracking-wider">
EMPFOHLEN
</div>
)}
<div className="mb-5">
<span className="text-orange-400 text-xs font-bold tracking-widest uppercase">
{pkg.users} · {pkg.devices}
</span>
<h3 className="text-2xl font-black text-slate-900 dark:text-white mt-1">{pkg.name}</h3>
</div>
{/* Preis */}
<div className="mb-6">
<div className="flex items-end gap-1">
<span className="text-4xl font-black text-orange-400">{pkg.price} €</span>
<span className="text-slate-500 text-sm mb-1">/Monat</span>
</div>
<p className="text-slate-500 text-xs mt-1">
Einrichtung: {pkg.setup} € einmalig
</p>
</div>
{/* Leistungen */}
<ul className="space-y-2 mb-6">
{pkg.includes.map((item) => (
<li key={item} className="flex items-start gap-2 text-sm text-slate-700 dark:text-slate-300">
<span className="w-4 h-4 rounded-full bg-orange-500 flex items-center justify-center flex-shrink-0 mt-0.5">
<svg className="w-2.5 h-2.5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M5 13l4 4L19 7" />
</svg>
</span>
{item}
</li>
))}
</ul>
<Link
href="/#contact"
className={`block w-full py-3 rounded-xl text-center font-bold text-sm transition-colors ${
pkg.highlight
? "bg-orange-500 hover:bg-orange-600 text-white"
: "bg-slate-100 dark:bg-gray-800 hover:bg-slate-200 dark:hover:bg-gray-700 text-slate-800 dark:text-white border border-slate-300 dark:border-gray-700"
}`}
>
Paket anfragen
</Link>
</div>
))}
</div>
{/* Hinweis + CTA */}
<div className="p-6 rounded-2xl border border-blue-500/20 bg-blue-500/5 text-center">
<p className="text-slate-600 dark:text-slate-400 text-sm">
<strong className="text-slate-900 dark:text-white">Hinweis:</strong> Alle Preise zzgl.
gesetzl. MwSt. Individuelle Angebote auf Anfrage. Kostenlose Erstberatung vor Ort —
kein Risiko, kein Kleingedrucktes.
</p>
<Link
href="/#contact"
className="inline-block mt-4 px-6 py-3 bg-orange-500 hover:bg-orange-600 text-white font-bold rounded-xl text-sm transition-colors"
>
Kostenloses Erstgespräch anfragen
</Link>
</div>
</main>
</div>
);
}
```
- [ ] **Step 2: TypeScript prüfen**
```bash
npx tsc --noEmit
```
Erwartet: keine Fehler
- [ ] **Step 3: Im Browser prüfen**
Öffne `http://localhost:3000/pakete/vpn`
Erwartetes Ergebnis:
- Hero mit „Ihre Mitarbeiter. Überall. Sicher verbunden."
- 2 Info-Karten (Zero Trust / WireGuard)
- 3 Preiskarten: Starter 89 €, Business 149 € (EMPFOHLEN-Badge), Professional 249 €
- Hinweis-Box + CTA unten
- Zurück-Link führt zu `/pakete`
- [ ] **Step 4: Commit**
```bash
git add app/pakete/vpn/page.tsx
git commit -m "feat: add Zero-Trust-VPN detail page at /pakete/vpn"
```
---
### Task 3: Übersichtsseite `/pakete` umbauen
**Files:**
- Modify: `app/pakete/page.tsx` — vollständiger Ersatz durch Übersichtsseite
**Interfaces:**
- Consumes: `/pakete/nextcloud` (Task 1), `/pakete/vpn` (Task 2)
- Produces: `/pakete` — Übersichtsseite mit 2 Service-Kacheln
- [ ] **Step 1: `app/pakete/page.tsx` vollständig ersetzen**
```tsx
import type { Metadata } from "next";
import Link from "next/link";
import Logo from "@/components/Logo";
export const metadata: Metadata = {
title: "Pakete & Preise | MBO-Tech-IT",
description:
"Unsere IT-Dienstleistungen auf einen Blick: Nextcloud + Paperless-ngx Cloud-Lösungen und Zero-Trust-VPN für sicheren Fernzugriff. Individuelle Angebote aus Crailsheim.",
openGraph: {
title: "Pakete & Preise | MBO-Tech-IT",
description:
"Nextcloud, Paperless-ngx und Zero-Trust-VPN — IT-Lösungen aus Crailsheim.",
url: "https://mbo-tech-it.de/pakete",
},
alternates: {
canonical: "https://mbo-tech-it.de/pakete",
},
};
const services = [
{
href: "/pakete/nextcloud",
icon: (
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" />
</svg>
),
iconBg: "bg-blue-500/10 text-blue-400",
label: "Nextcloud + Paperless-ngx",
description:
"Eigene Cloud & digitales Dokumentenarchiv auf Ihrem Server — DSGVO-konform, selbst gehostet auf Hetzner Cloud.",
tag: "Einmalige Installation ab Anfrage",
},
{
href: "/pakete/vpn",
icon: (
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
</svg>
),
iconBg: "bg-orange-500/10 text-orange-400",
label: "Zero-Trust-VPN",
description:
"Sicherer Fernzugriff für alle Mitarbeiter. Managed Netbird mit WireGuard — Server in Deutschland, feste Monatspauschale.",
tag: "NEU · ab 89 €/Monat",
isNew: true,
},
];
export default function PaketePage() {
return (
<div className="min-h-screen bg-[#f0f4f8] dark:bg-[#18212f]">
{/* Header */}
<header className="bg-white dark:bg-[#111925] border-b border-slate-200 dark:border-gray-800">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex items-center justify-between">
<Link href="/" className="flex items-center gap-3 group">
<Logo className="h-8 w-auto" />
<div className="flex flex-col leading-tight">
<span className="font-black text-slate-900 dark:text-white text-base tracking-wider uppercase">
MBO-<span className="bg-gradient-to-r from-blue-400 to-blue-600 bg-clip-text text-transparent">TECH-IT</span>
</span>
<span className="text-[9px] font-semibold tracking-[0.2em] text-orange-400/70 uppercase hidden sm:block">
Digital Denken. Lokal Handeln.
</span>
</div>
</Link>
<Link
href="/"
className="flex items-center gap-2 text-slate-600 dark:text-slate-400 hover:text-orange-400 transition-colors text-sm font-medium"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
Zurück
</Link>
</div>
</header>
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
{/* Hero */}
<div className="text-center mb-16">
<span className="text-orange-400 font-mono text-xs font-bold tracking-[0.25em] uppercase">
Unsere Leistungen
</span>
<h1 className="text-4xl sm:text-5xl font-black text-slate-900 dark:text-white mt-3 mb-4">
Pakete & Preise
</h1>
<p className="text-slate-600 dark:text-slate-400 text-lg max-w-2xl mx-auto">
Wählen Sie Ihre Lösung wir installieren, betreiben und warten.
Alles aus einer Hand, aus Crailsheim.
</p>
</div>
{/* Service-Kacheln */}
<div className="grid sm:grid-cols-2 gap-6 max-w-3xl mx-auto mb-16">
{services.map((service) => (
<Link
key={service.href}
href={service.href}
className="group relative p-6 rounded-2xl bg-white dark:bg-gray-900 border border-slate-200 dark:border-gray-800 hover:border-orange-500/50 hover:shadow-lg hover:shadow-orange-500/5 transition-all duration-300 flex flex-col"
>
{service.isNew && (
<span className="absolute top-4 right-4 px-2 py-0.5 bg-orange-500 rounded-full text-white text-[10px] font-black tracking-wider">
NEU
</span>
)}
<div className={`w-12 h-12 rounded-xl flex items-center justify-center mb-4 ${service.iconBg}`}>
{service.icon}
</div>
<h2 className="text-lg font-black text-slate-900 dark:text-white mb-2">
{service.label}
</h2>
<p className="text-slate-600 dark:text-slate-400 text-sm leading-relaxed flex-1">
{service.description}
</p>
<div className="mt-4 flex items-center justify-between">
<span className="text-orange-400 text-xs font-bold">{service.tag}</span>
<svg
className="w-4 h-4 text-slate-400 group-hover:text-orange-400 group-hover:translate-x-1 transition-all"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</div>
</Link>
))}
</div>
{/* CTA */}
<div className="p-6 rounded-2xl border border-blue-500/20 bg-blue-500/5 text-center">
<p className="text-slate-600 dark:text-slate-400 text-sm">
<strong className="text-slate-900 dark:text-white">Nicht sicher, was passt?</strong>{" "}
Kostenlose Erstberatung vor Ort kein Risiko, kein Kleingedrucktes.
</p>
<Link
href="/#contact"
className="inline-block mt-4 px-6 py-3 bg-orange-500 hover:bg-orange-600 text-white font-bold rounded-xl text-sm transition-colors"
>
Kostenloses Erstgespräch anfragen
</Link>
</div>
</main>
</div>
);
}
```
- [ ] **Step 2: TypeScript prüfen**
```bash
npx tsc --noEmit
```
Erwartet: keine Fehler
- [ ] **Step 3: Im Browser prüfen**
Öffne `http://localhost:3000/pakete`
Erwartetes Ergebnis:
- Hero: „Pakete & Preise"
- 2 Kacheln: „Nextcloud + Paperless-ngx" (blau) und „Zero-Trust-VPN" (orange, NEU-Badge)
- Klick auf Nextcloud-Kachel → `/pakete/nextcloud` mit vollem Inhalt
- Klick auf VPN-Kachel → `/pakete/vpn` mit Preiskarten
- Zurück-Links auf den Unterseiten führen zurück zu `/pakete`
- [ ] **Step 4: Produktions-Build prüfen**
```bash
npm run build
```
Erwartet: Build läuft fehlerfrei durch, alle 3 Routen erscheinen in der Route-Übersicht:
- `/pakete`
- `/pakete/nextcloud`
- `/pakete/vpn`
- [ ] **Step 5: Commit + Push**
```bash
git add app/pakete/page.tsx
git commit -m "feat: rebuild /pakete as service overview with tiles"
git push
```