MBO-Tech-IT-Webseite/docs/superpowers/plans/2026-04-02-website-erweiter...

26 KiB

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

// 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<HTMLDivElement>(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 (
    <div
      ref={ref}
      className={className}
      style={{
        opacity: visible ? 1 : 0,
        transform: visible ? "translateY(0)" : "translateY(24px)",
        transition: `opacity 500ms ease-out ${delay}ms, transform 500ms ease-out ${delay}ms`,
      }}
    >
      {children}
    </div>
  );
}
  • Step 2: Dev-Server starten und Datei prüfen
npm run dev

Öffne http://localhost:3000 — Seite soll unverändert aussehen (Komponente noch nicht eingebunden).

  • Step 3: Commit
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

mkdir -p hooks
// 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
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:

// components/Hero.tsx
"use client";

import { useTypewriter } from "@/hooks/useTypewriter";

export default function Hero() {
  const typed = useTypewriter(["Professionell.", "DSGVO-konform.", "Zuverlässig.", "Skalierbar."]);

  return (
    <section className="relative min-h-screen flex items-center justify-center overflow-hidden">
      {/* Background grid */}
      <div className="absolute inset-0 bg-grid opacity-50" />

      {/* Radial gradient glow */}
      <div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,rgba(249,115,22,0.10)_0%,transparent_65%)]" />

      {/* Floating orbs */}
      <div className="absolute top-1/4 left-1/4 w-72 h-72 bg-orange-500/5 rounded-full blur-3xl animate-pulse-slow" />
      <div className="absolute bottom-1/4 right-1/4 w-80 h-80 bg-blue-600/5 rounded-full blur-3xl animate-pulse-slow" />

      <div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
        {/* Tagline badge */}
        <div className="inline-flex items-center gap-2 px-5 py-2 rounded-full border border-orange-500/40 bg-orange-500/10 text-orange-400 text-xs font-black tracking-[0.3em] uppercase mb-8">
          <span className="w-1.5 h-1.5 bg-orange-400 rounded-full animate-pulse" />
          Digital Denken. Lokal Handeln.
        </div>

        {/* Headline */}
        <h1 className="text-5xl sm:text-6xl lg:text-7xl font-black text-white leading-tight mb-6 tracking-tight">
          Ihre IT-Infrastruktur.{" "}
          <span className="text-gradient">
            {typed}
            <span className="animate-pulse">|</span>
          </span>
          <br />
          Skalierbar. Zuverlässig.
        </h1>

        {/* Subheadline */}
        <p className="text-xl sm:text-2xl text-slate-400 max-w-3xl mx-auto mb-4 leading-relaxed">
          Von Docker-Containern über Kubernetes-Cluster bis hin zu
          Proxmox-Virtualisierung auf Hetzner Cloud &mdash; wir bringen Ihre
          IT auf das nächste Level.
        </p>

        {/* Tech pills */}
        <div className="flex flex-wrap items-center justify-center gap-3 mb-10">
          {["Docker", "Kubernetes", "Proxmox", "Hetzner Cloud", "Linux"].map((tech) => (
            <span
              key={tech}
              className="px-3 py-1 rounded-md bg-gray-900 border border-gray-700 text-slate-300 text-sm font-mono"
            >
              {tech}
            </span>
          ))}
        </div>

        {/* CTAs */}
        <div className="flex flex-col sm:flex-row items-center justify-center gap-4">
          <a href="#contact" className="btn-primary w-full sm:w-auto px-8 py-4 text-lg">
            Projekt anfragen
          </a>
          <a href="#services" className="btn-secondary w-full sm:w-auto px-8 py-4 text-lg">
            Services ansehen
          </a>
        </div>

        {/* Scroll indicator */}
        <div className="absolute bottom-8 left-1/2 -translate-x-1/2 flex flex-col items-center gap-2 text-slate-600">
          <span className="text-xs font-bold tracking-[0.3em] uppercase">Scroll</span>
          <div className="w-px h-12 bg-gradient-to-b from-slate-600 to-transparent" />
        </div>
      </div>
    </section>
  );
}
  • 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
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

// 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<HTMLSpanElement>(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 (
    <span ref={ref} className={`text-4xl sm:text-5xl font-black ${color}`}>
      {count}{suffix}
    </span>
  );
}

export default function StatsBar() {
  return (
    <section className="py-12 px-4 sm:px-6 lg:px-8 relative">
      <div className="absolute inset-0 bg-[#111925]" />
      <div className="max-w-7xl mx-auto relative">
        <div className="grid grid-cols-2 lg:grid-cols-4 gap-8">
          {stats.map((stat) => (
            <div key={stat.label} className="text-center">
              <Counter value={stat.value} suffix={stat.suffix} accent={stat.accent} />
              <p className="text-slate-500 text-sm mt-1">{stat.label}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}
  • 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:

// 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 (
    <main className="min-h-screen bg-[#18212f]">
      <Header />
      <Hero />
      <TaglineBanner />
      <StatsBar />
      <Services />
      <TaglineBanner />
      <PaperlessSection />
      <DataSovereignty />
      <TaglineBanner />
      <Technologies />
      <About />
      <TaglineBanner />
      <Contact />
      <Footer />
    </main>
  );
}

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

  {
    icon: (
      <svg viewBox="0 0 24 24" className="w-8 h-8" fill="currentColor">
        <path d="M1 6l5 4-5 4V6zm7 0h14v2H8V6zm0 5h14v2H8v-2zm0 5h14v2H8v-2z" />
        <path d="M5.828 7l-1.414 1.414L6.586 10.6 4.414 12.8l1.414 1.4L10 10.6 5.828 7z" opacity=".6"/>
        <path d="M19 3H5a2 2 0 00-2 2v1h2V5h14v14H5v-1H3v1a2 2 0 002 2h14a2 2 0 002-2V5a2 2 0 00-2-2z"/>
        <circle cx="4" cy="12" r="3"/>
        <path d="M4 10.5A1.5 1.5 0 115.5 12 1.5 1.5 0 014 10.5z" fill="#18212f"/>
      </svg>
    ),
    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: (
      <svg viewBox="0 0 24 24" className="w-8 h-8" fill="currentColor">
        <path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/>
      </svg>
    ),
    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:

import ScrollReveal from "@/components/ScrollReveal";

Ändere dann die Karten-Schleife in der return-Anweisung von:

<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  {services.map((service) => {
    const c = colorMap[service.accent as keyof typeof colorMap];
    return (
      <div
        key={service.title}
        className={`group p-6 rounded-2xl bg-gray-900 border ${c.border} transition-all duration-300 hover:-translate-y-1 hover:shadow-xl ${c.shadow}`}
      >

zu:

<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  {services.map((service, index) => {
    const c = colorMap[service.accent as keyof typeof colorMap];
    return (
      <ScrollReveal key={service.title} delay={index * 75}>
        <div
          className={`group p-6 rounded-2xl bg-gray-900 border ${c.border} transition-all duration-300 hover:-translate-y-1 hover:shadow-xl ${c.shadow}`}
        >

Und die schließende </div> der Karte wird zu </div></ScrollReveal>. Die vollständige return-Schleife sieht dann so aus:

{services.map((service, index) => {
  const c = colorMap[service.accent as keyof typeof colorMap];
  return (
    <ScrollReveal key={service.title} delay={index * 75}>
      <div
        className={`group p-6 rounded-2xl bg-gray-900 border ${c.border} transition-all duration-300 hover:-translate-y-1 hover:shadow-xl ${c.shadow}`}
      >
        <div className={`w-14 h-14 rounded-xl ${c.iconBg} ${c.icon} flex items-center justify-center mb-5`}>
          {service.icon}
        </div>
        <h3 className="text-xl font-bold text-white mb-3">{service.title}</h3>
        <p className="text-slate-400 text-sm leading-relaxed mb-5">{service.description}</p>
        <ul className="space-y-2">
          {service.features.map((feature) => (
            <li key={feature} className="flex items-center gap-2 text-sm text-slate-300">
              <span className={`w-1.5 h-1.5 rounded-full ${c.dot} flex-shrink-0`} />
              {feature}
            </li>
          ))}
        </ul>
      </div>
    </ScrollReveal>
  );
})}
  • Step 3: Im Browser prüfen

http://localhost:3000 → Services-Bereich soll 8 Karten zeigen, die beim Scrollen gestaffelt einfahren.

  • Step 4: Commit
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

// 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 (
    <section id="paperless" className="py-24 px-4 sm:px-6 lg:px-8 relative">
      <div className="absolute inset-0 bg-[#111925]" />
      <div className="absolute inset-0 bg-grid opacity-20" />
      <div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top_right,rgba(34,197,94,0.04)_0%,transparent_60%)]" />

      <div className="max-w-7xl mx-auto relative">

        {/* Header */}
        <ScrollReveal>
          <div className="text-center mb-16">
            <span className="text-orange-400 font-mono text-xs font-bold tracking-[0.25em] uppercase">
              Compliance & Dokumentenmanagement
            </span>
            <h2 className="text-4xl sm:text-5xl font-black text-white mt-3 mb-4">
              DSGVO & GoBD mit{" "}
              <span className="text-gradient-orange">Paperless-ngx</span>
            </h2>
            <p className="text-slate-400 text-lg max-w-2xl mx-auto">
              Digitale Dokumentenverwaltung, die rechtssicher ist  DSGVO-konform,
              GoBD-tauglich, selbstgehostet. Kein Abo, keine US-Cloud, volle Kontrolle.
            </p>
          </div>
        </ScrollReveal>

        {/* What is Paperless */}
        <ScrollReveal delay={100}>
          <div className="mb-12 p-6 rounded-2xl bg-gray-900 border border-orange-500/20 flex flex-col md:flex-row gap-6 items-start">
            <div className="flex-shrink-0 w-14 h-14 rounded-xl bg-orange-500/10 text-orange-400 flex items-center justify-center">
              <svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
              </svg>
            </div>
            <div>
              <h3 className="text-white font-bold text-lg mb-2">Was ist Paperless-ngx?</h3>
              <p className="text-slate-400 text-sm leading-relaxed">
                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.
              </p>
              <div className="flex flex-wrap gap-2 mt-3">
                {["Open Source", "Self-Hosted", "OCR", "Volltextsuche", "Automatische Tags"].map((tag) => (
                  <span key={tag} className="px-3 py-1 rounded-full bg-orange-500/10 border border-orange-500/20 text-orange-400 text-xs font-mono">
                    {tag}
                  </span>
                ))}
              </div>
            </div>
          </div>
        </ScrollReveal>

        {/* Requirements grid */}
        <div className="grid md:grid-cols-3 gap-6 mb-16">
          {requirements.map((req, index) => {
            const c = colorMap[req.accent as keyof typeof colorMap];
            return (
              <ScrollReveal key={req.title} delay={index * 100}>
                <div className={`p-6 rounded-2xl bg-gray-900 border ${c.border} transition-all duration-300 h-full`}>
                  <div className={`w-2 h-2 rounded-full ${c.dot} mb-4`} />
                  <h3 className="text-white font-bold text-base mb-3">{req.title}</h3>
                  <p className="text-slate-400 text-sm leading-relaxed">{req.text}</p>
                </div>
              </ScrollReveal>
            );
          })}
        </div>

        {/* Divider */}
        <div className="flex items-center gap-6 mb-12">
          <div className="flex-1 h-px bg-gradient-to-r from-transparent via-gray-700 to-transparent" />
          <div className="px-6 py-2 rounded-full border border-orange-500/40 bg-orange-500/5 text-orange-400 text-sm font-black tracking-wider whitespace-nowrap">
            Unser Leistungsumfang
          </div>
          <div className="flex-1 h-px bg-gradient-to-r from-transparent via-gray-700 to-transparent" />
        </div>

        {/* Services list */}
        <ScrollReveal delay={100}>
          <div className="grid sm:grid-cols-2 gap-4 mb-16">
            {services.map((item) => (
              <div key={item} className="flex items-center gap-3 p-4 rounded-xl bg-gray-900 border border-gray-800">
                <div className="w-5 h-5 rounded-full bg-orange-500 flex items-center justify-center flex-shrink-0">
                  <svg className="w-3 h-3 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M5 13l4 4L19 7" />
                  </svg>
                </div>
                <span className="text-slate-300 text-sm">{item}</span>
              </div>
            ))}
          </div>
        </ScrollReveal>

        {/* CTA */}
        <ScrollReveal delay={150}>
          <div className="p-8 rounded-2xl border border-orange-500/30 bg-orange-500/5 text-center">
            <p className="text-orange-400 font-black text-sm tracking-[0.2em] uppercase mb-2">
              Compliance leicht gemacht
            </p>
            <p className="text-white text-xl font-bold mb-2">
              DSGVO & GoBD  ohne Kompromisse.
            </p>
            <p className="text-slate-400 text-sm max-w-xl mx-auto mb-6">
              Wir richten Paperless-ngx auf Ihrer Infrastruktur ein, migrieren
              Ihre bestehenden Dokumente und schulen Ihr Team. Rechtssicher,
              selbstgehostet, dauerhaft unter Ihrer Kontrolle.
            </p>
            <a href="#contact" className="btn-primary inline-flex px-8 py-3 text-sm">
              Jetzt Beratung anfragen
            </a>
          </div>
        </ScrollReveal>

      </div>
    </section>
  );
}
  • 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
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):

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 (
    <main className="min-h-screen bg-[#18212f]">
      <Header />
      <Hero />
      <TaglineBanner />
      <StatsBar />
      <Services />
      <TaglineBanner />
      <PaperlessSection />
      <DataSovereignty />
      <TaglineBanner />
      <Technologies />
      <About />
      <TaglineBanner />
      <Contact />
      <Footer />
    </main>
  );
}

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

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 ✓