Communitygithub.com

LP Hero Video Skill

Ein Skill zur Integration von Produkt-Demo-Videos in Landingpages: Hero-Videos, Hover-Play-Karten, Device-Mockups und Lightbox-Modale – inklusive CSS-Animationen für UI-Mocks ohne Videodateien.

Was ist LP Hero Video Skill?

Dieser Skill ermöglicht es, auf Landingpages und Websites wirkungsvoll Produkt-Demo-Videos einzubinden. Er deckt fünf gängige Muster ab: Hero-Background-Videos, Product-Card-Videos mit Hover-Autoplay, Browser- oder Handy-Mockup-Videos, Lightbox-Modal-Videos (auch YouTube-Embeds) und – als Highlight – CSS-animierte UI-Mocks ohne echte Videodateien, ähnlich den Ansätzen von Stripe, Linear oder Vercel. Der Skill stellt fertige React-Komponenten (HeroVideo, ProductCardVideo, BrowserMockupVideo, VideoLightbox) mit TypeScript-Typen und Ausführungen für gängige LP-Strukturen bereit. Er wurde ursprünglich für die Plural Reality-Website entwickelt und enthält detaillierte Checklisten für Performance (Lazy Loading, Progressive Playback mit faststart, MP4+WebM), Responsivität (Mobile-Fallback-Standbilder) und Accessibility (reduced-motion-Unterstützung). Zudem erklärt er die Erstellung von Demo-Videos mit ffmpeg-Optimierung, empfohlene Hosting-Optionen (lokal, CDN, YouTube/Vimeo) und die Dateistruktur (public/videos/, Komponenten in src/components/). Der Skill ist ideal für Entwickler, die mit Agenten wie Claude Code oder Cursor schnell hochwertige, performante und barrierefreie Video-Lösungen für SaaS- oder Corporate-Seiten umsetzen möchten.

Funktioniert mit~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/yuidvg/skills/tree/HEAD/skills/lp-hero-video

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Was macht LP Hero Video Skill?

Ein Leitfaden zur effektiven Integration von Produkt-Demo-Videos in Landingpages und Websites.

Unterstützte Muster

  1. Hero-Background-Video – Vollflächiges Hintergrundvideo im oberen Seitenbereich
  2. Produkt-Demo-Bereich – Inline-Video im Produktvorstellungsbereich
  3. Floating Device Mockup – Video in einem Geräterahmen darstellen
  4. Lightbox / Modal-Video – Bei Klick vergrößert abspielen

Schritt 0: Vorab-Checkliste

Vor der Videointegration Folgendes prüfen:

Videomaterial prüfen

  • Videodatei vorhanden? (Falls nicht, zuerst Platzhalter-UI erstellen)
  • Format: Ideal .mp4 (H.264) + .webm (VP9) in beiden Formaten
  • Auflösung: Für Hero 1920x1080 empfohlen, für Karten 1280x720 ausreichend
  • Dateigröße: Hero 5-15 MB, Karte 2-5 MB
  • Länge: Autoplay 10-30 Sekunden Loop optimal

Videomaterial erstellen (z. B. mit Screen Studio)

  1. Den eindrucksvollsten Workflow des Produkts in 15-30 Sekunden aufzeichnen
  2. Aufnahme mit mindestens 1920x1080
  3. Beim Export einstellen:
    • MP4 (H.264): Qualität Mittel-Hoch, Bitrate 4-8 Mbps
    • WebM (VP9): Optional mit gleicher Qualität exportieren (falls Tool unterstützt)
  4. Konvertierung mit ffmpeg:
# MP4-Optimierung (Web, mit faststart)
ffmpeg -i input.mov -c:v libx264 -crf 23 -preset slow \
  -movflags +faststart -an -vf scale=1920:-2 output.mp4

# WebM-Konvertierung
ffmpeg -i input.mov -c:v libvpx-vp9 -crf 30 -b:v 0 \
  -an -vf scale=1920:-2 output.webm

# Für Karten (kleiner)
ffmpeg -i input.mov -c:v libx264 -crf 26 -preset slow \
  -movflags +faststart -an -vf scale=1280:-2 output-card.mp4

Hosting

  • Lokal (/public/videos/): Für kleine Websites, Vercel / Netlify Deploy
  • CDN / Object Storage: Für große Mengen, mehrere Videos (Cloudflare R2, AWS S3 + CloudFront)
  • YouTube / Vimeo Embed: Bei SEO-Fokus und externer Teilbarkeit

Muster 1: Hero-Background-Video

Vollflächiges Produkt-Demo-Video oben auf der Seite mit Text-Overlay.

React-Komponente

interface HeroVideoProps {
  /** Pfad zum MP4-Video */
  videoSrc: string;
  /** Pfad zum WebM-Video (optional) */
  videoSrcWebm?: string;
  /** Posterbild, das vor dem Laden des Videos angezeigt wird */
  posterSrc?: string;
  /** Kindelemente für das Overlay (z. B. Überschrift) */
  children?: React.ReactNode;
  /** Deckkraft des Overlays (0-1, Standard 0.4) */
  overlayOpacity?: number;
}

function HeroVideo({
  videoSrc,
  videoSrcWebm,
  posterSrc,
  children,
  overlayOpacity = 0.4,
}: HeroVideoProps) {
  const videoRef = useRef<HTMLVideoElement>(null);

  return (
    <div className="relative h-screen w-full overflow-hidden bg-black">
      {/* Hintergrundvideo */}
      <video
        ref={videoRef}
        autoPlay
        muted
        loop
        playsInline
        poster={posterSrc}
        className="absolute inset-0 w-full h-full object-cover"
      >
        {videoSrcWebm && <source src={videoSrcWebm} type="video/webm" />}
        <source src={videoSrc} type="video/mp4" />
      </video>

      {/* Dunkles Overlay */}
      <div
        className="absolute inset-0"
        style={{ backgroundColor: `rgba(0, 0, 0, ${overlayOpacity})` }}
      />

      {/* Gradient zum Seitenhintergrund */}
      <div className="absolute inset-x-0 bottom-0 h-32 bg-gradient-to-t from-background to-transparent" />

      {/* Inhalt */}
      {children && (
        <div className="absolute inset-0 z-10 flex items-end">
          <div className="container pb-16 md:pb-24">{children}</div>
        </div>
      )}
    </div>
  );
}

Verwendungsbeispiel

<HeroVideo
  videoSrc="/videos/product-demo.mp4"
  videoSrcWebm="/videos/product-demo.webm"
  posterSrc="/images/hero-poster.jpg"
  overlayOpacity={0.35}
>
  <h1 className="text-4xl md:text-6xl font-normal text-white tracking-tight">
    Technologie, die Gespräche neu erfindet.
  </h1>
</HeroVideo>

Anwendungsbereich in der Plural-Reality-Landingpage

Statt oder zusätzlich zur aktuellen LifeGameHero-Komponente:

// Home.tsx – Ersetzungsmuster
// Option A: Vollständiger Ersatz
<HeroVideo videoSrc="/videos/hero-demo.mp4" posterSrc="/images/IMG_5298.jpeg">
  <h1 ...>{h.heroTitle}</h1>
</HeroVideo>

// Option B: LifeGameHero behalten, darunter Video hinzufügen
<LifeGameHero>...</LifeGameHero>
<Section className="py-0">
  <HeroVideo videoSrc="/videos/product-overview.mp4" overlayOpacity={0.2}>
    <h2>Produktvorstellung</h2>
  </HeroVideo>
</Section>

Muster 2: Product Card Video

In jeder Produktkarte wird statt eines Standbilds ein Demo-Video bei Hover abgespielt.

React-Komponente

interface ProductCardVideoProps {
  videoSrc: string;
  posterSrc: string;
  alt: string;
  className?: string;
}

function ProductCardVideo({
  videoSrc,
  posterSrc,
  alt,
  className,
}: ProductCardVideoProps) {
  const videoRef = useRef<HTMLVideoElement>(null);

  const handleMouseEnter = () => {
    videoRef.current?.play();
  };

  const handleMouseLeave = () => {
    const video = videoRef.current;
    if (video) {
      video.pause();
      video.currentTime = 0;
    }
  };

  return (
    <div
      className={cn("relative aspect-video bg-muted overflow-hidden", className)}
      onMouseEnter={handleMouseEnter}
      onMouseLeave={handleMouseLeave}
    >
      <video
        ref={videoRef}
        muted
        loop
        playsInline
        poster={posterSrc}
        preload="metadata"
        className="w-full h-full object-cover"
      >
        <source src={videoSrc} type="video/mp4" />
      </video>
    </div>
  );
}

Verwendungsbeispiel (Bild in vorhandener Karte ersetzen)

// Vorher:
<ParallaxImage src="/images/kouchoai.png" alt={t.products.kouchouAI} />

// Nachher:
<ProductCardVideo
  videoSrc="/videos/kouchou-ai-demo.mp4"
  posterSrc="/images/kouchoai.png"
  alt={t.products.kouchouAI}
/>

Muster 3: Device Mockup Video

Demo-Video in einem Browser- oder Smartphone-Rahmen darstellen (Vertrauensgewinn).

function BrowserMockupVideo({
  videoSrc,
  posterSrc,
  title,
}: {
  videoSrc: string;
  posterSrc?: string;
  title?: string;
}) {
  return (
    <div className="border border-border bg-background overflow-hidden">
      {/* Browser-Chrome */}
      <div className="flex items-center gap-2 px-4 py-3 bg-secondary/30 border-b border-border">
        <div className="flex gap-1.5">
          <div className="w-3 h-3 rounded-full bg-muted-foreground/20" />
          <div className="w-3 h-3 rounded-full bg-muted-foreground/20" />
          <div className="w-3 h-3 rounded-full bg-muted-foreground/20" />
        </div>
        {title && (
          <div className="flex-1 text-center">
            <span className="text-xs text-muted-foreground font-mono">{title}</span>
          </div>
        )}
      </div>
      {/* Video-Inhalt */}
      <div className="aspect-video">
        <video
          autoPlay
          muted
          loop
          playsInline
          poster={posterSrc}
          className="w-full h-full object-cover"
        >
          <source src={videoSrc} type="video/mp4" />
        </video>
      </div>
    </div>
  );
}

Muster 4: Lightbox Modal Video

Video per Klick auf ein Thumbnail in einem Modal anzeigen. Auch für YouTube-Embeds geeignet.

function VideoLightbox({
  thumbnailSrc,
  videoSrc,
  youtubeId,
  alt,
}: {
  thumbnailSrc: string;
  videoSrc?: string;
  youtubeId?: string;
  alt: string;
}) {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <button
        onClick={() => setIsOpen(true)}
        className="relative group cursor-pointer aspect-video w-full overflow-hidden"
      >
        <img src={thumbnailSrc} alt={alt} className="w-full h-full object-cover" />
        {/* Play-Button-Overlay */}
        <div className="absolute inset-0 flex items-center justify-center bg-black/20 group-hover:bg-black/30 transition-colors">
          <div className="w-16 h-16 flex items-center justify-center bg-white/90 group-hover:bg-white transition-colors">
            <svg className="w-6 h-6 text-foreground ml-1" fill="currentColor" viewBox="0 0 24 24">
              <path d="M8 5v14l11-7z" />
            </svg>
          </div>
        </div>
      </button>

      {/* Modal */}
      {isOpen && (
        <div
          className="fixed inset-0 z-50 flex items-center justify-center bg-black/80"
          onClick={() => setIsOpen(false)}
        >
          <div className="w-full max-w-5xl aspect-video" onClick={(e) => e.stopPropagation()}>
            {youtubeId ? (
              <iframe
                src={`https://www.youtube.com/embed/${youtubeId}?autoplay=1`}
                className="w-full h-full"
                allow="autoplay; encrypted-media"
                allowFullScreen
              />
            ) : (
              <video
                src={videoSrc}
                autoPlay
                controls
                className="w-full h-full object-contain bg-black"
              />
            )}
          </div>
        </div>
      )}
    </>
  );
}

Implementierungs-Checkliste

Beim Hinzufügen von Videos folgende Punkte prüfen:

Performance

  • autoPlay, muted, loop, playsInline – alle vier Attribute setzen (iOS-Pflicht)
  • poster-Attribut mit Startbild (verbessert Ladeerfahrung)
  • preload="metadata" für leichteres Erstladen bei Kartenvideos
  • -movflags +faststart auf Videodatei anwenden (progressives Abspielen)
  • MP4 + WebM beide als <source> anbieten (Browser-Kompatibilität)

Responsiv

  • Mit object-cover / object-contain richtig einpassen
  • Alternative: Auf Mobilgeräten statt Video ein Standbild anzeigen
    const isMobile = window.innerWidth < 768;
    // Auf Mobilgeräten nur Posterbild, kein Video laden
    

Barrierefreiheit

  • Autoplay-Videos immer mit muted (Audio ohne Benutzeraktion wird blockiert)
  • prefers-reduced-motion unterstützen – bei deaktivierten Animationen auf Standbild zurückfallen
    @media (prefers-reduced-motion: reduce) {
      video { display: none; }
      .video-poster-fallback { display: block; }
    }
    

Design (Plural Reality-konform)

  • Keine abgerundeten Ecken (border-radius: 0px)
  • Border: 1px solid var(--border)
  • Overlay ist schwarzer Verlauf (monochrom bleiben)
  • Play-Button-Symbol aus Lucide React: Play

Datei-Ablagekonventionen

client/
  public/
    videos/
      hero-demo.mp4           # Hero-Video (MP4)
      hero-demo.webm           # Hero-Video (WebM)
      hero-poster.jpg           # Posterbild für Hero-Video
      kouchou-ai-demo.mp4      # Demo-Video Kouchou AI
      baisoku-survey-demo.mp4  # Demo-Video Baisoku Survey
      baisoku-kaigi-demo.mp4   # Demo-Video Baisoku Kaigi
  src/
    components/
      HeroVideo.tsx             # Komponente für vollflächiges Hero-Video
      ProductCardVideo.tsx      # Komponente für Hover-Play-Video in Karten
      BrowserMockupVideo.tsx    # Video mit Browserrahmen
      VideoLightbox.tsx         # Modal-Video-Komponente

Typische Layout-Beispiele

SaaS / Produkt-LP (empfohlenes Layout)

Hero-Vollflächenvideo (15-30 Sekunden Loop, stumm Autoplay)
  ↓
Textabschnitt (Mission & Werte)
  ↓
Browser-Mockup-Video (Demo des Hauptprodukts)
  ↓
Produktkarten (Hover für individuelle Demo-Videos)
  ↓
Fallstudien / Referenzen
  ↓
CTA

Corporate-Website (zurückhaltendes Layout)

Hero-Bild + Play-Button (Klick öffnet Lightbox-Video)
  ↓
Textabschnitt
  ↓
Produktkarten (Standbild, Video auf Detailseite)

Muster 5: CSS-animierter Produkt-UI-Mock (empfohlen)

Ohne Videodatei die Bedienung des Produkts direkt mit CSS-Animation / SVG / Canvas darstellen. Wird von Stripe, Linear und Vercel verwendet.

Vorteile

  • Keine Videodatei nötig (null zusätzliche Bytes)
  • Vollständig responsiv (bei jeder Bildschirmgröße sauber)
  • Native Darstellung – scharf (keine Kompressionsartefakte)
  • Interaktiv möglich (Hover, Klick verändert Darstellung)
  • Automatische Unterstützung von Dark-/Light-Modus

Vorhandene Animations-Assets

Die Plural-Reality-LP enthält in SolutionAnimations.tsx folgende hochwertige Animationen:

KomponenteInhaltTechnik
NetworkOntologyAnimation3‑stufige Ontologie (DATA→ONTOLOGY→APPLICATION)SVG + framer-motion
DataFlowAnimationPipeline: sammeln → organisieren → verbindenSVG + framer-motion
ClusterAnimationVisualisierung von Meinungs-ClusternSVG + framer-motion
ConversationBranchAnimationVerzweigungsbaum für TiefeninterviewsSVG + framer-motion
FeedbackLoopAnimationKontinuierlicher DialogzyklusSVG + framer-motion
IntegrationMeshAnimationPlattform-IntegrationsdiagrammSVG + framer-motion
ParticleFieldAnimationPartikelnetzwerkCanvas
IsometricLayersAnimationIsometrische SchichtenstrukturSVG + framer-motion

Außerdem gibt es in LifeGameHero.tsx eine Canvas-Animation der Erde → Japan.

Gemeinsame Designprinzipien

- Hintergrund: Schwarz (#000000), weiße Elemente zeichnen
- Monochrom (keine Farben oder nur Brand Teal als Akzent)
- Schriftarten: var(--font-mono) für Tech-Labels, var(--font-sans) für UI-Elemente
- Keine abgerundeten Ecken: rx={0} / border-radius: 0px
- Animation: framer-motion useInView + motion.* für scroll-getriggerte Animationen
- Rasterhintergrund: Hellweißes Linienraster (GridBg-Utility)
- Glühen: feDropShadow für dezentes Leuchten (GlowDef-Utility)

Muster 5A: Browserrahmen + animierte UI

Browser-Chrome (Titelzeile + Punkte) mit animiertem Mock-UI darin.

function ProductDemoMock({
  title,
  children,
  className,
}: {
  title: string;
  children: React.ReactNode;
  className?: string;
}) {
  return (
    <div className={cn("border border-border bg-black overflow-hidden", className)}>
      {/* Browser-Chrome */}
      <div className="flex items-center gap-2 px-4 py-3 bg-[#1c1c1e] border-b border-border">
        <div className="flex gap-1.5">
          <div className="w-2.5 h-2.5 rounded-full bg-white/10" />
          <div className="w-2.5 h-2.5 rounded-full bg-white/10" />
          <div className="w-2.5 h-2.5 rounded-full bg-white/10" />
        </div>
        <div className="flex-1 text-center">
          <span className="text-[10px] text-white/40 font-mono">{title}</span>
        </div>
      </div>
      {/* Animierter Inhalt */}
      <div className="aspect-video relative overflow-hidden">
        {children}
      </div>
    </div>
  );
}

Muster 5B: Kouchou AI Demo-Animation

Textdaten fließen ein → AI clustert → Ergebnis wird angezeigt.

// Konzeptionelles Design (bei Implementierung ClusterAnimation aus SolutionAnimations als Referenz nehmen)
function KouchouAIDemoAnimation() {
  const [phase, setPhase] = useState<"input" | "processing" | "result">("input");

  useEffect(() => {
    const timers = [
      setTimeout(() => setPhase("processing"), 2000),
      setTimeout(() => setPhase("result"), 4000),
    ];
    const loop = setInterval(() => {
      setPhase("input");
      timers.push(setTimeout(() => setPhase("processing"), 2000));
      timers.push(setTimeout(() => setPhase("result"), 4000));
    }, 8000);
    return () => { timers.forEach(clearTimeout); clearInterval(loop); };
  }, []);

  return (
    <ProductDemoMock title="kouchou-ai.plural-reality.com">
      <svg viewBox="0 0 800 450" className="w-full h-full">
        {/* Phase 1: Textzeilen gleiten von links ein */}
        {phase === "input" && (
          <g>
            {["Der Verkehr ist umständlich.", "Ich wünsche mir mehr Kinderbetreuung.", "Die Katastrophenvorsorge macht mir Sorgen."].map((text, i) => (
              <motion.g
                key={text}
                initial={{ opacity: 0, x: -40 }}
                animate={{ opacity: 1, x: 0 }}
                transition={{ delay: i * 0.4 }}
              >
                <rect x={40} y={60 + i * 50} width={350} height={36} fill="white" fillOpacity={0.05} stroke="white" strokeWidth={0.5} />
                <text x={56} y={82 + i * 50} fill="white" fontSize={11} fontFamily="var(--font-sans)" opacity={0.8}>
                  {text}
                </text>
              </motion.g>
            ))}
          </g>
        )}

        {/* Phase 2: Partikel sammeln sich in der Mitte */}
        {phase === "processing" && (
          <motion.text x={400} y={225} textAnchor="middle" fill="white" fontSize={12} fontFamily="var(--font-mono)"
            className="opacity-60">
            Verarbeite...
          </motion.text>
        )}

        {/* Phase 3: Cluster-Ergebnis */}
        {phase === "result" && (
          <g>
            {["Verkehr", "Kinderbetreuung", "Katastrophenschutz"].map((label, i) => (
              <motion.g
                key={label}
                initial={{ scale: 0, opacity: 0 }}
                animate={{ scale: 1, opacity: 1 }}
                transition={{ delay: i * 0.3, type: "spring" }}
              >
                <circle cx={200 + i * 200} cy={225} r={60} fill="none" stroke="white" strokeWidth={0.5} opacity={0.3} />
                <text x={200 + i * 200} y={225} textAnchor="middle" fill="white" fontSize={11} fontFamily="var(--font-mono)">
                  {label}
                </text>
              </motion.g>
            ))}
          </g>
        )}
      </svg>
    </ProductDemoMock>
  );
}

Datei-Ablagekonventionen (Animationen)

client/
  src/
    components/
      animations/
        SolutionAnimations.tsx   # Alle Lösungssimulationen gebündelt
        LifeGameHero.tsx         # Canvas-Erd-Animation (bestehend)

Verwandte Skills