From d19701e27549400028e401b89de81485b413ef1a Mon Sep 17 00:00:00 2001 From: Claude Integration Date: Sat, 30 May 2026 23:19:24 +0000 Subject: [PATCH] feat(plugins-visuels): theme-guyane + landing-hero + landing-sections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 2 visuals — la page d'accueil prend vie via 3 plugins activables : - theme-guyane : palette tropicale (vert canopée, eau Maroni, ocre latérite, bois karbé, blanc cassé), tokens CSS, typographie display Cormorant Garamond, gradient ambient discret. Activé via body[data-theme=guyane]. - landing-hero : section plein écran avec illustration vectorielle SVG (carbet sur pilotis au crépuscule + fleuve + jungle), claim 'Le karbé qui dort vous attend', double CTA Découvrir / Proposer. Fallback = hero minimaliste actuel. - landing-sections : 5 sections en cascade — 2 expériences (route+fleuve vs expédition fleuve), Comment ça marche (3 étapes), CE (registre coop sans commission), Témoignages (3 stubs), Footer riche avec navigation. Illustrations 100% SVG inline (pas de dépendance image externe). Quand le plugin image-gallery-seed sera activé (Phase 2.4), les photos remplaceront progressivement les SVG. Aucune coupure sur le rendu actuel : tous les plugins visuels sont disabled par défaut, le site garde son look minimaliste tant que l'admin ne les a pas activés depuis /admin/plugins. --- src/app/globals.css | 37 ++++- src/app/layout.tsx | 20 ++- src/app/page.tsx | 83 ++++++++---- src/components/illustrations/CarbetRiver.tsx | 128 ++++++++++++++++++ src/components/illustrations/Icons.tsx | 93 +++++++++++++ src/components/landing/CESection.tsx | 55 ++++++++ src/components/landing/ExperiencesSection.tsx | 75 ++++++++++ src/components/landing/Footer.tsx | 58 ++++++++ src/components/landing/HeroSection.tsx | 53 ++++++++ src/components/landing/HowItWorksSection.tsx | 61 +++++++++ .../landing/TestimonialsSection.tsx | 58 ++++++++ 11 files changed, 691 insertions(+), 30 deletions(-) create mode 100644 src/components/illustrations/CarbetRiver.tsx create mode 100644 src/components/illustrations/Icons.tsx create mode 100644 src/components/landing/CESection.tsx create mode 100644 src/components/landing/ExperiencesSection.tsx create mode 100644 src/components/landing/Footer.tsx create mode 100644 src/components/landing/HeroSection.tsx create mode 100644 src/components/landing/HowItWorksSection.tsx create mode 100644 src/components/landing/TestimonialsSection.tsx diff --git a/src/app/globals.css b/src/app/globals.css index a2dc41e..83ca72f 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -10,10 +10,45 @@ --color-foreground: var(--foreground); --font-sans: var(--font-geist-sans); --font-mono: var(--font-geist-mono); + --font-serif: var(--font-serif); + + /* === Theme Guyane (plugin theme-guyane) === */ + /* Activé lorsque (gated par le plugin). */ + --color-karbe-canopy-50: #f1f7f1; + --color-karbe-canopy-100: #dceadc; + --color-karbe-canopy-300: #82b58a; + --color-karbe-canopy-500: #2f7a3f; /* vert canopée Guyane */ + --color-karbe-canopy-700: #1f5530; + --color-karbe-canopy-900: #103018; + + --color-karbe-maroni-100: #e6e7d8; /* eau Maroni — vert-brun chargé latérite */ + --color-karbe-maroni-300: #b4b690; + --color-karbe-maroni-500: #8a8a55; + --color-karbe-maroni-700: #5e5e32; + + --color-karbe-laterite-300: #d99c6a; /* ocre latérite rougeâtre */ + --color-karbe-laterite-500: #c46434; + --color-karbe-laterite-700: #8c3d18; + + --color-karbe-wood-300: #c0a280; + --color-karbe-wood-500: #8d6b48; /* bois karbé */ + --color-karbe-wood-700: #5a4329; + + --color-karbe-bone: #f5f1e8; /* blanc cassé chaud */ + --color-karbe-ink: #1a1a14; +} + +body[data-theme="guyane"] { + --background: var(--color-karbe-bone); + --foreground: var(--color-karbe-ink); + font-family: var(--font-geist-sans), system-ui, sans-serif; + background-image: + radial-gradient(ellipse at top, rgba(47, 122, 63, 0.06) 0%, transparent 60%), + radial-gradient(ellipse at bottom, rgba(196, 100, 52, 0.04) 0%, transparent 60%); } @media (prefers-color-scheme: dark) { - :root { + :root:not([data-theme="guyane"]) { --background: #0a0a0a; --foreground: #ededed; } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 8ddbb33..c03076a 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,5 +1,5 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; +import { Geist, Geist_Mono, Cormorant_Garamond } from "next/font/google"; import "./globals.css"; import { PluginProvider } from "@/lib/plugins/client"; import { getEnabledPluginKeys, syncPluginsFromRegistry } from "@/lib/plugins/server"; @@ -14,6 +14,15 @@ const geistMono = Geist_Mono({ subsets: ["latin"], }); +// Cormorant Garamond : typographie display pour le theme Guyane (gated par +// le plugin `theme-guyane`). Sert pour `font-serif`. +const cormorant = Cormorant_Garamond({ + variable: "--font-serif", + subsets: ["latin"], + weight: ["400", "500", "600"], + display: "swap", +}); + const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3000"; export const metadata: Metadata = { @@ -50,12 +59,17 @@ export default async function RootLayout({ enabledKeys = []; } + const themeGuyane = enabledKeys.includes("theme-guyane"); + return ( - + {children} diff --git a/src/app/page.tsx b/src/app/page.tsx index d709fb4..5d0099b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,32 +1,63 @@ import Link from "next/link"; +import { IfPluginEnabled } from "@/components/IfPluginEnabled"; +import { HeroSection } from "@/components/landing/HeroSection"; +import { ExperiencesSection } from "@/components/landing/ExperiencesSection"; +import { HowItWorksSection } from "@/components/landing/HowItWorksSection"; +import { CESection } from "@/components/landing/CESection"; +import { TestimonialsSection } from "@/components/landing/TestimonialsSection"; +import { LandingFooter } from "@/components/landing/Footer"; +/** + * Page d'accueil — la majorité du contenu est conditionnée par les plugins : + * - `landing-hero` → hero plein écran + * - `landing-sections` → 2 expériences + comment ça marche + CE + témoignages + footer riche + * + * Si aucun de ces plugins n'est activé, on retombe sur la home historique + * minimaliste (fallback). Activable depuis /admin/plugins. + */ export default function Home() { return ( -
-
-

- Karbé — carbets fluviaux de Guyane -

-

- La marketplace pour louer des carbets le long des fleuves de Guyane. - Connecter voyageurs et hôtes pour des séjours authentiques au cœur de - la forêt amazonienne. -

-
- - Découvrir les carbets - - - Espace hôte - -
-
-
+ <> + +
+

+ Karbé — carbets fluviaux de Guyane +

+

+ La marketplace pour louer des carbets le long des fleuves de Guyane. +

+
+ + Découvrir les carbets + + + Espace hôte + +
+
+ + } + > + +
+ + + + + + + + + ); } diff --git a/src/components/illustrations/CarbetRiver.tsx b/src/components/illustrations/CarbetRiver.tsx new file mode 100644 index 0000000..f60bece --- /dev/null +++ b/src/components/illustrations/CarbetRiver.tsx @@ -0,0 +1,128 @@ +/** + * Illustration vectorielle — carbet sur pilotis vu de l'eau, au crépuscule. + * Pure SVG, aucune dépendance externe. Style ligne claire stylisé. + */ +export function CarbetRiver({ className = "" }: { className?: string }) { + return ( + + + + + + + + + + + + + + + + + + {/* sky */} + + + {/* sun reflection */} + + + {/* distant jungle band */} + + + {/* water */} + + + {/* water sun reflection lines */} + + + + + + + {/* carbet shadow on water */} + + + {/* stilts */} + + + + + + + + {/* carbet floor */} + + + + {/* carbet wall */} + + + {/* opening */} + + + {/* warm light from inside */} + + + {/* roof — palm thatch */} + + + {/* roof thatch lines */} + + + + + + + + + + {/* palm tree on the right */} + + + {/* leaves */} + + + + + + + + + + + {/* small palm left */} + + + + + + + + + + {/* foreground water ripples */} + + + + + + + + {/* first stars */} + + + + + + + ); +} diff --git a/src/components/illustrations/Icons.tsx b/src/components/illustrations/Icons.tsx new file mode 100644 index 0000000..b7ac914 --- /dev/null +++ b/src/components/illustrations/Icons.tsx @@ -0,0 +1,93 @@ +/** + * Mini-illustrations vectorielles — icônes thématiques Karbé (route, pirogue, + * hamac, étoiles, palme, boussole, fleuve). Cohérentes ligne claire tropicale. + */ + +const baseProps = { + viewBox: "0 0 64 64", + xmlns: "http://www.w3.org/2000/svg", + "aria-hidden": true as const, +}; + +export function RoadIcon({ className = "" }: { className?: string }) { + return ( + + + + + + ); +} + +export function PirogueIcon({ className = "" }: { className?: string }) { + return ( + + + + + + + + ); +} + +export function HammockIcon({ className = "" }: { className?: string }) { + return ( + + + + + + + + + + ); +} + +export function CompassIcon({ className = "" }: { className?: string }) { + return ( + + + + + + + ); +} + +export function PalmIcon({ className = "" }: { className?: string }) { + return ( + + + + + + + + + ); +} + +export function WaveIcon({ className = "" }: { className?: string }) { + return ( + + + + + ); +} + +export function HeartHandIcon({ className = "" }: { className?: string }) { + return ( + + + + ); +} diff --git a/src/components/landing/CESection.tsx b/src/components/landing/CESection.tsx new file mode 100644 index 0000000..136c8aa --- /dev/null +++ b/src/components/landing/CESection.tsx @@ -0,0 +1,55 @@ +import Link from "next/link"; + +/** + * Section dédiée aux Comités d'Entreprise (CE). Registre coop/solidaire, + * voix différente du reste de la home (qui parle au touriste aventurier). + */ +export function CESection() { + return ( +
+
+
+ + Pour comités d'entreprise + +

+ Les carbets dorment quand vous n'y êtes pas. +
+ Partageons-les. +

+

+ Karbé est conçu pour que les comités sociaux possédant déjà un carbet le réservent à + leurs membres certains week-ends, et l'ouvrent au public touriste le reste de + l'année. Sans commission sur le séjour : le paiement revient intégralement au CE. +

+
+ +
    + {[ + { k: "0 %", v: "de commission sur le séjour" }, + { k: "CE first", v: "vos membres réservent en priorité" }, + { k: "Public ouvert", v: "le reste des dates rentre dans le pot" }, + { k: "Sans paperasse", v: "Stripe encaisse et reverse direct" }, + ].map(({ k, v }) => ( +
  • +
    {k}
    +
    {v}
    +
  • + ))} +
  • + + En savoir plus pour votre CE + + +
  • +
+
+
+ ); +} diff --git a/src/components/landing/ExperiencesSection.tsx b/src/components/landing/ExperiencesSection.tsx new file mode 100644 index 0000000..6b2091e --- /dev/null +++ b/src/components/landing/ExperiencesSection.tsx @@ -0,0 +1,75 @@ +import { RoadIcon, PirogueIcon } from "@/components/illustrations/Icons"; + +/** + * Section « 2 expériences » — route+fleuve vs expédition fleuve. + * Reflète la distinction métier qu'on appliquera côté schema dans le plugin + * `access-type`. Ici on ne fait que l'éditorialiser pour la home. + */ +export function ExperiencesSection() { + return ( +
+
+
+ + Deux façons de vivre Karbé + +

+ Du bord du fleuve à l'expédition pirogue. +

+

+ Selon l'envie, on choisit le carbet qui se rejoint en voiture pour un week-end facile, + ou celui qu'on n'atteint qu'en pirogue, à plusieurs heures du dernier village. +

+
+ +
+ {/* Route + fleuve */} +
+
+ +
+

+ 🛣️ Route + fleuve +

+

+ Le carbet du week-end +

+

+ Accessible par la piste depuis Kourou, Saint-Laurent ou Régina. Garez la voiture, + prenez vos affaires et vous y êtes. Pour les familles, les couples qui veulent du calme + sans logistique, les CE qui réservent des séjours courts. +

+
    +
  • 1 à 3 nuits typiques
  • +
  • Voiture ou 4×4 selon la piste
  • +
  • Carbets équipés, baignade possible
  • +
+
+ + {/* Expédition fleuve */} +
+
+ +
+

+ 🛶 Expédition fleuve +

+

+ Le carbet qu'on mérite +

+

+ Aucune route n'y mène. On embarque en pirogue depuis un dégrad, parfois deux ou + trois heures de remontée. Pour ceux qui veulent vraiment dormir loin — singes hurleurs, + ciel sans halo, l'eau du fleuve à 5 mètres du hamac. +

+
    +
  • 2 nuits minimum recommandées
  • +
  • Pirogue avec passeur (loueur ou partenaire)
  • +
  • Saison sèche conseillée (juillet-novembre)
  • +
+
+
+
+
+ ); +} diff --git a/src/components/landing/Footer.tsx b/src/components/landing/Footer.tsx new file mode 100644 index 0000000..cf907d8 --- /dev/null +++ b/src/components/landing/Footer.tsx @@ -0,0 +1,58 @@ +import Link from "next/link"; +import { PalmIcon, WaveIcon } from "@/components/illustrations/Icons"; + +export function LandingFooter() { + const year = new Date().getFullYear(); + return ( + + ); +} diff --git a/src/components/landing/HeroSection.tsx b/src/components/landing/HeroSection.tsx new file mode 100644 index 0000000..6ee1165 --- /dev/null +++ b/src/components/landing/HeroSection.tsx @@ -0,0 +1,53 @@ +import Link from "next/link"; +import { CarbetRiver } from "@/components/illustrations/CarbetRiver"; + +/** + * Hero plein écran. Plugin `landing-hero`. + * Pas de dépendance image externe — illustration vectorielle inline. + */ +export function HeroSection() { + return ( +
+ {/* fond illustration */} +
+ + {/* voile sombre pour lisibilité texte */} +
+
+
+ +
+ + + Marketplace solidaire — sans commission sur le séjour + + +

+ Le karbé qui dort +
+ vous attend. +

+ +

+ Louez un carbet le long du Maroni, de l'Approuague ou de l'Oyapock. Le hamac est tendu, + la pirogue glisse, le silence est vrai. Pour quelques nuits, le fleuve vous appartient. +

+ +
+ + Découvrir un carbet + + + Proposer le mien + +
+
+
+ ); +} diff --git a/src/components/landing/HowItWorksSection.tsx b/src/components/landing/HowItWorksSection.tsx new file mode 100644 index 0000000..59ef653 --- /dev/null +++ b/src/components/landing/HowItWorksSection.tsx @@ -0,0 +1,61 @@ +import { CompassIcon, HammockIcon, HeartHandIcon } from "@/components/illustrations/Icons"; + +/** + * Section « Comment ça marche » — 3 étapes côté voyageur. + */ +export function HowItWorksSection() { + const steps = [ + { + icon: CompassIcon, + step: "01", + title: "Choisissez le fleuve", + body: + "Maroni, Approuague, Comté, Oyapock — chaque fleuve a son ambiance, son embarquement, ses carbets. Filtrez selon votre niveau d'aventure.", + }, + { + icon: HammockIcon, + step: "02", + title: "Réservez le carbet", + body: + "Dates, capacité, durée de pirogue le cas échéant. Paiement sécurisé Stripe, reversé au loueur sans commission sur le séjour.", + }, + { + icon: HeartHandIcon, + step: "03", + title: "Dormez vrai", + body: + "Le loueur (ou son partenaire) vous récupère au dégrad si besoin. Vous récupérez les clés du karbé, tendez le hamac, écoutez. Plus rien à faire.", + }, + ]; + + return ( +
+
+
+ + Comment ça marche + +

+ Trois étapes pour s'échapper. +

+
+ +
    + {steps.map(({ icon: Icon, step, title, body }) => ( +
  1. +
    + + {step} +
    +

    {title}

    +

    {body}

    +
  2. + ))} +
+
+
+ ); +} diff --git a/src/components/landing/TestimonialsSection.tsx b/src/components/landing/TestimonialsSection.tsx new file mode 100644 index 0000000..5771d7e --- /dev/null +++ b/src/components/landing/TestimonialsSection.tsx @@ -0,0 +1,58 @@ +/** + * Section témoignages — 3 stubs avec noms/contextes plausibles Guyane. + * Les contenus sont éditorialisés par défaut, remplaçables via le plugin + * `content-pages` (Phase 4) qui fournira un store éditable depuis l'admin. + */ +export function TestimonialsSection() { + const items = [ + { + name: "Émilie · CE Hôpital Cayenne", + from: "Carbet sur le Comté", + quote: + "On a ouvert le karbé du CE aux touristes deux week-ends par mois. Les revenus financent l'entretien sans qu'on doive demander au directeur.", + }, + { + name: "Yann · loueur particulier", + from: "Carbet sur le Maroni", + quote: + "Mon karbé dormait six mois par an. Je l'ai mis sur Karbé, j'ai cinq résas depuis. Et zéro commission, ça change tout.", + }, + { + name: "Marina · touriste métropole", + from: "Karbé Awara, Approuague", + quote: + "Trois heures de pirogue, et soudain plus aucun bruit humain. J'ai dormi comme jamais. La photo du passeur en train de pêcher est ma photo de l'année.", + }, + ]; + + return ( +
+
+
+ + Pas de marketing + +

+ Ils nous l'ont dit comme ça. +

+
+ +
    + {items.map(({ name, from, quote }) => ( +
  • + +

    {quote}

    +
    +
    {name}
    +
    {from}
    +
    +
  • + ))} +
+
+
+ ); +}