diff options
| author | ertopogo <erwin.t.pombett@gmail.com> | 2026-02-19 11:34:16 +0100 |
|---|---|---|
| committer | ertopogo <erwin.t.pombett@gmail.com> | 2026-02-19 11:34:16 +0100 |
| commit | a21bd6a6710d123ef3bfc3c9aab37fc0c276f9c5 (patch) | |
| tree | e2cc828607ea91e5c90ae0ea98c6b7d11324eaf1 /src/app/(public) | |
feat: initial project setup - Next.js 16, Payload CMS v3, palette Mapuche
Next.js 16 App Router + TypeScript + Tailwind CSS v4. Payload CMS v3 with PostgreSQL adapter. Mapuche Corporate palette. Public pages, Docker Compose + Caddy, security middleware.
Co-authored-by: Cursor <cursoragent@cursor.com>
Diffstat (limited to 'src/app/(public)')
| -rw-r--r-- | src/app/(public)/about/page.tsx | 153 | ||||
| -rw-r--r-- | src/app/(public)/articles/page.tsx | 38 | ||||
| -rw-r--r-- | src/app/(public)/demos/page.tsx | 94 | ||||
| -rw-r--r-- | src/app/(public)/layout.tsx | 16 | ||||
| -rw-r--r-- | src/app/(public)/page.tsx | 174 | ||||
| -rw-r--r-- | src/app/(public)/services/page.tsx | 148 |
6 files changed, 623 insertions, 0 deletions
diff --git a/src/app/(public)/about/page.tsx b/src/app/(public)/about/page.tsx new file mode 100644 index 0000000..7e76cbe --- /dev/null +++ b/src/app/(public)/about/page.tsx @@ -0,0 +1,153 @@ +import { Code, Server, Shield, Award } from "lucide-react"; + +const timeline = [ + { + icon: Code, + period: "Début de carrière", + title: "Développeur", + description: + "Développement logiciel, compréhension profonde du code et des architectures applicatives. Base solide pour comprendre les enjeux de sécurité au niveau applicatif.", + }, + { + icon: Server, + period: "Évolution", + title: "Administrateur Systèmes", + description: + "Administration Linux et Windows Server. Gestion d'infrastructures, scripting, automatisation. Vision complète de la chaîne technique.", + }, + { + icon: Shield, + period: "Spécialisation", + title: "Expert IAM & Sécurité", + description: + "Spécialisation en Identity & Access Management. Administration AD et Entra ID, implémentation OIDC/OAuth, stratégies Zero Trust.", + }, +]; + +const skills = { + "Identity & Access Management": [ + "OIDC / OAuth 2.0 / SAML", + "Keycloak", + "Active Directory", + "Microsoft Entra ID (Azure AD)", + "PIM / PAM", + "RBAC / ABAC", + "Conditional Access", + "SSO / Federation", + ], + "Sécurité": [ + "Zero Trust Architecture", + "Durcissement AD (Tiering Model)", + "Sécurité des endpoints", + "PKI & Certificats", + "Audit de sécurité", + "Conformité & Gouvernance", + ], + "Systèmes & Infra": [ + "Windows Server / AD DS", + "Linux (Debian, RHEL, Ubuntu)", + "Docker & Conteneurisation", + "PowerShell / Bash", + "Automatisation & CI/CD", + "Monitoring & Logging", + ], +}; + +export default function AboutPage() { + return ( + <> + <section className="bg-cosmos-900 py-16 sm:py-20"> + <div className="mx-auto max-w-7xl px-6 lg:px-8"> + <div className="mx-auto max-w-2xl text-center"> + <h1 className="text-3xl font-bold tracking-tight text-nieve sm:text-5xl"> + À propos + </h1> + <p className="mt-6 text-lg text-cosmos-300"> + Un parcours du développement à la sécurité, pour une vision + complète et pragmatique de l'IAM. + </p> + </div> + </div> + </section> + + {/* Timeline */} + <section className="py-20"> + <div className="mx-auto max-w-7xl px-6 lg:px-8"> + <h2 className="text-2xl font-bold text-cosmos-900 text-center mb-16"> + Parcours professionnel + </h2> + <div className="relative"> + <div className="absolute left-1/2 -translate-x-px h-full w-0.5 bg-border hidden lg:block" /> + <div className="space-y-12 lg:space-y-16"> + {timeline.map((item, index) => { + const Icon = item.icon; + const isLeft = index % 2 === 0; + return ( + <div + key={item.title} + className={`relative flex flex-col lg:flex-row items-center gap-8 ${ + isLeft ? "lg:flex-row" : "lg:flex-row-reverse" + }`} + > + <div + className={`flex-1 ${isLeft ? "lg:text-right" : "lg:text-left"}`} + > + <p className="text-sm font-semibold text-araucaria-600 uppercase tracking-wider"> + {item.period} + </p> + <h3 className="mt-2 text-xl font-bold text-cosmos-900"> + {item.title} + </h3> + <p className="mt-3 text-muted leading-relaxed"> + {item.description} + </p> + </div> + <div className="relative z-10 w-14 h-14 rounded-full bg-cosmos-900 flex items-center justify-center border-4 border-nieve shadow-lg shrink-0"> + <Icon className="w-6 h-6 text-araucaria-400" /> + </div> + <div className="flex-1 hidden lg:block" /> + </div> + ); + })} + </div> + </div> + </div> + </section> + + {/* Compétences */} + <section className="py-20 bg-pewma border-t border-border"> + <div className="mx-auto max-w-7xl px-6 lg:px-8"> + <h2 className="text-2xl font-bold text-cosmos-900 text-center mb-16"> + Compétences techniques + </h2> + <div className="grid grid-cols-1 md:grid-cols-3 gap-8"> + {Object.entries(skills).map(([category, items]) => ( + <div + key={category} + className="rounded-xl border border-border bg-nieve p-8" + > + <div className="flex items-center gap-3 mb-6"> + <Award className="w-5 h-5 text-kultrun-700" /> + <h3 className="text-lg font-semibold text-cosmos-900"> + {category} + </h3> + </div> + <ul className="space-y-2"> + {items.map((skill) => ( + <li + key={skill} + className="text-sm text-muted flex items-center gap-2" + > + <span className="w-1.5 h-1.5 rounded-full bg-araucaria-500 shrink-0" /> + {skill} + </li> + ))} + </ul> + </div> + ))} + </div> + </div> + </section> + </> + ); +} diff --git a/src/app/(public)/articles/page.tsx b/src/app/(public)/articles/page.tsx new file mode 100644 index 0000000..5dd7a01 --- /dev/null +++ b/src/app/(public)/articles/page.tsx @@ -0,0 +1,38 @@ +import { FileText } from "lucide-react"; + +export default function ArticlesPage() { + return ( + <> + <section className="bg-cosmos-900 py-16 sm:py-20"> + <div className="mx-auto max-w-7xl px-6 lg:px-8"> + <div className="mx-auto max-w-2xl text-center"> + <h1 className="text-3xl font-bold tracking-tight text-nieve sm:text-5xl"> + Articles & Guides + </h1> + <p className="mt-6 text-lg text-cosmos-300"> + Concepts de sécurité, guides d'implémentation OIDC/OAuth, + best practices Zero Trust. + </p> + </div> + </div> + </section> + + <section className="py-20"> + <div className="mx-auto max-w-7xl px-6 lg:px-8"> + <div className="mx-auto max-w-2xl text-center"> + <div className="w-16 h-16 mx-auto rounded-2xl bg-pewma flex items-center justify-center mb-6"> + <FileText className="w-8 h-8 text-cosmos-500" /> + </div> + <h2 className="text-xl font-semibold text-cosmos-900"> + Articles à venir + </h2> + <p className="mt-4 text-muted"> + Les premiers articles techniques sur OIDC, OAuth2 et le Zero Trust + sont en cours de rédaction. Revenez bientôt ! + </p> + </div> + </div> + </section> + </> + ); +} diff --git a/src/app/(public)/demos/page.tsx b/src/app/(public)/demos/page.tsx new file mode 100644 index 0000000..7afee2a --- /dev/null +++ b/src/app/(public)/demos/page.tsx @@ -0,0 +1,94 @@ +import Link from "next/link"; +import { Workflow, Terminal, KeyRound, ShieldCheck } from "lucide-react"; + +const demos = [ + { + icon: Workflow, + title: "Visualiseur OIDC", + description: + "Animation pas-à-pas des flux OIDC : Authorization Code, PKCE, Client Credentials. Comprenez chaque échange entre le client, l'IdP et le resource server.", + href: "/demos/oidc-flow", + status: "Bientôt disponible", + }, + { + icon: Terminal, + title: "Playground OAuth2", + description: + "Testez interactivement les requêtes OAuth2. Explorez les scopes, tokens, refresh tokens. Connecté à un vrai serveur Keycloak.", + href: "/demos/oauth-playground", + status: "Bientôt disponible", + }, + { + icon: KeyRound, + title: "Décodeur JWT", + description: + "Décodez et inspectez vos tokens JWT en temps réel. Visualisez le header, le payload et validez la signature.", + href: "/demos/token-decoder", + status: "Bientôt disponible", + }, + { + icon: ShieldCheck, + title: "Simulateur Zero Trust", + description: + "Visualisation interactive des couches de sécurité Zero Trust. Explorez les différentes stratégies d'implémentation.", + href: "/demos/zero-trust", + status: "Bientôt disponible", + }, +]; + +export default function DemosPage() { + return ( + <> + <section className="bg-cosmos-900 py-16 sm:py-20"> + <div className="mx-auto max-w-7xl px-6 lg:px-8"> + <div className="mx-auto max-w-2xl text-center"> + <h1 className="text-3xl font-bold tracking-tight text-nieve sm:text-5xl"> + Démos interactives + </h1> + <p className="mt-6 text-lg text-cosmos-300"> + Explorez les concepts de sécurité et d'IAM à travers des + outils interactifs. Apprenez en pratiquant. + </p> + </div> + </div> + </section> + + <section className="py-20"> + <div className="mx-auto max-w-7xl px-6 lg:px-8"> + <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> + {demos.map((demo) => { + const Icon = demo.icon; + return ( + <div + key={demo.title} + className="group relative rounded-xl border border-border bg-nieve p-8 hover:border-cosmos-300 hover:shadow-lg transition-all duration-300" + > + <div className="flex items-start justify-between mb-6"> + <div className="w-12 h-12 rounded-lg bg-cosmos-900 flex items-center justify-center"> + <Icon className="w-6 h-6 text-araucaria-400" /> + </div> + <span className="px-3 py-1 text-xs font-medium bg-araucaria-50 text-araucaria-700 rounded-full border border-araucaria-200"> + {demo.status} + </span> + </div> + <h3 className="text-xl font-semibold text-cosmos-900"> + {demo.title} + </h3> + <p className="mt-3 text-sm text-muted leading-relaxed"> + {demo.description} + </p> + <Link + href={demo.href} + className="mt-6 inline-flex items-center text-sm font-semibold text-cosmos-700 hover:text-kultrun-700 transition-colors" + > + Explorer la démo → + </Link> + </div> + ); + })} + </div> + </div> + </section> + </> + ); +} diff --git a/src/app/(public)/layout.tsx b/src/app/(public)/layout.tsx new file mode 100644 index 0000000..5b71246 --- /dev/null +++ b/src/app/(public)/layout.tsx @@ -0,0 +1,16 @@ +import { Header } from "@/components/layout/Header"; +import { Footer } from "@/components/layout/Footer"; + +export default function PublicLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + <> + <Header /> + <main className="min-h-[calc(100vh-4rem)]">{children}</main> + <Footer /> + </> + ); +} diff --git a/src/app/(public)/page.tsx b/src/app/(public)/page.tsx new file mode 100644 index 0000000..36ecee7 --- /dev/null +++ b/src/app/(public)/page.tsx @@ -0,0 +1,174 @@ +import Link from "next/link"; +import { + Shield, + Key, + Lock, + Network, + Server, + ArrowRight, + CheckCircle, +} from "lucide-react"; + +const expertises = [ + { + icon: Key, + title: "OIDC & OAuth2", + description: + "Intégration et sécurisation des flux d'authentification. Authorization Code, PKCE, Client Credentials.", + }, + { + icon: Shield, + title: "Zero Trust", + description: + "Architecture Zero Trust de bout en bout. Never trust, always verify. Micro-segmentation et contrôle d'accès continu.", + }, + { + icon: Lock, + title: "Active Directory & Entra ID", + description: + "Administration, durcissement et migration AD. Configuration Entra ID, Conditional Access, PIM.", + }, + { + icon: Network, + title: "IAM & Gouvernance", + description: + "Stratégie IAM complète. Gestion des identités, provisioning, RBAC/ABAC, audit et conformité.", + }, + { + icon: Server, + title: "Infrastructure & DevSecOps", + description: + "Sécurisation Linux & Windows. Automatisation, durcissement, monitoring sécurité.", + }, +]; + +const highlights = [ + "Expert senior avec expérience en développement, systèmes et sécurité", + "Maîtrise des environnements Open Source et Windows", + "Approche pragmatique orientée résultats", + "Accompagnement de la stratégie à l'implémentation", +]; + +export default function HomePage() { + return ( + <> + {/* Hero */} + <section className="relative overflow-hidden bg-cosmos-900 py-24 sm:py-32"> + <div className="absolute inset-0 opacity-10"> + <div + className="absolute inset-0" + style={{ + backgroundImage: `radial-gradient(circle at 25% 25%, var(--color-araucaria-500) 1px, transparent 1px), + radial-gradient(circle at 75% 75%, var(--color-kultrun-700) 1px, transparent 1px)`, + backgroundSize: "60px 60px", + }} + /> + </div> + <div className="relative mx-auto max-w-7xl px-6 lg:px-8"> + <div className="mx-auto max-w-3xl text-center"> + <p className="text-sm font-semibold text-araucaria-400 uppercase tracking-widest"> + Consulting IAM & Sécurité + </p> + <h1 className="mt-4 text-4xl font-bold tracking-tight text-nieve sm:text-6xl"> + Sécurisez vos identités, + <br /> + <span className="text-araucaria-400">protégez vos accès</span> + </h1> + <p className="mt-6 text-lg leading-8 text-cosmos-300"> + Expert senior en Identity & Access Management. J'accompagne + les organisations dans leur stratégie de sécurité des identités, + de l'audit à l'implémentation. + </p> + <div className="mt-10 flex items-center justify-center gap-4 flex-wrap"> + <Link + href="/services" + className="inline-flex items-center gap-2 rounded-lg bg-kultrun-700 px-6 py-3 text-sm font-semibold text-nieve hover:bg-kultrun-600 transition-colors" + > + Mes services + <ArrowRight className="w-4 h-4" /> + </Link> + <Link + href="/demos" + className="inline-flex items-center gap-2 rounded-lg border border-cosmos-600 px-6 py-3 text-sm font-semibold text-cosmos-200 hover:bg-cosmos-800 hover:text-nieve transition-colors" + > + Voir les démos + </Link> + </div> + </div> + </div> + </section> + + {/* Highlights */} + <section className="py-12 bg-pewma border-b border-border"> + <div className="mx-auto max-w-7xl px-6 lg:px-8"> + <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6"> + {highlights.map((text) => ( + <div key={text} className="flex items-start gap-3"> + <CheckCircle className="w-5 h-5 text-ngunechen-700 mt-0.5 shrink-0" /> + <p className="text-sm text-tierra-700 font-medium">{text}</p> + </div> + ))} + </div> + </div> + </section> + + {/* Expertises */} + <section className="py-20 sm:py-28"> + <div className="mx-auto max-w-7xl px-6 lg:px-8"> + <div className="mx-auto max-w-2xl text-center"> + <h2 className="text-3xl font-bold tracking-tight text-cosmos-900 sm:text-4xl"> + Domaines d'expertise + </h2> + <p className="mt-4 text-lg text-muted"> + Une expertise transversale, du développement à + l'infrastructure, centrée sur la sécurité des identités. + </p> + </div> + + <div className="mx-auto mt-16 grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3"> + {expertises.map((item) => { + const Icon = item.icon; + return ( + <div + key={item.title} + className="group relative rounded-xl border border-border bg-nieve p-8 hover:border-cosmos-300 hover:shadow-lg transition-all duration-300" + > + <div className="w-12 h-12 rounded-lg bg-cosmos-900 flex items-center justify-center group-hover:bg-cosmos-800 transition-colors"> + <Icon className="w-6 h-6 text-araucaria-400" /> + </div> + <h3 className="mt-6 text-lg font-semibold text-cosmos-900"> + {item.title} + </h3> + <p className="mt-2 text-sm text-muted leading-relaxed"> + {item.description} + </p> + </div> + ); + })} + </div> + </div> + </section> + + {/* CTA */} + <section className="bg-cosmos-900 py-16"> + <div className="mx-auto max-w-7xl px-6 lg:px-8"> + <div className="mx-auto max-w-2xl text-center"> + <h2 className="text-2xl font-bold text-nieve sm:text-3xl"> + Un projet de sécurisation ? + </h2> + <p className="mt-4 text-cosmos-300"> + Discutons de vos besoins en IAM et sécurité informatique. + </p> + <Link + href="/contact" + className="mt-8 inline-flex items-center gap-2 rounded-lg bg-araucaria-500 px-8 py-3 text-sm font-semibold text-cosmos-950 hover:bg-araucaria-400 transition-colors" + > + Prendre contact + <ArrowRight className="w-4 h-4" /> + </Link> + </div> + </div> + </section> + </> + ); +} diff --git a/src/app/(public)/services/page.tsx b/src/app/(public)/services/page.tsx new file mode 100644 index 0000000..424e939 --- /dev/null +++ b/src/app/(public)/services/page.tsx @@ -0,0 +1,148 @@ +import { + Search, + Key, + ShieldCheck, + Server, + ArrowRight, +} from "lucide-react"; +import Link from "next/link"; + +const services = [ + { + id: "audit", + icon: Search, + title: "Audit IAM & Sécurité", + description: + "Évaluation complète de votre posture de sécurité des identités. Analyse des configurations AD, Entra ID, politiques d'accès, et recommandations priorisées.", + deliverables: [ + "Rapport d'audit détaillé", + "Matrice de risques priorisée", + "Plan de remédiation", + ], + }, + { + id: "oidc", + icon: Key, + title: "Intégration OIDC / OAuth2", + description: + "Conception et implémentation de flux d'authentification modernes. Intégration d'applications existantes avec OIDC, migration depuis SAML, mise en place de SSO.", + deliverables: [ + "Architecture d'authentification", + "Implémentation et tests", + "Documentation technique", + ], + }, + { + id: "zero-trust", + icon: ShieldCheck, + title: "Stratégie Zero Trust", + description: + "Définition et déploiement d'une architecture Zero Trust adaptée à votre contexte. Conditional Access, micro-segmentation, vérification continue.", + deliverables: [ + "Feuille de route Zero Trust", + "Configuration Conditional Access", + "Formation des équipes", + ], + }, + { + id: "ad-entra", + icon: Server, + title: "AD & Entra ID", + description: + "Administration avancée, durcissement et migration Active Directory. Configuration Entra ID, synchronisation hybride, PIM/PAM.", + deliverables: [ + "Durcissement AD (tiering model)", + "Configuration Entra ID", + "Migration et synchronisation", + ], + }, +]; + +export default function ServicesPage() { + return ( + <> + <section className="bg-cosmos-900 py-16 sm:py-20"> + <div className="mx-auto max-w-7xl px-6 lg:px-8"> + <div className="mx-auto max-w-2xl text-center"> + <h1 className="text-3xl font-bold tracking-tight text-nieve sm:text-5xl"> + Services de consulting + </h1> + <p className="mt-6 text-lg text-cosmos-300"> + Des mandats ciblés pour sécuriser vos identités et vos accès, + de l'audit stratégique à l'implémentation technique. + </p> + </div> + </div> + </section> + + <section className="py-20"> + <div className="mx-auto max-w-7xl px-6 lg:px-8"> + <div className="space-y-16"> + {services.map((service, index) => { + const Icon = service.icon; + const isEven = index % 2 === 0; + return ( + <div + key={service.id} + id={service.id} + className={`flex flex-col lg:flex-row gap-8 lg:gap-16 items-start ${ + isEven ? "" : "lg:flex-row-reverse" + }`} + > + <div className="flex-1"> + <div className="flex items-center gap-4 mb-4"> + <div className="w-12 h-12 rounded-lg bg-cosmos-900 flex items-center justify-center"> + <Icon className="w-6 h-6 text-araucaria-400" /> + </div> + <h2 className="text-2xl font-bold text-cosmos-900"> + {service.title} + </h2> + </div> + <p className="text-muted leading-relaxed"> + {service.description} + </p> + </div> + <div className="flex-1 w-full lg:max-w-sm"> + <div className="rounded-xl border border-border bg-pewma p-6"> + <h3 className="text-sm font-semibold text-cosmos-700 uppercase tracking-wider mb-4"> + Livrables + </h3> + <ul className="space-y-3"> + {service.deliverables.map((item) => ( + <li + key={item} + className="flex items-start gap-3 text-sm text-tierra-700" + > + <ArrowRight className="w-4 h-4 text-kultrun-700 mt-0.5 shrink-0" /> + {item} + </li> + ))} + </ul> + </div> + </div> + </div> + ); + })} + </div> + </div> + </section> + + <section className="bg-pewma py-16 border-t border-border"> + <div className="mx-auto max-w-7xl px-6 lg:px-8 text-center"> + <h2 className="text-2xl font-bold text-cosmos-900"> + Besoin d'un mandat sur mesure ? + </h2> + <p className="mt-4 text-muted"> + Chaque organisation est unique. Discutons de vos besoins spécifiques. + </p> + <Link + href="/contact" + className="mt-8 inline-flex items-center gap-2 rounded-lg bg-kultrun-700 px-8 py-3 text-sm font-semibold text-nieve hover:bg-kultrun-600 transition-colors" + > + Discuter de mon projet + </Link> + </div> + </section> + </> + ); +} |
