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

22 KiB

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:
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",
  },
};
  1. „← Zurück"-Link zeigt auf /pakete statt /:
<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:

export default function NextcloudPage() {
  • Step 2: TypeScript prüfen
npx tsc --noEmit

Erwartet: keine Fehler

  • Step 3: Im Browser prüfen
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
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

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
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

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

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
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

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

git add app/pakete/page.tsx
git commit -m "feat: rebuild /pakete as service overview with tiles"
git push