# Website-Erweiterung Implementation Plan > **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:** Zwei neue Service-Karten, eine DSGVO/GoBD/Paperless-Sektion und drei Spezialeffekte (Scroll-Reveal, Typewriter, Counter) zur bestehenden MBO-Tech-IT Next.js Website hinzufügen. **Architecture:** Alle Effekte werden mit nativen Web-APIs (Intersection Observer, requestAnimationFrame) ohne externe Packages implementiert. Neue Komponenten folgen dem bestehenden Muster (Tailwind, dark theme, orange/blau Akzente). `"use client"` nur wo Browser-APIs benötigt werden. **Tech Stack:** Next.js 14 (App Router), TypeScript, Tailwind CSS, Intersection Observer API --- ## Dateiübersicht | Aktion | Datei | Zweck | |--------|-------|-------| | Create | `components/ScrollReveal.tsx` | Wiederverwendbarer Wrapper mit Intersection Observer | | Create | `hooks/useTypewriter.ts` | Hook für Typewriter-Effekt | | Create | `components/StatsBar.tsx` | Animierte Statistik-Leiste mit Counter | | Create | `components/PaperlessSection.tsx` | DSGVO & GoBD mit Paperless Sektion | | Modify | `components/Services.tsx` | 2 neue Karten (WLAN, WebApps) + ScrollReveal | | Modify | `components/Hero.tsx` | Typewriter-Effekt integrieren | | Modify | `app/page.tsx` | StatsBar + PaperlessSection einbinden | --- ## Task 1: ScrollReveal-Komponente **Files:** - Create: `components/ScrollReveal.tsx` - [ ] **Step 1: Komponente erstellen** ```tsx // components/ScrollReveal.tsx "use client"; import { useEffect, useRef, useState } from "react"; interface ScrollRevealProps { children: React.ReactNode; delay?: number; className?: string; } export default function ScrollReveal({ children, delay = 0, className = "" }: ScrollRevealProps) { const ref = useRef(null); const [visible, setVisible] = useState(false); useEffect(() => { const el = ref.current; if (!el) return; const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { setVisible(true); observer.disconnect(); } }, { threshold: 0.1 } ); observer.observe(el); return () => observer.disconnect(); }, []); return (
{children}
); } ``` - [ ] **Step 2: Dev-Server starten und Datei prüfen** ```bash npm run dev ``` Öffne http://localhost:3000 — Seite soll unverändert aussehen (Komponente noch nicht eingebunden). - [ ] **Step 3: Commit** ```bash git add components/ScrollReveal.tsx git commit -m "feat: add ScrollReveal component with Intersection Observer" ``` --- ## Task 2: useTypewriter Hook **Files:** - Create: `hooks/useTypewriter.ts` - [ ] **Step 1: `hooks/` Ordner anlegen und Hook erstellen** ```bash mkdir -p hooks ``` ```ts // hooks/useTypewriter.ts "use client"; import { useEffect, useState } from "react"; export function useTypewriter(words: string[], typingSpeed = 80, deletingSpeed = 40, pauseMs = 2000) { const [displayed, setDisplayed] = useState(""); const [wordIndex, setWordIndex] = useState(0); const [isDeleting, setIsDeleting] = useState(false); useEffect(() => { const current = words[wordIndex % words.length]; const timeout = setTimeout(() => { if (!isDeleting) { setDisplayed(current.slice(0, displayed.length + 1)); if (displayed.length + 1 === current.length) { setTimeout(() => setIsDeleting(true), pauseMs); } } else { setDisplayed(current.slice(0, displayed.length - 1)); if (displayed.length - 1 === 0) { setIsDeleting(false); setWordIndex((i) => i + 1); } } }, isDeleting ? deletingSpeed : typingSpeed); return () => clearTimeout(timeout); }, [displayed, isDeleting, wordIndex, words, typingSpeed, deletingSpeed, pauseMs]); return displayed; } ``` - [ ] **Step 2: Commit** ```bash git add hooks/useTypewriter.ts git commit -m "feat: add useTypewriter hook" ``` --- ## Task 3: Hero — Typewriter-Effekt integrieren **Files:** - Modify: `components/Hero.tsx` - [ ] **Step 1: Hero.tsx anpassen** Ersetze die gesamte Datei `components/Hero.tsx` mit folgendem Inhalt: ```tsx // components/Hero.tsx "use client"; import { useTypewriter } from "@/hooks/useTypewriter"; export default function Hero() { const typed = useTypewriter(["Professionell.", "DSGVO-konform.", "Zuverlässig.", "Skalierbar."]); return (
{/* Background grid */}
{/* Radial gradient glow */}
{/* Floating orbs */}
{/* Tagline badge */}
Digital Denken. Lokal Handeln.
{/* Headline */}

Ihre IT-Infrastruktur.{" "} {typed} |
Skalierbar. Zuverlässig.

{/* Subheadline */}

Von Docker-Containern über Kubernetes-Cluster bis hin zu Proxmox-Virtualisierung auf Hetzner Cloud — wir bringen Ihre IT auf das nächste Level.

{/* Tech pills */}
{["Docker", "Kubernetes", "Proxmox", "Hetzner Cloud", "Linux"].map((tech) => ( {tech} ))}
{/* CTAs */} {/* Scroll indicator */}
Scroll
); } ``` - [ ] **Step 2: Im Browser prüfen** Öffne http://localhost:3000 — der Hero-Text soll zwischen "Professionell.", "DSGVO-konform.", "Zuverlässig.", "Skalierbar." wechseln mit Cursor `|`. - [ ] **Step 3: Commit** ```bash git add components/Hero.tsx hooks/useTypewriter.ts git commit -m "feat: add typewriter effect to Hero headline" ``` --- ## Task 4: StatsBar — Animierte Statistiken **Files:** - Create: `components/StatsBar.tsx` - [ ] **Step 1: Komponente erstellen** ```tsx // components/StatsBar.tsx "use client"; import { useEffect, useRef, useState } from "react"; const stats = [ { value: 30, suffix: "+", label: "Jahre IT-Erfahrung", accent: "orange" }, { value: 99, suffix: "%", label: "Server-Uptime", accent: "blue" }, { value: 50, suffix: "+", label: "Abgeschlossene Projekte", accent: "orange" }, { value: 24, suffix: "h", label: "Support-Reaktionszeit", accent: "blue" }, ]; function Counter({ value, suffix, accent }: { value: number; suffix: string; accent: string }) { const [count, setCount] = useState(0); const ref = useRef(null); const started = useRef(false); useEffect(() => { const el = ref.current; if (!el) return; const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting && !started.current) { started.current = true; const duration = 1500; const start = performance.now(); const tick = (now: number) => { const progress = Math.min((now - start) / duration, 1); const eased = 1 - Math.pow(1 - progress, 3); setCount(Math.floor(eased * value)); if (progress < 1) requestAnimationFrame(tick); }; requestAnimationFrame(tick); observer.disconnect(); } }, { threshold: 0.3 } ); observer.observe(el); return () => observer.disconnect(); }, [value]); const color = accent === "orange" ? "text-orange-400" : "text-blue-400"; return ( {count}{suffix} ); } export default function StatsBar() { return (
{stats.map((stat) => (

{stat.label}

))}
); } ``` - [ ] **Step 2: StatsBar in `app/page.tsx` einbinden** Füge den Import und die Komponente in `app/page.tsx` ein. Die Datei soll danach so aussehen: ```tsx // app/page.tsx import Header from "@/components/Header"; import Hero from "@/components/Hero"; import TaglineBanner from "@/components/TaglineBanner"; import StatsBar from "@/components/StatsBar"; import Services from "@/components/Services"; import Technologies from "@/components/Technologies"; import DataSovereignty from "@/components/DataSovereignty"; import PaperlessSection from "@/components/PaperlessSection"; import About from "@/components/About"; import Contact from "@/components/Contact"; import Footer from "@/components/Footer"; export default function Home() { return (
); } ``` **Hinweis:** `PaperlessSection` existiert noch nicht — TypeScript wird einen Fehler werfen. Das ist normal, wir erstellen sie in Task 6. - [ ] **Step 3: Im Browser prüfen** Öffne http://localhost:3000 — nach dem Hero soll die dunkle StatsBar erscheinen. Beim Scrollen dazu zählen die Zahlen hoch. - [ ] **Step 4: Commit** ```bash git add components/StatsBar.tsx app/page.tsx git commit -m "feat: add animated StatsBar with counter effect" ``` --- ## Task 5: Services — 2 neue Karten + ScrollReveal **Files:** - Modify: `components/Services.tsx` - [ ] **Step 1: `services`-Array in `Services.tsx` um 2 Einträge erweitern** Füge am Ende des `services`-Arrays (nach dem Kubernetes-Eintrag, vor der schließenden `]`) folgende zwei Objekte ein: ```ts { icon: ( ), title: "WLAN & Netzwerk", description: "Professionelle WLAN-Planung, Installation und Troubleshooting für Privat- und Gewerbekunden. Mesh-Netzwerke, Access Points und hartnäckige Netzwerkprobleme — auch in schwierigen Gebäuden.", features: ["WLAN-Planung & Installation", "Mesh-Netzwerke", "Netzwerk-Troubleshooting", "Privat- & Gewerbekunden"], accent: "orange", }, { icon: ( ), title: "Individuelle Webanwendungen", description: "Maßgeschneiderte Web-Apps für spezielle Geschäftsanforderungen. Von Kundenportalen über interne Tools bis zu Buchungssystemen — entwickelt auf Ihre Prozesse zugeschnitten.", features: ["Maßgeschneiderte Entwicklung", "Kundenportale & Tools", "API-Integrationen", "Moderner Tech-Stack"], accent: "blue", }, ``` - [ ] **Step 2: ScrollReveal in die Karten-Schleife integrieren** Füge am Anfang der Datei den Import hinzu: ```tsx import ScrollReveal from "@/components/ScrollReveal"; ``` Ändere dann die Karten-Schleife in der `return`-Anweisung von: ```tsx
{services.map((service) => { const c = colorMap[service.accent as keyof typeof colorMap]; return (
``` zu: ```tsx
{services.map((service, index) => { const c = colorMap[service.accent as keyof typeof colorMap]; return (
``` Und die schließende `
` der Karte wird zu `
`. Die vollständige `return`-Schleife sieht dann so aus: ```tsx {services.map((service, index) => { const c = colorMap[service.accent as keyof typeof colorMap]; return (
{service.icon}

{service.title}

{service.description}

    {service.features.map((feature) => (
  • {feature}
  • ))}
); })} ``` - [ ] **Step 3: Im Browser prüfen** http://localhost:3000 → Services-Bereich soll 8 Karten zeigen, die beim Scrollen gestaffelt einfahren. - [ ] **Step 4: Commit** ```bash git add components/Services.tsx git commit -m "feat: add WLAN and WebApps service cards with scroll-reveal" ``` --- ## Task 6: PaperlessSection — DSGVO & GoBD **Files:** - Create: `components/PaperlessSection.tsx` - [ ] **Step 1: Komponente erstellen** ```tsx // components/PaperlessSection.tsx import ScrollReveal from "@/components/ScrollReveal"; const requirements = [ { accent: "orange", title: "DSGVO-konforme Archivierung", text: "Alle Dokumente bleiben auf Ihrer eigenen Infrastruktur — in Deutschland oder bei Hetzner. Kein Zugriff durch Drittanbieter, keine US-Cloud. Vollständig DSGVO-konform.", }, { accent: "blue", title: "GoBD-Anforderungen erfüllt", text: "Revisionssichere, unveränderliche Ablage steuerrelevanter Belege. Paperless-ngx protokolliert alle Änderungen und erfüllt die Anforderungen der GoBD an die digitale Buchführung.", }, { accent: "orange", title: "Selbstgehostet & unter Kontrolle", text: "Betrieb auf Ihrem eigenen Server oder auf einem deutschen Hetzner-VPS. Sie haben die volle Kontrolle über Ihre Daten — heute, morgen und in 10 Jahren.", }, ]; const services = [ "Installation & Konfiguration von Paperless-ngx", "Einrichtung automatischer Dokumentenerkennung (OCR)", "Migration bestehender Dokumentenarchive", "Schulung & Dokumentation für Ihr Team", ]; const colorMap = { orange: { border: "border-orange-500/20 hover:border-orange-500/50", dot: "bg-orange-400", dotBg: "bg-orange-500/10", }, blue: { border: "border-blue-500/20 hover:border-blue-500/50", dot: "bg-blue-400", dotBg: "bg-blue-500/10", }, }; export default function PaperlessSection() { return (
{/* Header */}
Compliance & Dokumentenmanagement

DSGVO & GoBD mit{" "} Paperless-ngx

Digitale Dokumentenverwaltung, die rechtssicher ist — DSGVO-konform, GoBD-tauglich, selbstgehostet. Kein Abo, keine US-Cloud, volle Kontrolle.

{/* What is Paperless */}

Was ist Paperless-ngx?

Paperless-ngx ist ein Open-Source Dokumentenmanagementsystem (DMS), das Ihre Papierflut digitalisiert und durchsuchbar macht. Rechnungen, Verträge, Briefe — automatisch per OCR erkannt, kategorisiert und archiviert. Betrieben auf Ihrer eigenen Infrastruktur, ohne Abhängigkeit von Cloud-Anbietern.

{["Open Source", "Self-Hosted", "OCR", "Volltextsuche", "Automatische Tags"].map((tag) => ( {tag} ))}
{/* Requirements grid */}
{requirements.map((req, index) => { const c = colorMap[req.accent as keyof typeof colorMap]; return (

{req.title}

{req.text}

); })}
{/* Divider */}
Unser Leistungsumfang
{/* Services list */}
{services.map((item) => (
{item}
))}
{/* CTA */}

Compliance leicht gemacht

DSGVO & GoBD — ohne Kompromisse.

Wir richten Paperless-ngx auf Ihrer Infrastruktur ein, migrieren Ihre bestehenden Dokumente und schulen Ihr Team. Rechtssicher, selbstgehostet, dauerhaft unter Ihrer Kontrolle.

Jetzt Beratung anfragen
); } ``` - [ ] **Step 2: Im Browser prüfen** http://localhost:3000 → Zwischen Services und DataSovereignty soll die neue Paperless-Sektion erscheinen mit dunkelgrauem Hintergrund, 3 Anforderungskarten und CTA. - [ ] **Step 3: Commit** ```bash git add components/PaperlessSection.tsx git commit -m "feat: add PaperlessSection with DSGVO/GoBD content" ``` --- ## Task 7: page.tsx — PaperlessSection finalisieren **Files:** - Modify: `app/page.tsx` Nach Task 4 wurde `PaperlessSection` bereits in `page.tsx` importiert. In Task 6 wurde die Komponente erstellt. - [ ] **Step 1: Prüfen dass page.tsx korrekt ist** `app/page.tsx` soll exakt so aussehen (wurde bereits in Task 4 geschrieben): ```tsx import Header from "@/components/Header"; import Hero from "@/components/Hero"; import TaglineBanner from "@/components/TaglineBanner"; import StatsBar from "@/components/StatsBar"; import Services from "@/components/Services"; import Technologies from "@/components/Technologies"; import DataSovereignty from "@/components/DataSovereignty"; import PaperlessSection from "@/components/PaperlessSection"; import About from "@/components/About"; import Contact from "@/components/Contact"; import Footer from "@/components/Footer"; export default function Home() { return (
); } ``` Falls noch nicht so, jetzt anpassen. - [ ] **Step 2: Finaler Check im Browser** http://localhost:3000 — vollständige Seite prüfen: - Hero: Typewriter läuft ✓ - StatsBar: Zahlen zählen hoch beim Scrollen ✓ - Services: 8 Karten, gleiten beim Scrollen ein ✓ - PaperlessSection: erscheint nach Services ✓ - Keine TypeScript/Console-Fehler ✓ - [ ] **Step 3: Finaler Commit** ```bash git add app/page.tsx git commit -m "feat: wire up all new sections in page layout" ``` --- ## Self-Review Ergebnis - **Spec-Abdeckung:** Alle 7 Anforderungen (2 Karten, 1 Sektion, 3 Effekte, page.tsx) haben Tasks ✓ - **Keine Platzhalter:** Alle Code-Blöcke sind vollständig ✓ - **Typ-Konsistenz:** `ScrollReveal` wird in Tasks 5 und 6 identisch verwendet ✓ - **useTypewriter:** Hook gibt `string` zurück, wird in Hero als `{typed}` eingesetzt ✓