-
- Rejoignez l'Aventure
-
+
+ Rejoignez l’Aventure
+
Faites partie de la révolution cloud gaming. Plus de 1500 joueurs nous font déjà confiance.
diff --git a/app/[locale]/services/page.tsx b/app/[locale]/services/page.tsx
index 7521e98..f3d34f1 100644
--- a/app/[locale]/services/page.tsx
+++ b/app/[locale]/services/page.tsx
@@ -1,7 +1,13 @@
'use client'
-import { useMemo } from 'react'
-import { useI18n } from '@/lib/i18n-simple'
+import { useMemo, useState } from 'react'
+import {
+ AnimatePresence,
+ LazyMotion,
+ domAnimation,
+ m,
+ useReducedMotion,
+} from 'framer-motion'
import dynamic from 'next/dynamic'
import Link from 'next/link'
import { useParams } from 'next/navigation'
@@ -10,24 +16,19 @@ import {
Cpu,
HeadphonesIcon,
Cloud,
- ArrowRight,
- TrendingUp,
- Award,
Rocket,
Target,
Users,
+ Sparkles,
+ Compass,
+ Layers,
} from 'lucide-react'
import type { LucideIcon } from 'lucide-react'
import SiteHeader from '@/components/SiteHeader'
-import FlipCard3D from '@/components/services/FlipCard3D'
-import AnimatedCounter from '@/components/services/AnimatedCounter'
-import InteractiveTimeline from '@/components/services/InteractiveTimeline'
-import ParticleBackground from '@/components/services/ParticleBackground'
-import GlowingCard from '@/components/services/GlowingCard'
-import MorphingShape from '@/components/services/MorphingShape'
+import { useI18n } from '@/lib/i18n-simple'
const Footer = dynamic(() => import('@/components/Footer'), {
- loading: () =>
,
+ loading: () =>
,
ssr: false,
})
@@ -57,28 +58,6 @@ type ServicesStep = {
description: string
}
-type PillarCard = {
- id: string
- icon: LucideIcon
- gradient: string
- iconColor: string
- title: string
- description: string
- bullets: string[]
- stats: { label: string; value: string }[]
- highlights: string[]
-}
-
-type SolutionCard = {
- id: string
- icon: LucideIcon
- gradient: string
- title: string
- description: string
- link: string
- linkLabel: string
-}
-
type ServicesContent = {
badge?: string
title?: string
@@ -109,30 +88,209 @@ type ServicesContent = {
}
}
+type PillarBlueprint = {
+ id: string
+ icon: LucideIcon
+ label: string
+ accent: string
+ stats: { label: string; value: string }[]
+ defaultDescription: string
+ defaultBullets: string[]
+}
+
+type SolutionBlueprint = {
+ id: string
+ icon: LucideIcon
+ accent: string
+ defaultTitle: string
+ defaultDescription: string
+ defaultLinkLabel: string
+ linkBuilder: (locale: string) => string
+}
+
+const HERO_METRIC_FALLBACK: ServicesMetric[] = [
+ { id: 'uptime', value: '99,9 %', label: 'Disponibilité garantie' },
+ { id: 'clients', value: '120+', label: 'Clients pro accompagnés' },
+ { id: 'regions', value: '8', label: 'Régions cloud actives' },
+ { id: 'sla', value: '<5 min', label: 'SLA support moyen' },
+]
+
+const PILLAR_BLUEPRINTS: PillarBlueprint[] = [
+ {
+ id: 'security',
+ icon: Shield,
+ label: 'Sécurité proactive',
+ accent: 'from-purple-500/90 to-purple-700/60',
+ stats: [
+ { label: 'Kernel shield', value: 'Propriétaire' },
+ { label: 'Audits', value: 'Quotidiens' },
+ { label: 'Détection', value: '0%' },
+ ],
+ defaultDescription:
+ 'Protection multi-couches, supervision anti-détection et chiffrement bout en bout.',
+ defaultBullets: [
+ 'Surveillance continue et audits dynamiques',
+ 'Gestion proactive des incidents',
+ 'Playbooks de mitigation personnalisés',
+ ],
+ },
+ {
+ id: 'performance',
+ icon: Cpu,
+ label: 'Performance calibrée',
+ accent: 'from-sky-500/90 to-indigo-700/60',
+ stats: [
+ { label: 'GPU', value: 'RTX 4090' },
+ { label: 'Latency', value: '<1 ms' },
+ { label: 'Scaling', value: 'Instantané' },
+ ],
+ defaultDescription:
+ 'Clusters bare-metal optimisés, pipeline CI/CD gaming et monitoring temps réel.',
+ defaultBullets: [
+ 'Optimisation GPU frame-by-frame',
+ 'Auto-scaling multi-régions',
+ 'Benchmarks et rapports mensuels',
+ ],
+ },
+ {
+ id: 'partnership',
+ icon: HeadphonesIcon,
+ label: 'Support dédié',
+ accent: 'from-emerald-500/90 to-teal-700/60',
+ stats: [
+ { label: 'Réponse', value: '<5 min' },
+ { label: 'Disponibilité', value: '24/7' },
+ { label: 'Satisfaction', value: '98%' },
+ ],
+ defaultDescription:
+ 'Account manager senior, escalade prioritaire et canaux privés Discord/WhatsApp.',
+ defaultBullets: [
+ 'Veille & recommandations proactives',
+ 'Workshops adaptés à votre roster',
+ 'Documentation personnalisée',
+ ],
+ },
+ {
+ id: 'infrastructure',
+ icon: Cloud,
+ label: 'Cloud orchestration',
+ accent: 'from-cyan-500/90 to-slate-700/60',
+ stats: [
+ { label: 'Régions', value: '12+' },
+ { label: 'Uptime', value: '99.99%' },
+ { label: 'Déploiement', value: '<2 min' },
+ ],
+ defaultDescription:
+ 'Provisionnement instantané, bascule automatique de région et sauvegardes en continu.',
+ defaultBullets: [
+ 'Réseau 10 Gbps sécurisé',
+ 'Disaster recovery automatisé',
+ 'Intégration API PulseForge',
+ ],
+ },
+]
+
+const SOLUTION_BLUEPRINTS: SolutionBlueprint[] = [
+ {
+ id: 'cloud',
+ icon: Rocket,
+ accent: 'from-blue-500/90 to-purple-500/60',
+ defaultTitle: 'Cloud Ops & Scaling',
+ defaultDescription:
+ 'Provisionnement automatisé, régions multiples et pipelines CI/CD prêts pour PulseForge.',
+ defaultLinkLabel: 'Découvrir Premium',
+ linkBuilder: (locale) => `/${locale}/premium`,
+ },
+ {
+ id: 'competitive',
+ icon: Target,
+ accent: 'from-rose-500/90 to-orange-500/60',
+ defaultTitle: 'Labs Anti-Cheat',
+ defaultDescription:
+ 'Reverse engineering continu, correctifs jour zéro et protocoles d’audit conformes.',
+ defaultLinkLabel: 'Voir les jeux',
+ linkBuilder: (locale) => `/${locale}/games`,
+ },
+ {
+ id: 'custom',
+ icon: Users,
+ accent: 'from-emerald-500/90 to-cyan-500/60',
+ defaultTitle: 'Coaching & Integrations',
+ defaultDescription:
+ 'Sessions 1:1, assistance en direct et intégrations personnalisées dans vos outils.',
+ defaultLinkLabel: 'Planifier un call',
+ linkBuilder: (locale) => `/${locale}/contact`,
+ },
+]
+
+const PROCESS_FALLBACK: ServicesStep[] = [
+ {
+ id: 'discover',
+ title: 'Kick-off & audit',
+ description:
+ 'Analyse de votre roster, objectifs de performance et contraintes de sécurité.',
+ },
+ {
+ id: 'prototype',
+ title: 'Prototype guidé',
+ description:
+ 'Instance pilote PulseForge avec profils calibrés et supervision conjointe.',
+ },
+ {
+ id: 'deploy',
+ title: 'Déploiement orchestré',
+ description:
+ 'Activation progressive, documentation et transfert de compétences.',
+ },
+ {
+ id: 'optimize',
+ title: 'Optimisation continue',
+ description:
+ 'Revues, benchmarks et évolution proactive selon vos retours terrain.',
+ },
+]
+
+const CONTACT_METRIC_FALLBACK: ServicesMetric[] = [
+ { id: 'sla', value: '<5 min', label: 'Temps de réponse moyen' },
+ { id: 'coverage', value: '24/7', label: 'Support global' },
+ { id: 'satisfaction', value: '98 %', label: 'Satisfaction client' },
+]
+
+const heroReveal = {
+ hidden: { opacity: 0, y: 32 },
+ show: { opacity: 1, y: 0 },
+}
+
+const sectionReveal = {
+ hidden: { opacity: 0, y: 40 },
+ show: { opacity: 1, y: 0 },
+}
+
+const cardReveal = {
+ hidden: { opacity: 0, y: 24 },
+ show: { opacity: 1, y: 0 },
+}
+
export default function ServicesPage() {
const { t } = useI18n()
const params = useParams()
const locale = (params?.locale as string) || 'fr'
const servicesContent = (t.services ?? {}) as ServicesContent
+ const shouldReduceMotion = useReducedMotion()
- const badge = servicesContent.badge ?? 'Services Premium'
- const title = servicesContent.title ?? 'Infrastructure & Sécurité'
+ const badge = servicesContent.badge ?? 'Services PulseForge'
+ const title =
+ servicesContent.title ??
+ 'Infrastructure et sécurité professionnelles pour vos opérations gaming'
const subtitle =
servicesContent.subtitle ??
- 'Des services sur-mesure pour les joueurs et équipes qui exigent la perfection technique et la performance maximale.'
+ 'Nous combinons cloud, sécurité et coaching technique pour déployer des expériences PulseForge irréprochables.'
const primaryCta = servicesContent.cta ?? 'Parler à un expert'
- const heroMetricFallback: ServicesMetric[] = [
- { id: 'uptime', value: '99.9%', label: 'Uptime garanti' },
- { id: 'clients', value: '500+', label: 'Clients satisfaits' },
- { id: 'regions', value: '12', label: 'Régions globales' },
- { id: 'support', value: '24/7', label: 'Support dédié' },
- ]
- const heroMetricsSource = Array.isArray(servicesContent.metrics)
- ? servicesContent.metrics
- : []
- const heroMetrics = heroMetricFallback.map((metric) => {
- const match = heroMetricsSource.find((item) => item?.id === metric.id)
+ const heroMetrics = HERO_METRIC_FALLBACK.map((metric) => {
+ const match = Array.isArray(servicesContent.metrics)
+ ? servicesContent.metrics.find((item) => item?.id === metric.id)
+ : undefined
return {
...metric,
value: match?.value ?? metric.value,
@@ -140,517 +298,463 @@ export default function ServicesPage() {
}
})
- const pillarDefaults: PillarCard[] = [
- {
- id: 'security',
- icon: Shield,
- gradient: 'from-purple-500 via-violet-500 to-purple-600',
- iconColor: 'text-purple-400',
- title: 'Sécurité Maximale',
- description:
- 'Protection multi-couches avec supervision continue et technologies anti-détection de pointe pour une tranquillité totale.',
- bullets: [
- 'Surveillance anti-cheat 24/7',
- 'Kernel shield propriétaire',
- 'Chiffrement E2E permanent',
- ],
- stats: [
- { label: 'Protection', value: 'Kernel-level' },
- { label: 'Détection', value: '0%' },
- { label: 'Uptime', value: '99.9%' },
- { label: 'Audits', value: 'Quotidiens' },
- ],
- highlights: [
- 'Protection kernel-level avancée',
- 'HWID spoofer intégré',
- 'Bypass EAC/BE/Vanguard',
- 'Stream-proof garanti',
- 'Chiffrement bout en bout',
- 'Monitoring en temps réel',
- 'Alertes instantanées',
- 'Backup automatique',
- ],
- },
- {
- id: 'performance',
- icon: Cpu,
- gradient: 'from-blue-500 via-indigo-500 to-blue-600',
- iconColor: 'text-blue-400',
- title: 'Performance Extrême',
- description:
- 'Infrastructure bare-metal avec optimisation GPU frame-by-frame et pipelines CI/CD pensés pour le gaming compétitif.',
- bullets: [
- 'Clusters bare-metal dédiés',
- 'Optimisation GPU à la frame',
- 'Monitoring de latence en direct',
- ],
- stats: [
- { label: 'CPU', value: 'i9-13900K' },
- { label: 'GPU', value: 'RTX 4090' },
- { label: 'RAM', value: '128GB DDR5' },
- { label: 'Latence', value: '<1ms' },
- ],
- highlights: [
- 'Processeurs dernière génération',
- 'GPU RTX 4090 dédiés',
- 'RAM DDR5 ultra-rapide',
- 'SSD NVMe Gen4',
- 'Réseau 10Gbps',
- 'Optimisation automatique',
- 'Scaling instantané',
- 'Zero downtime',
- ],
- },
- {
- id: 'partnership',
- icon: HeadphonesIcon,
- gradient: 'from-emerald-500 via-teal-500 to-emerald-600',
- iconColor: 'text-emerald-400',
- title: 'Support Dédié',
- description:
- 'Account manager personnel, playbooks sur-mesure et support prioritaire sur canaux privés Discord et WhatsApp.',
- bullets: [
- 'Account manager dédié',
- 'Playbooks personnalisés',
- 'Escalade instantanée sur Discord',
- ],
- stats: [
- { label: 'Réponse', value: '<5min' },
- { label: 'Disponibilité', value: '24/7' },
- { label: 'Satisfaction', value: '98%' },
- { label: 'Résolution', value: '<30min' },
- ],
- highlights: [
- 'Manager dédié à votre compte',
- 'Canal Discord prioritaire',
- 'Support WhatsApp direct',
- 'Documentation personnalisée',
- 'Formations régulières',
- 'Veille technologique',
- 'Recommendations proactives',
- 'Revues mensuelles',
- ],
- },
- {
- id: 'infrastructure',
- icon: Cloud,
- gradient: 'from-cyan-500 via-sky-500 to-cyan-600',
- iconColor: 'text-cyan-400',
- title: 'Cloud Enterprise',
- description:
- 'Infrastructure cloud redondante multi-régions avec provisionnement automatisé et scaling intelligent en temps réel.',
- bullets: [
- 'Multi-régions global',
- 'Auto-scaling intelligent',
- 'Déploiement automatisé',
- ],
- stats: [
- { label: 'Régions', value: '12+' },
- { label: 'Uptime', value: '99.99%' },
- { label: 'Déploiement', value: '<2min' },
- { label: 'Backup', value: 'Temps réel' },
- ],
- highlights: [
- 'Présence dans 12 régions',
- 'Load balancing automatique',
- 'CDN global optimisé',
- 'Disaster recovery',
- 'Backup redondant',
- 'Migration à chaud',
- 'Scaling élastique',
- 'Monitoring avancé',
- ],
- },
- {
- id: 'analytics',
- icon: TrendingUp,
- gradient: 'from-amber-500 via-yellow-500 to-amber-600',
- iconColor: 'text-amber-400',
- title: 'Analytics & Insights',
- description:
- 'Tableaux de bord en temps réel avec métriques de performance détaillées et rapports d\'optimisation personnalisés.',
- bullets: [
- 'Dashboard temps réel',
- 'Métriques détaillées',
- 'Rapports personnalisés',
- ],
- stats: [
- { label: 'Métriques', value: '50+' },
- { label: 'Refresh', value: 'Temps réel' },
- { label: 'Historique', value: '6 mois' },
- { label: 'Exports', value: 'Illimités' },
- ],
- highlights: [
- 'Dashboard interactif',
- 'KPIs personnalisables',
- 'Alertes intelligentes',
- 'Rapports automatiques',
- 'Comparaisons périodiques',
- 'Prédictions IA',
- 'Export données brutes',
- 'API complète',
- ],
- },
- {
- id: 'compliance',
- icon: Award,
- gradient: 'from-pink-500 via-rose-500 to-pink-600',
- iconColor: 'text-pink-400',
- title: 'Conformité & Certifications',
- description:
- 'Infrastructure certifiée aux standards internationaux avec audits réguliers et conformité RGPD garantie.',
- bullets: [
- 'Certifications ISO',
- 'Conformité RGPD',
- 'Audits trimestriels',
- ],
- stats: [
- { label: 'Certifs', value: 'ISO 27001' },
- { label: 'RGPD', value: 'Conforme' },
- { label: 'Audits', value: 'Trimestriels' },
- { label: 'SOC', value: 'Type II' },
- ],
- highlights: [
- 'Certification ISO 27001',
- 'SOC 2 Type II compliant',
- 'RGPD full compliance',
- 'Audits indépendants',
- 'Documentation complète',
- 'Formation équipes',
- 'Politiques mises à jour',
- 'Transparence totale',
- ],
- },
- ]
-
- const pillarSource = Array.isArray(servicesContent.pillars)
- ? servicesContent.pillars
- : []
- const pillars = pillarDefaults.map((pillar) => {
- const match = pillarSource.find((item) => item?.id === pillar.id)
+ const pillars = useMemo(() => {
+ const source = Array.isArray(servicesContent.pillars)
+ ? servicesContent.pillars
+ : []
+ return PILLAR_BLUEPRINTS.map((pillar) => {
+ const match = source.find((item) => item?.id === pillar.id)
+ return {
+ ...pillar,
+ title: match?.title ?? pillar.label,
+ description: match?.description ?? pillar.defaultDescription,
+ bullets:
+ Array.isArray(match?.bullets) && match?.bullets?.length
+ ? (match?.bullets as string[])
+ : pillar.defaultBullets,
+ }
+ })
+ }, [servicesContent.pillars])
+
+ const [activePillarId, setActivePillarId] = useState
(
+ () => PILLAR_BLUEPRINTS[0]?.id ?? 'security',
+ )
+
+ const fallbackPillar = useMemo(() => {
+ const blueprint = PILLAR_BLUEPRINTS[0]
return {
- ...pillar,
- title: match?.title ?? pillar.title,
- description: match?.description ?? pillar.description,
- bullets:
- Array.isArray(match?.bullets) && match?.bullets?.length
- ? (match?.bullets as string[])
- : pillar.bullets,
+ ...blueprint,
+ title: blueprint.label,
+ description: blueprint.defaultDescription,
+ bullets: blueprint.defaultBullets,
}
- })
+ }, [])
+
+ const activePillar = pillars.find((pillar) => pillar.id === activePillarId)
+ const displayedPillar = activePillar ?? fallbackPillar
const pillarsHeading = {
- title: servicesContent.pillarsHeading?.title ?? 'Nos Services Premium',
+ title:
+ servicesContent.pillarsHeading?.title ?? 'Des fondations pensées pour le pro',
subtitle:
servicesContent.pillarsHeading?.subtitle ??
- 'Une suite complète de services professionnels pour maximiser vos performances et votre sécurité.',
+ 'Chaque pilier combine nos briques cloud, sécurité et support pour une exécution PulseForge sans faille.',
}
- const solutionDefaults: SolutionCard[] = [
- {
- id: 'cloud',
- icon: Rocket,
- gradient: 'from-sky-500 via-blue-600 to-indigo-600',
- title: 'Cloud Gaming Infrastructure',
- description:
- 'Infrastructure cloud complète avec machines virtuelles optimisées, auto-scaling intelligent et déploiement multi-régions instantané.',
- link: `/${locale}/premium`,
- linkLabel: 'Découvrir Premium',
- },
- {
- id: 'competitive',
- icon: Target,
- gradient: 'from-purple-500 via-fuchsia-500 to-purple-600',
- title: 'Solutions Anti-Cheat',
- description:
- 'Protection avancée avec reverse engineering continu, correctifs jour zéro et protocoles d\'audit pour rester indétectable sur tous les anti-cheats.',
- link: `/${locale}/games`,
- linkLabel: 'Voir les jeux',
- },
- {
- id: 'custom',
- icon: Users,
- gradient: 'from-emerald-500 via-teal-500 to-emerald-600',
- title: 'Coaching & Intégrations',
- description:
- 'Accompagnement personnalisé avec sessions 1:1, assistance en direct, intégrations API sur-mesure et formation continue de vos équipes.',
- link: `/${locale}/contact`,
- linkLabel: 'Nous contacter',
- },
- ]
-
- const solutionsSource = servicesContent.solutions?.items ?? []
- const solutions = solutionDefaults.map((solution) => {
- const match = solutionsSource.find((item) => item?.id === solution.id)
- return {
- ...solution,
- title: match?.title ?? solution.title,
- description: match?.description ?? solution.description,
- linkLabel: match?.linkLabel ?? solution.linkLabel,
- }
- })
+ const solutions = useMemo(() => {
+ const source = Array.isArray(servicesContent.solutions?.items)
+ ? servicesContent.solutions?.items ?? []
+ : []
+ return SOLUTION_BLUEPRINTS.map((solution) => {
+ const match = source.find((item) => item?.id === solution.id)
+ return {
+ ...solution,
+ title: match?.title ?? solution.defaultTitle,
+ description: match?.description ?? solution.defaultDescription,
+ linkLabel: match?.linkLabel ?? solution.defaultLinkLabel,
+ link: solution.linkBuilder(locale),
+ }
+ })
+ }, [servicesContent.solutions?.items, locale])
const solutionsHeading = {
- title: servicesContent.solutions?.title ?? 'Solutions Complètes',
+ title: servicesContent.solutions?.title ?? 'Modules prêts à activer',
subtitle:
servicesContent.solutions?.subtitle ??
- 'Des modules flexibles qui s\'intègrent parfaitement à votre workflow pour un écosystème gaming complet.',
+ 'Composez votre stack PulseForge en sélectionnant les modules adaptés à vos besoins opérationnels.',
}
- const processFallback = [
- {
- id: 'discover',
- title: 'Découverte & Audit',
- description:
- 'Analyse approfondie de vos besoins, objectifs de performance et contraintes techniques pour créer une solution parfaitement adaptée.',
- },
- {
- id: 'prototype',
- title: 'Prototype & Test',
- description:
- 'Mise en place d\'un environnement de test avec configurations optimisées et validation complète avant déploiement production.',
- },
- {
- id: 'deploy',
- title: 'Déploiement Production',
- description:
- 'Migration progressive avec supervision continue, formation de vos équipes et documentation technique complète.',
- },
- {
- id: 'optimize',
- title: 'Optimisation Continue',
- description:
- 'Monitoring permanent, revues mensuelles, ajustements proactifs et évolution de l\'infrastructure selon vos besoins.',
- },
- ]
-
- const processSource = servicesContent.process?.steps ?? []
- const processSteps = processFallback.map((step) => {
- const match = processSource.find((item) => item?.id === step.id)
- return {
- ...step,
- title: match?.title ?? step.title,
- description: match?.description ?? step.description,
- }
- })
+ const processSteps = useMemo(() => {
+ const source = Array.isArray(servicesContent.process?.steps)
+ ? servicesContent.process?.steps ?? []
+ : []
+ return PROCESS_FALLBACK.map((step) => {
+ const match = source.find((item) => item?.id === step.id)
+ return {
+ ...step,
+ title: match?.title ?? step.title,
+ description: match?.description ?? step.description,
+ }
+ })
+ }, [servicesContent.process?.steps])
const processHeading = {
- title: servicesContent.process?.title ?? 'Notre Méthodologie',
+ title: servicesContent.process?.title ?? 'Notre méthode accompagnée',
subtitle:
servicesContent.process?.subtitle ??
- 'Un processus éprouvé qui garantit une intégration fluide et des résultats mesurables dès le premier jour.',
+ 'Un cadre en quatre phases pour intégrer PulseForge sans rupture et avec un pilotage constant.',
}
const contactContent = servicesContent.contact ?? {}
- const contactMetricFallback: ServicesMetric[] = [
- { id: 'sla', value: '5', label: 'Temps de réponse (min)' },
- { id: 'coverage', value: '365', label: 'Jours par an' },
- { id: 'satisfaction', value: '98', label: 'Satisfaction (%)' },
- ]
-
- const contactMetricsSource = Array.isArray(contactContent.metrics)
- ? contactContent.metrics
- : []
- const contactMetrics = contactMetricFallback.map((metric) => {
- const match = contactMetricsSource.find((item) => item?.id === metric.id)
- return {
- ...metric,
- value: match?.value ?? metric.value,
- label: match?.label ?? metric.label,
- }
- })
-
- const contactNote =
- contactContent.note ??
- 'Un canal prioritaire Discord & WhatsApp est activé dès la signature du contrat.'
-
- const contactTitle = contactContent.title ?? 'Prêt à démarrer ?'
+ const contactMetrics = useMemo(() => {
+ const source = Array.isArray(contactContent.metrics)
+ ? contactContent.metrics
+ : []
+ return CONTACT_METRIC_FALLBACK.map((metric) => {
+ const match = source.find((item) => item?.id === metric.id)
+ return {
+ ...metric,
+ value: match?.value ?? metric.value,
+ label: match?.label ?? metric.label,
+ }
+ })
+ }, [contactContent.metrics])
+
+ const contactTitle =
+ contactContent.title ?? 'Prêt à lancer votre build PulseForge ?'
const contactDescription =
contactContent.description ??
- 'Notre équipe vous répond sous 24h pour évaluer vos besoins et préparer un plan d\'action personnalisé.'
- const contactCta = contactContent.cta ?? 'Planifier un call'
+ 'Nos ingénieurs vous répondent sous 24 h pour cadrer les besoins, planifier les tests et verrouiller la mise en production.'
+ const contactCta = contactContent.cta ?? 'Planifier un call dédié'
+ const contactNote =
+ contactContent.note ??
+ 'Un canal prioritaire (Discord + WhatsApp) est ouvert dès la signature pour les escalades critiques.'
return (
-
+
+
+
+
+
+
+
+
+
+
+
+ {badge}
+
+
+
+ {title}
+
+
+
+ {subtitle}
+
+
+
+
+ {primaryCta}
+
+
+ Explorer les offres
+
+
+
- {/* Background Effects */}
-
-
-
- {/* Background grid */}
-
-
-
-
- {/* Hero Section */}
-
-
-
- {badge}
-
-
-
-
- {title}
-
-
-
-
- {subtitle}
-
-
- {/* Animated Counters */}
-
- {heroMetrics.map((metric) => (
-
- ))}
-
-
-
- {primaryCta}
-
-
-
-
- {/* Pillars Title */}
-
-
-
- {pillarsHeading.title}
-
-
-
- {pillarsHeading.subtitle}
-
-
-
- {/* Flip Cards Grid */}
-
- {pillars.map((pillar) => (
-
- ))}
-
-
- {/* Solutions Section */}
-
-
-
-
- {solutionsHeading.title}
-
-
-
- {solutionsHeading.subtitle}
-
+
+ {heroMetrics.map((metric, index) => (
+
+
+ {metric.label}
+ {metric.value}
+
+ ))}
+
+
+
+
+
+
+
+ Pillars
+
+ {pillarsHeading.title}
+
+ {pillarsHeading.subtitle}
+
+
+
+
+ {pillars.map((pillar) => {
+ const Icon = pillar.icon
+ const isActive = pillar.id === activePillarId
+ return (
+
+ )
+ })}
+
- {/* Glowing Cards */}
-
- {solutions.map((solution) => (
-
- ))}
+
+
+
+
+
+
+
{displayedPillar.title}
+
{displayedPillar.description}
+
+
+ {displayedPillar.stats.map((stat) => (
+
+
{stat.label}
+
{stat.value}
+
+ ))}
+
+
+
+
+ {displayedPillar.bullets.map((bullet, index) => (
+
+
+ {bullet}
+
+ ))}
+
+
+
+
+
-
-
- {/* Process Section - Interactive Timeline */}
-
-
-
-
- {processHeading.title}
-
-
-
- {processHeading.subtitle}
-
+
+
+
+
+
+ Modules
+
+ {solutionsHeading.title}
+
+ {solutionsHeading.subtitle}
+
+
+
+ {solutions.map((solution, index) => {
+ const Icon = solution.icon
+ return (
+
+
+
+
+
+
+
{solution.title}
+
{solution.description}
+
+
+ {solution.linkLabel}
+
+
+
+
+
+ )
+ })}
+
-
-
-
-
- {/* CTA Section */}
-
-
-
-
-
- {contactTitle}
+
+
+
+
+
+ Process
+
+ {processHeading.title}
-
- {contactDescription}
-
-
- {/* Contact Metrics with Animation */}
-
- {contactMetrics.map((metric) => (
-
- ))}
+
{processHeading.subtitle}
+
+
+
+ {processSteps.map((step, index) => (
+
+
+
+
+
+ {index + 1}
+
+
{step.title}
+
+
{step.description}
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+
Contact
+
{contactTitle}
+
{contactDescription}
+
+
+ {contactMetrics.map((metric) => (
+
+
{metric.label}
+
{metric.value}
+
+ ))}
+
- {contactNote}
-
-
+
{contactCta}
-
-
-
- Voir les offres
+
{contactNote}
-
+
-
-
-
-
+
+
+
)
diff --git a/components/CommunityGamingProductPage.tsx b/components/CommunityGamingProductPage.tsx
index ba721d9..c253133 100644
--- a/components/CommunityGamingProductPage.tsx
+++ b/components/CommunityGamingProductPage.tsx
@@ -1,238 +1,312 @@
'use client'
+import { useMemo } from 'react'
import { Star, Check, ArrowRight, Users, Cloud } from 'lucide-react'
import Link from 'next/link'
-import { usePathname } from 'next/navigation'
-import type { GamingProduct, ProductVariant } from '@/lib/gaming-products'
+import type { GamingProduct } from '@/lib/gaming-products'
import { getSubscriptionPlans } from '@/lib/subscriptions'
+import type { SubscriptionPlan } from '@/lib/subscriptions'
import ProductImage from './ProductImage'
+import SiteHeader from '@/components/SiteHeader'
+import Footer from '@/components/Footer'
+import { useI18n } from '@/lib/i18n-simple'
+import { motion } from 'framer-motion'
+
+const inViewFadeProps = {
+ initial: { opacity: 0, y: 28 },
+ whileInView: { opacity: 1, y: 0 },
+ viewport: { once: true, amount: 0.25 }
+} as const
+
+const inViewSlideProps = {
+ initial: { opacity: 0, x: -36 },
+ whileInView: { opacity: 1, x: 0 },
+ viewport: { once: true, amount: 0.25 }
+} as const
+
+const inViewScaleProps = {
+ initial: { opacity: 0, scale: 0.9, y: 18 },
+ whileInView: { opacity: 1, scale: 1, y: 0 },
+ viewport: { once: true, amount: 0.3 }
+} as const
+
+const inViewTiltProps = {
+ initial: { opacity: 0, rotateX: -8, y: 24 },
+ whileInView: { opacity: 1, rotateX: 0, y: 0 },
+ viewport: { once: true, amount: 0.25 }
+} as const
+
+const hoverLiftProps = {
+ whileHover: { y: -8, scale: 1.02 },
+ whileTap: { scale: 0.98 }
+} as const
+
+const hoverGlowProps = {
+ whileHover: { y: -6, scale: 1.01, boxShadow: '0px 16px 38px rgba(59, 130, 246, 0.35)' },
+ whileTap: { scale: 0.99 }
+} as const
+
+const fadeTransition = { duration: 0.6, ease: 'easeOut' } as const
interface CommunityGamingProductPageProps {
product: GamingProduct
}
+type CommunityPageCopy = {
+ breadcrumb: { home: string; games: string }
+ badges: { catalog: string; support: string }
+ subscription: { title: string; description: string; popular: string; viewDetails: string }
+ about: { title: string }
+ featuresTitle: string
+ benefits: { title: string; items: Array<{ title: string; description: string }> }
+ cta: { title: string; description: string; button: string }
+ reviewsLabel: string
+}
+
+const formatMessage = (template?: string, replacements: Record
= {}) =>
+ template
+ ? Object.entries(replacements).reduce(
+ (result, [key, value]) => result.replaceAll(`{{${key}}}`, value),
+ template,
+ )
+ : undefined
+
export default function CommunityGamingProductPage({ product }: CommunityGamingProductPageProps) {
- const pathname = usePathname()
- const locale = pathname.split('/')[1]
+ const { t, locale } = useI18n()
+ const copy = t.communityProductPage as CommunityPageCopy
+ const planTranslations = t.premiumSignup?.plans as Record> | undefined
+
+ const subscriptionDescription =
+ formatMessage(copy.subscription.description, { productName: product.name }) ??
+ `Accédez à ${product.name} avec n'importe quel abonnement Hackboot`
+ const aboutTitle =
+ formatMessage(copy.about.title, { productName: product.name }) ?? `À propos de ${product.name}`
+ const ctaTitle =
+ formatMessage(copy.cta.title, { game: product.game }) ?? `Prêt à jouer à ${product.game} ?`
+ const ctaDescription =
+ formatMessage(copy.cta.description, { productName: product.name }) ??
+ `Choisissez votre abonnement et accédez immédiatement à ${product.name}`
const subscriptionPlans = getSubscriptionPlans()
+ const localizedPlans = useMemo(
+ () =>
+ subscriptionPlans.map((plan) => {
+ const override = planTranslations?.[plan.id]
+ if (!override) {
+ return plan
+ }
+ return {
+ ...plan,
+ ...override,
+ features: override.features ?? plan.features
+ }
+ }),
+ [subscriptionPlans, planTranslations]
+ )
+ const benefitIcons = [Cloud, Users, Check] as const
const variant = product.variants[0]
return (
-
- {/* Breadcrumb */}
-
-
-
-
- {/* Hero Section */}
-
-
- {/* Image */}
-
-
-
-
-
- Catalogue Communautaire
-
-
-
-
+
+
+
+
+
+
- {/* Product Info */}
-
-
-
-
- SUPPORT COMMUNAUTAIRE
-
- •
- {product.game}
-
-
{product.name}
-
{product.description}
-
+
+
+
+
+
+
+
+
+
+ {copy.badges.catalog}
+
+
+
+
- {product.reviews.count > 0 && (
-
-
- {[...Array(5)].map((_, i) => (
-
- ))}
+
+
+
+
+ {copy.badges.support}
+
+ •
+ {product.game}
-
{product.reviews.average}
-
({product.reviews.count} avis)
+
{product.name}
+
{product.description}
- )}
-
- {/* Choisissez votre abonnement */}
-
-
Choisissez votre abonnement
-
- Accédez à {product.name} avec n'importe quel abonnement Hackboot
-
-
- {subscriptionPlans.map((plan) => (
-
- {plan.popular && (
-
- Le plus populaire
-
- )}
-
-
-
{plan.name}
-
{plan.description}
-
-
-
{plan.price.toFixed(2)}€
-
{plan.billing}
-
-
-
-
- ))}
-
-
- {/* Configuration */}
-
-
Configuration Standard
-
-
- GPU
- {variant.gpu}
-
-
- RAM
- {variant.ram}
-
-
- CPU
- {variant.cpu}
-
-
-
Support
-
Communautaire
+ {product.reviews.count > 0 && (
+
+
+ {[...Array(5)].map((_, i) => (
+
+ ))}
+
+ {product.reviews.average}
+ ({product.reviews.count} {copy.reviewsLabel})
+
+ )}
+
+
+
{copy.subscription.title}
+
{subscriptionDescription}
+
+ {localizedPlans.map((plan, idx) => (
+
+
+ {plan.popular && (
+
+ {copy.subscription.popular}
+
+ )}
+
+
+
{plan.name}
+
{plan.description}
+
+
+
{plan.price.toFixed(2)}€
+
{plan.billing}
+
+
+
+
{copy.subscription.viewDetails}
+
+
+
+
+ ))}
-
+
-
- {/* About Section */}
-
-
-
À propos de {product.name}
-
- {product.longDescription}
-
-
-
-
- {/* Features */}
-
-
-
Fonctionnalités
-
-
-
-
- {variant.features.map((feature, idx) => (
-
-
- {feature}
-
- ))}
-
-
-
+
+
+ {aboutTitle}
+ {product.longDescription}
+
+
- {/* Community Benefits */}
-
-
-
Avantages du Catalogue Communautaire
-
+
+
+ {copy.featuresTitle}
+
-
-
-
-
+
+
+ {variant.features.map((feature, idx) => (
+
+
+ {feature}
+
+ ))}
- Infrastructure Cloud
-
- Configuration cloud standard optimisée pour des performances fiables
-
-
+
+
-
-
-
-
-
Support Communautaire
-
- Accédez aux forums, guides et aide de la communauté Hackboot
-
-
+
+
+ {copy.benefits.title}
+
-
-
-
-
-
Mises à Jour Régulières
-
- Configurations maintenues à jour avec les derniers patchs du jeu
-
+
+ {copy.benefits.items.map((item, index) => {
+ const Icon = benefitIcons[index] ?? Cloud
+ return (
+
+
+
+
+ {item.title}
+ {item.description}
+
+ )
+ })}
-
-
+
- {/* CTA Section */}
-
-
Prêt à Jouer à {product.game} ?
-
- Choisissez votre abonnement et accédez immédiatement à {product.name}
-
-
- Choisir mon abonnement
-
-
+
{ctaTitle}
+
{ctaDescription}
+
+
+ {copy.cta.button}
+
+
+
+
-
+
+
)
}
diff --git a/components/Header.tsx b/components/Header.tsx
index 321e400..908c5d2 100644
--- a/components/Header.tsx
+++ b/components/Header.tsx
@@ -1,6 +1,7 @@
'use client'
import { useState, useEffect, useMemo } from 'react'
+import { AnimatePresence, motion } from 'framer-motion'
import Link from 'next/link'
import { usePathname, useRouter } from 'next/navigation'
import LanguageSelectorSimplest from '@/components/LanguageSelectorSimplest'
@@ -38,6 +39,16 @@ const Header = () => {
return () => window.removeEventListener('scroll', handleScroll)
}, [])
+ const overlayTransition = useMemo(
+ () => ({ duration: 0.25, ease: [0.4, 0, 0.2, 1] }),
+ []
+ )
+
+ const panelTransition = useMemo(
+ () => ({ type: 'spring', stiffness: 260, damping: 28, mass: 0.9 }),
+ []
+ )
+
const navigation = [
{ name: t?.nav?.home || 'Accueil', href: basePath },
{ name: t?.nav?.games || 'Jeux', href: `${basePath}/games` },
@@ -135,17 +146,32 @@ const Header = () => {
{/* Mobile Menu */}
- {isMobileMenuOpen && (
- <>
-