feat: add Product Demo page and integrate into routing (#84)

This commit is contained in:
davida-ps
2026-02-26 16:51:06 +02:00
committed by GitHub
parent 7c0aa37a05
commit 5c5c7f539a
3 changed files with 96 additions and 1 deletions
+2
View File
@@ -7,6 +7,7 @@ import { SkillsCatalog } from './pages/SkillsCatalog';
import { SkillDetail } from './pages/SkillDetail';
import { AdvisoryDetail } from './pages/AdvisoryDetail';
import { WikiBrowser } from './pages/WikiBrowser';
import { ProductDemo } from './pages/ProductDemo';
const App: React.FC = () => {
return (
@@ -18,6 +19,7 @@ const App: React.FC = () => {
<Route path="/skills/:skillId" element={<SkillDetail />} />
<Route path="/feed" element={<FeedSetup />} />
<Route path="/feed/:advisoryId" element={<AdvisoryDetail />} />
<Route path="/demo" element={<ProductDemo />} />
<Route path="/wiki/*" element={<WikiBrowser />} />
</Routes>
</Layout>
+2 -1
View File
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { NavLink } from 'react-router-dom';
import { Menu, X, Terminal, Layers, Rss, Home, Github, BookOpenText } from 'lucide-react';
import { Menu, X, Terminal, Layers, Rss, Home, Github, BookOpenText, PlayCircle } from 'lucide-react';
export const Header: React.FC = () => {
const [isOpen, setIsOpen] = useState(false);
@@ -9,6 +9,7 @@ export const Header: React.FC = () => {
{ label: 'Home', path: '/', icon: Home },
{ label: 'Skills', path: '/skills', icon: Layers },
{ label: 'Security Feed', path: '/feed', icon: Rss },
{ label: 'Product Demo', path: '/demo', icon: PlayCircle },
{ label: 'Wiki', path: '/wiki', icon: BookOpenText },
];
+92
View File
@@ -0,0 +1,92 @@
import React from 'react';
import { ExternalLink, PlayCircle } from 'lucide-react';
import { Footer } from '../components/Footer';
interface DemoVideo {
id: string;
title: string;
description: string;
videoSrc: string;
posterSrc: string;
videoContainerClassName?: string;
}
const demoVideos: DemoVideo[] = [
{
id: 'drift-demo',
title: 'Drift Detection Demo (soul-guardian)',
description:
'Shows integrity monitoring in action: tamper detection, alerting, and restoration-oriented behavior for protected files.',
videoSrc: '/video/soul-guardian-demo.mp4',
posterSrc: '/video/soul-guardian-demo-poster.jpg',
},
{
id: 'install-demo',
title: 'Install Demo (clawsec-suite)',
description:
'Walkthrough of the one-command suite install flow and what gets configured for advisory monitoring and protection.',
videoSrc: '/video/install-demo.mp4',
posterSrc: '/video/install-demo-poster.jpg',
videoContainerClassName: 'md:max-w-[50%]',
},
];
export const ProductDemo: React.FC = () => {
return (
<div className="max-w-5xl mx-auto pt-[52px] space-y-10">
<section className="text-center space-y-4">
<h1 className="text-3xl md:text-4xl text-white flex items-center justify-center gap-3">
<PlayCircle className="text-clawd-accent" />
Watch It in Action
</h1>
<p className="text-gray-400 max-w-3xl mx-auto">
Product demos for ClawSec installation and runtime protection behavior. These are the
same demo assets referenced in the repository README, presented as playable videos.
</p>
</section>
<section className="space-y-8">
{demoVideos.map((demo) => (
<article
key={demo.id}
className="bg-clawd-900 border border-clawd-700 rounded-xl overflow-hidden"
>
<div className="px-6 pt-6 pb-4 space-y-3">
<h2 className="text-xl text-white">{demo.title}</h2>
<p className="text-gray-400">{demo.description}</p>
</div>
<div className="px-6 pb-6 space-y-4">
<div
className={`rounded-lg overflow-hidden border border-clawd-700 bg-black ${
demo.videoContainerClassName ?? ''
}`}
>
<video
className="w-full h-auto"
controls
playsInline
preload="metadata"
poster={demo.posterSrc}
>
<source src={demo.videoSrc} type="video/mp4" />
Your browser does not support the video tag.
</video>
</div>
<a
href={demo.videoSrc}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 text-sm text-clawd-accent hover:underline"
>
<ExternalLink size={15} />
Open video in new tab
</a>
</div>
</article>
))}
</section>
<Footer />
</div>
);
};