add presentation page

This commit is contained in:
Puechberty Arthur
2026-04-19 14:22:00 +02:00
parent 3063796eb0
commit e0f4e1b8fe
12 changed files with 1338 additions and 3 deletions
+5
View File
@@ -12,6 +12,11 @@
--radius-lg: 20px; --radius-lg: 20px;
} }
@tailwind base;
@tailwind components;
@tailwind utilities;
* { * {
box-sizing: border-box; box-sizing: border-box;
} }
+18 -2
View File
@@ -1,5 +1,21 @@
import { redirect } from "next/navigation"; import Hero from "../components/Hero";
import Features from "../components/Features";
import HowItWorks from "../components/HowItWorks";
import Footer from "../components/Footer";
export default function HomePage() { export default function HomePage() {
redirect("/dashboard"); return (
<main className="min-h-screen bg-gradient-to-b from-gray-900 via-gray-950 to-black text-gray-100 antialiased">
<div className="container mx-auto px-6 py-16 lg:py-24">
<Hero />
<div className="mt-16 space-y-20">
<Features />
<HowItWorks />
</div>
</div>
<Footer />
</main>
);
} }
+26
View File
@@ -0,0 +1,26 @@
import { ReactNode } from "react";
export default function FeatureCard({
title,
description,
icon,
}: {
title: string;
description: string;
icon: ReactNode;
}) {
return (
<div className="p-6 bg-gray-900/40 rounded-xl border border-white/6 hover:shadow-lg transition">
<div className="flex items-start gap-4">
<div className="p-2 bg-white/5 rounded-md text-white flex items-center justify-center">
{icon}
</div>
<div>
<h3 className="text-lg font-semibold text-white">{title}</h3>
<p className="mt-2 text-sm text-gray-300">{description}</p>
</div>
</div>
</div>
);
}
+50
View File
@@ -0,0 +1,50 @@
import FeatureCard from "./FeatureCard";
export default function Features() {
const items = [
{
title: "Multi-bot",
description:
"Gérez plusieurs bots indépendants depuis un tableau de bord unique — configurations et logs centralisés.",
icon: (
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="text-white">
<path d="M4 7h16v10H4z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
<path d="M8 11h0" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
),
},
{
title: "Gestion simple",
description: "Démarrez, arrêtez, et configurez en quelques clics — interface claire et rapide.",
icon: (
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 3v18" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
<path d="M5 8h14" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
),
},
{
title: "Scalable",
description: "Scale automatique des instances pour absorber la charge et garder la disponibilité.",
icon: (
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 12h18" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
<path d="M6 8v8" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
</svg>
),
},
];
return (
<section>
<h2 className="text-2xl font-bold text-white">Fonctionnalités principales</h2>
<p className="mt-2 text-gray-400 max-w-2xl">Toutes les fonctionnalités essentielles pour piloter vos bots en production.</p>
<div className="mt-6 grid grid-cols-1 md:grid-cols-3 gap-6">
{items.map((it, idx) => (
<FeatureCard key={idx} title={it.title} description={it.description} icon={it.icon} />
))}
</div>
</section>
);
}
+12
View File
@@ -0,0 +1,12 @@
export default function Footer() {
return (
<footer className="mt-20 border-t border-white/6 bg-gradient-to-t from-black/0 to-black/30">
<div className="container mx-auto px-6 py-8 flex items-center justify-between">
<div className="text-sm text-gray-400">© {new Date().getFullYear()} Shadow</div>
<div className="text-sm text-gray-400">
<a href="https://github.com/" target="_blank" rel="noreferrer" className="hover:text-white transition">GitHub</a>
</div>
</div>
</footer>
);
}
+68
View File
@@ -0,0 +1,68 @@
import Link from "next/link";
import Logo from "./Logo";
export default function Hero() {
const bots = [
{ name: "Moderation", status: "online" },
{ name: "Welcome", status: "stopped" },
{ name: "Analytics", status: "online" },
];
return (
<section className="relative z-10">
<header className="flex items-center justify-between">
<Logo />
<nav className="flex items-center gap-4">
<Link href="/login" className="text-sm text-gray-400 hover:text-white transition">Se connecter</Link>
</nav>
</header>
<div className="mt-12 lg:flex lg:items-center lg:justify-between">
<div className="lg:w-7/12">
<h1 className="text-4xl sm:text-5xl font-extrabold leading-tight tracking-tight text-white">
Shadow Gérez vos bots Discord simplement
</h1>
<p className="mt-4 text-lg text-gray-300 max-w-2xl">
Centralisez, déployez et contrôlez tous vos bots depuis un tableau de bord moderne. Démarrez,
stoppez et scalez en temps réel, en toute simplicité.
</p>
<div className="mt-8 flex items-center gap-4">
<Link href="/dashboard" className="inline-flex items-center gap-3 px-5 py-3 bg-white text-black rounded-md shadow hover:scale-[1.02] transition transform">
Accéder au dashboard
</Link>
<Link href="/login" className="inline-flex items-center gap-2 px-4 py-3 border border-gray-700 text-gray-200 rounded-md hover:bg-gray-800 transition">
Se connecter
</Link>
</div>
</div>
<div className="mt-10 lg:mt-0 lg:w-5/12">
<div className="bg-gradient-to-br from-gray-800 to-gray-900 p-6 rounded-2xl shadow-xl ring-1 ring-white/5">
<div className="space-y-4">
{bots.map((b, i) => (
<div key={i} className="flex items-center justify-between bg-gray-900/40 p-3 rounded-lg">
<div>
<div className="text-sm font-medium text-white">{b.name}</div>
<div className="text-xs text-gray-400">Instances: 1 · CPU 35%</div>
</div>
<div className="flex items-center gap-3">
<span className={`px-2 py-1 text-xs rounded-full ${b.status === "online" ? "bg-green-500/20 text-green-300" : "bg-gray-700 text-gray-300"}`}>
{b.status === "online" ? "Online" : "Stopped"}
</span>
<button className="px-3 py-1 bg-white/10 text-sm rounded-md hover:bg-white/20 transition">Manage</button>
</div>
</div>
))}
</div>
<div className="mt-4 text-xs text-gray-400">Aperçu en temps réel du statut de vos bots</div>
</div>
</div>
</div>
</section>
);
}
+37
View File
@@ -0,0 +1,37 @@
export default function HowItWorks() {
const steps = [
{
title: "Ajouter un bot",
desc: "Connectez votre application Discord via OAuth et enregistrez-la dans Shadow.",
},
{
title: "Gérer depuis le dashboard",
desc: "Accédez aux commandes, aux logs et aux paramètres depuis une interface centralisée.",
},
{
title: "Contrôler en temps réel",
desc: "Démarrez, arrêtez et scalez vos bots instantanément selon la demande.",
},
];
return (
<section>
<h2 className="text-2xl font-bold text-white">Comment ça marche</h2>
<p className="mt-2 text-gray-400 max-w-2xl">Trois étapes simples pour prendre le contrôle de vos bots.</p>
<div className="mt-6 grid grid-cols-1 md:grid-cols-3 gap-6">
{steps.map((s, i) => (
<div key={i} className="p-6 bg-gray-900/30 rounded-xl border border-white/6">
<div className="flex items-center gap-4">
<div className="flex items-center justify-center w-10 h-10 rounded-full bg-gradient-to-br from-purple-600 to-cyan-500 text-white font-semibold">{i + 1}</div>
<div>
<h3 className="text-lg font-semibold text-white">{s.title}</h3>
<p className="mt-2 text-sm text-gray-300">{s.desc}</p>
</div>
</div>
</div>
))}
</div>
</section>
);
}
+20
View File
@@ -0,0 +1,20 @@
import Link from "next/link";
export default function Logo({ className = "" }: { className?: string }) {
return (
<Link href="/" className={`inline-flex items-center gap-3 ${className}`}>
<svg viewBox="0 0 48 48" className="w-9 h-9" xmlns="http://www.w3.org/2000/svg" aria-hidden>
<defs>
<linearGradient id="shadow-gradient" x1="0" x2="1" y1="0" y2="1">
<stop offset="0%" stopColor="#7c3aed" />
<stop offset="100%" stopColor="#06b6d4" />
</linearGradient>
</defs>
<rect width="48" height="48" rx="10" fill="url(#shadow-gradient)" />
<path d="M14 32c6-6 10-10 20-12" stroke="rgba(255,255,255,0.95)" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />
</svg>
<span className="text-white font-semibold tracking-tight text-lg">Shadow</span>
</Link>
);
}
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
+12
View File
@@ -0,0 +1,12 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
"../../packages/shared/src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
};
+1080
View File
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -25,6 +25,9 @@
"devDependencies": { "devDependencies": {
"@types/node": "^22.10.7", "@types/node": "^22.10.7",
"tsx": "^4.19.3", "tsx": "^4.19.3",
"typescript": "^5.7.3" "typescript": "^5.7.3",
"tailwindcss": "^3.4.7",
"postcss": "^8.4.21",
"autoprefixer": "^10.4.14"
} }
} }