feat: rebuild 3 demo pages with interactive features + local SEO pages

- Rebuild /macon with cert badge popups, before/after slider, intelligent
  form with urgency detection
- Rebuild /paysagiste with filterable gallery, seasonal banner, WhatsApp
  floating button, devis form
- Rebuild /plombier with sticky call bar, 3-step diagnostic wizard,
  transparent tariffs, zone map
- Add MagicReveal component (interactive before/after slider)
- Update Navbar with real phone number (06 04 40 81 57)
- Update DemosLive cards with new titles and subtitles
- Create sitemap.ts targeting local SEO zones (Douai, Orchies,
  Valenciennes, Saint-Amand, Arleux, Denain)
- Create LocalSeoPage template + 6 city-specific landing pages

https://claude.ai/code/session_01H2aRGDaKgarPvhay2HxN6Y
This commit is contained in:
Claude
2026-02-15 22:10:14 +00:00
parent a845b47316
commit 9025986e66
17 changed files with 1331 additions and 259 deletions

View File

@@ -0,0 +1,105 @@
"use client";
import { useState } from "react";
interface Realisation {
titre: string;
type: string;
lieu: string;
saison: string;
}
interface PaysagisteClientProps {
realisations?: Realisation[];
whatsapp?: boolean;
}
export default function PaysagisteClient({ realisations, whatsapp }: PaysagisteClientProps) {
if (whatsapp) {
return <WhatsAppButton />;
}
if (realisations) {
return <GalerieFiltrable realisations={realisations} />;
}
return null;
}
function WhatsAppButton() {
return (
<a
href="https://wa.me/33604408157?text=Bonjour%2C%20je%20souhaite%20un%20devis%20pour%20mon%20jardin"
target="_blank"
rel="noopener noreferrer"
className="fixed bottom-6 right-6 z-50 bg-[#25D366] hover:bg-[#1fb855] text-white rounded-full p-4 shadow-lg hover:shadow-xl transition-all group"
aria-label="Contacter sur WhatsApp"
>
<svg className="w-7 h-7" fill="currentColor" viewBox="0 0 24 24">
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" />
</svg>
<span className="absolute -top-2 -left-2 bg-white text-gray-800 text-[10px] font-bold px-2 py-0.5 rounded-full shadow-md opacity-0 group-hover:opacity-100 transition-opacity whitespace-nowrap">
Je veux le m\u00eame jardin !
</span>
</a>
);
}
function GalerieFiltrable({ realisations }: { realisations: Realisation[] }) {
const [filter, setFilter] = useState("Tous");
const types = ["Tous", "Terrasses", "Plantations", "All\u00e9es", "Entretien"];
const filtered = filter === "Tous" ? realisations : realisations.filter((r) => r.type === filter);
return (
<>
{/* Filtres */}
<div className="flex flex-wrap justify-center gap-2 mb-8">
{types.map((t) => (
<button
key={t}
onClick={() => setFilter(t)}
className={`px-4 py-2 text-sm font-semibold rounded-full transition-colors cursor-pointer ${
filter === t
? "bg-green-600 text-white"
: "bg-gray-100 text-gray-500 hover:bg-gray-200"
}`}
>
{t}
</button>
))}
</div>
{/* Grille */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
{filtered.map((r, i) => (
<div key={i} className="bg-[#f0f5ed] border border-gray-100 rounded-2xl overflow-hidden group hover:shadow-lg transition-shadow">
<div className="h-48 bg-gradient-to-br from-green-100 to-green-50 flex items-center justify-center relative overflow-hidden">
<div className="text-center">
<svg className="w-12 h-12 text-green-300 mx-auto mb-2 group-hover:scale-110 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1} d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" />
</svg>
<p className="text-gray-400 text-xs">Photo HD du projet</p>
</div>
{/* Tag type */}
<span className={`absolute top-3 left-3 text-[10px] font-bold px-2 py-0.5 rounded-full ${
r.type === "Entretien" ? "bg-amber-100 text-amber-700" : "bg-green-100 text-green-700"
}`}>
{r.type}
</span>
</div>
<div className="p-4">
<h3 className="text-gray-800 font-bold text-sm mb-1">{r.titre}</h3>
<p className="text-gray-400 text-xs flex items-center gap-1">
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
</svg>
{r.lieu}
</p>
</div>
</div>
))}
</div>
</>
);
}

View File

@@ -1,129 +1,187 @@
import type { Metadata } from "next";
import Link from "next/link";
import Button from "@/components/ui/Button";
import PaysagisteClient from "./PaysagisteClient";
export const metadata: Metadata = {
title: "D\u00e9mo Site Paysagiste / Peintre - Pack Esth\u00e9tique",
title: "D\u00e9mo Site Paysagiste / Peintre - L'Artisan Cr\u00e9ateur | HookLab",
description:
"D\u00e9couvrez le mod\u00e8le de site HookLab pour paysagistes et peintres. Design \u00e9pur\u00e9, galerie photo immersive, filtrage Cr\u00e9ation vs Entretien.",
"Mod\u00e8le de site HookLab pour paysagistes, peintres et d\u00e9corateurs. Galerie filtrable, saisonnalit\u00e9 intelligente, bouton WhatsApp flottant.",
};
const realisations = [
{ titre: "Jardin contemporain", type: "Cr\u00e9ation", lieu: "Douai" },
{ titre: "Terrasse bois & pergola", type: "Cr\u00e9ation", lieu: "Orchies" },
{ titre: "Entretien parc 2000m\u00b2", type: "Entretien", lieu: "Valenciennes" },
{ titre: "Am\u00e9nagement piscine", type: "Cr\u00e9ation", lieu: "Arleux" },
{ titre: "Taille de haies & \u00e9lagage", type: "Entretien", lieu: "Flines-lez-Raches" },
{ titre: "Jardin japonais", type: "Cr\u00e9ation", lieu: "Saint-Amand" },
{ titre: "Jardin contemporain avec terrasse composite", type: "Terrasses", lieu: "Orchies", saison: "printemps" },
{ titre: "Am\u00e9nagement complet piscine + cl\u00f4ture", type: "Terrasses", lieu: "Douai", saison: "printemps" },
{ titre: "Cr\u00e9ation massif fleuri 4 saisons", type: "Plantations", lieu: "Valenciennes", saison: "printemps" },
{ titre: "Haie brise-vue naturelle en bambou", type: "Plantations", lieu: "Arleux", saison: "automne" },
{ titre: "All\u00e9e carrossable en pav\u00e9s anciens", type: "All\u00e9es", lieu: "Saint-Amand", saison: "automne" },
{ titre: "Jardin japonais zen avec bassin", type: "Plantations", lieu: "Flines-lez-Raches", saison: "printemps" },
{ titre: "Taille architecturale haies buis", type: "Entretien", lieu: "Denain", saison: "automne" },
{ titre: "Entretien annuel parc 3000m\u00b2", type: "Entretien", lieu: "Douai", saison: "automne" },
];
export default function PaysagisteDemo() {
const currentMonth = new Date().getMonth();
const isSpringSummer = currentMonth >= 2 && currentMonth <= 8;
return (
<main className="min-h-screen bg-bg">
{/* Nav simplifi\u00e9e */}
<nav className="sticky top-0 z-50 bg-bg-white/90 backdrop-blur-md border-b border-border">
<main className="min-h-screen bg-white">
{/* Nav \u00e9pur\u00e9e */}
<nav className="sticky top-0 z-50 bg-white/90 backdrop-blur-md border-b border-gray-100">
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 flex items-center justify-between h-16">
<div className="flex items-center gap-3">
<Link href="/" className="text-text-muted hover:text-navy text-sm transition-colors">
&larr; Retour HookLab
<Link href="/" className="text-gray-400 hover:text-gray-700 text-sm transition-colors">
&larr; HookLab
</Link>
<span className="text-border">|</span>
<span className="text-navy font-bold text-sm">
D\u00e9mo : <span className="text-orange">Pack Esth\u00e9tique</span>
<span className="text-gray-200">|</span>
<span className="text-gray-800 font-bold text-sm">
[Votre Entreprise] &mdash; <span className="text-green-600">Paysagiste</span>
</span>
</div>
<a
href="tel:+33600000000"
className="bg-orange hover:bg-orange/90 text-white font-bold text-sm px-4 py-2 rounded-lg transition-colors"
href="tel:+33604408157"
className="bg-green-600 hover:bg-green-700 text-white font-bold text-sm px-5 py-2 rounded-lg transition-colors"
>
Devis Gratuit
</a>
</div>
</nav>
{/* Banni\u00e8re saisonni\u00e8re */}
<div className={`text-center py-2 text-xs font-semibold ${isSpringSummer ? "bg-green-50 text-green-700" : "bg-amber-50 text-amber-700"}`}>
{isSpringSummer
? "C\u2019est la saison ! Cr\u00e9ation de terrasses & plantations \u2014 Demandez votre devis maintenant"
: "Pr\u00e9parez le printemps ! Taille, \u00e9lagage & entretien d\u2019automne \u2014 Planifiez vos travaux"
}
</div>
{/* Hero \u00e9pur\u00e9 */}
<section className="py-24 md:py-36 bg-[#1a2e1a] text-center relative overflow-hidden">
<div className="absolute inset-0 bg-[radial-gradient(circle_at_50%_80%,rgba(34,139,34,0.15),transparent_70%)]" />
<section className="py-24 md:py-36 bg-[#f0f5ed] text-center relative overflow-hidden">
<div className="absolute inset-0 bg-[radial-gradient(circle_at_50%_80%,rgba(34,139,34,0.08),transparent_70%)]" />
<div className="relative max-w-4xl mx-auto px-4">
<span className="inline-block px-3 py-1.5 bg-green-500/20 border border-green-500/30 rounded-full text-green-400 text-xs font-semibold mb-6">
Paysagisme & Espaces Verts
<span className="inline-block px-3 py-1.5 bg-green-100 border border-green-200 rounded-full text-green-700 text-xs font-semibold mb-6">
Paysagisme &middot; Espaces Verts &middot; D\u00e9coration
</span>
<h1 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-white leading-tight mb-6">
[Votre Entreprise] &mdash; Paysagiste <span className="text-green-400">dans le Nord</span>
<h1 className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-gray-900 leading-tight mb-4">
Ne vendez pas des travaux,{" "}
<span className="text-green-600">vendez du r\u00eave.</span>
</h1>
<p className="text-white/60 text-lg max-w-2xl mx-auto mb-8">
Cr\u00e9ation de jardins d&rsquo;exception et entretien d&rsquo;espaces verts.
La nature est notre m\u00e9tier, la beaut\u00e9 notre signature.
<p className="text-gray-500 text-lg max-w-2xl mx-auto mb-4">
Pour un jardin ou un int\u00e9rieur, votre client n&rsquo;ach\u00e8te pas de la technique,
il ach\u00e8te une &laquo;&nbsp;ambiance&nbsp;&raquo;. Ce site est votre galerie d&rsquo;art.
</p>
<p className="text-gray-400 text-sm mb-8">
Cr\u00e9ations &agrave; Douai, Orchies, Valenciennes, Saint-Amand et environs.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Button size="lg" className="bg-green-600 hover:bg-green-700 border-green-600">
Demander un Devis Cr\u00e9ation
</Button>
<Button size="lg" variant="outline" className="border-white/30 text-white hover:bg-white/10">
Devis Entretien
</Button>
<a href="#devis">
<Button size="lg" className="bg-green-600 hover:bg-green-700 border-green-600">
Demander un Devis Cr\u00e9ation
</Button>
</a>
<a href="#devis">
<Button size="lg" variant="outline" className="border-green-300 text-green-700 hover:bg-green-50">
Devis Entretien
</Button>
</a>
</div>
</div>
</section>
{/* R\u00e9alisations avec filtrage */}
<section className="py-16 md:py-24 bg-bg-white">
{/* R\u00e9alisations filtrables */}
<section className="py-16 md:py-24 bg-white">
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h2 className="text-2xl md:text-3xl font-bold text-navy mb-3">
Nos <span className="text-orange">r\u00e9alisations</span>
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 mb-3">
Nos <span className="text-green-600">r\u00e9alisations</span>
</h2>
<p className="text-text-light mb-6">
Filtrez par type de projet pour trouver l&rsquo;inspiration.
<p className="text-gray-500 mb-2">
Des cr\u00e9ations dans des lieux que vous connaissez. Projetez-vous.
</p>
{/* Filtre visuel (d\u00e9mo statique) */}
<div className="flex justify-center gap-3">
<span className="px-4 py-2 bg-navy text-white text-sm font-semibold rounded-full">Tous</span>
<span className="px-4 py-2 bg-bg border border-border text-text-light text-sm rounded-full cursor-pointer hover:border-navy transition-colors">Cr\u00e9ation</span>
<span className="px-4 py-2 bg-bg border border-border text-text-light text-sm rounded-full cursor-pointer hover:border-navy transition-colors">Entretien</span>
</div>
</div>
<PaysagisteClient realisations={realisations} />
</div>
</section>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{realisations.map((r, i) => (
<div key={i} className="bg-bg border border-border rounded-2xl overflow-hidden group">
<div className="h-48 bg-green-50 flex items-center justify-center">
<div className="text-center">
<svg className="w-12 h-12 text-green-300 mx-auto mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1} d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" />
</svg>
<p className="text-text-muted text-xs">Photo du projet</p>
</div>
</div>
<div className="p-4">
<div className="flex items-center justify-between mb-2">
<h3 className="text-navy font-bold text-sm">{r.titre}</h3>
<span className={`text-xs font-semibold px-2 py-0.5 rounded-full ${
r.type === "Cr\u00e9ation" ? "bg-green-100 text-green-700" : "bg-blue-100 text-blue-700"
}`}>
{r.type}
</span>
</div>
<p className="text-text-muted text-xs">{r.lieu}</p>
{/* Immersion locale */}
<section className="py-16 md:py-24 bg-[#f0f5ed]">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 mb-10">
Des jardins pr\u00e8s de <span className="text-green-600">chez vous</span>
</h2>
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
{["Douai", "Orchies", "Valenciennes", "Arleux", "Saint-Amand", "Denain"].map((ville) => (
<div key={ville} className="bg-white rounded-xl p-4 border border-gray-100 hover:shadow-md transition-shadow">
<div className="w-10 h-10 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-2">
<svg className="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</div>
<p className="text-gray-800 font-semibold text-sm">Jardin \u00e0 {ville}</p>
</div>
))}
</div>
</div>
</section>
{/* CTA */}
<section className="py-16 bg-[#1a2e1a] text-center">
{/* Formulaire */}
<section id="devis" className="py-16 md:py-24 bg-gray-900">
<div className="max-w-2xl mx-auto px-4">
<p className="text-orange text-xs font-semibold uppercase tracking-wider mb-3">Ceci est une d\u00e9mo HookLab</p>
<div className="text-center mb-10">
<h2 className="text-2xl md:text-3xl font-bold text-white mb-3">
Demander un <span className="text-green-400">devis gratuit</span>
</h2>
<p className="text-white/60">D\u00e9crivez votre projet, on vous recontacte sous 24h.</p>
</div>
<div className="bg-white rounded-2xl p-6 sm:p-8">
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1.5">Type de projet</label>
<select className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl text-gray-800 text-sm focus:border-green-500 focus:ring-1 focus:ring-green-500 outline-none">
<option>Cr\u00e9ation de jardin complet</option>
<option>Terrasse / Am\u00e9nagement</option>
<option>Plantation / Massifs</option>
<option>Entretien r\u00e9gulier</option>
<option>Taille / \u00c9lagage</option>
<option>Cl\u00f4ture / Brise-vue</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1.5">Votre nom</label>
<input type="text" placeholder="Votre nom" className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl text-gray-800 text-sm placeholder:text-gray-400 focus:border-green-500 focus:ring-1 focus:ring-green-500 outline-none" />
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1.5">T\u00e9l\u00e9phone</label>
<input type="tel" placeholder="06 12 34 56 78" className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl text-gray-800 text-sm placeholder:text-gray-400 focus:border-green-500 focus:ring-1 focus:ring-green-500 outline-none" />
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1.5">D\u00e9crivez votre projet</label>
<textarea rows={3} placeholder="Surface, style souhait\u00e9, budget approximatif..." className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-xl text-gray-800 text-sm placeholder:text-gray-400 focus:border-green-500 focus:ring-1 focus:ring-green-500 outline-none resize-none" />
</div>
<Button size="lg" className="w-full bg-green-600 hover:bg-green-700 border-green-600">
Envoyer ma demande
</Button>
</div>
</div>
</div>
</section>
{/* WhatsApp flottant */}
<PaysagisteClient whatsapp />
{/* CTA HookLab */}
<section className="py-16 bg-green-600 text-center">
<div className="max-w-2xl mx-auto px-4">
<p className="text-white/80 text-xs font-semibold uppercase tracking-wider mb-3">Ceci est une d\u00e9mo HookLab</p>
<h2 className="text-2xl md:text-3xl font-bold text-white mb-4">
Ce design vous pla\u00eet&nbsp;? Il peut &ecirc;tre &agrave; vous.
Ce design vous pla\u00eet ? Il peut \u00eatre \u00e0 vous.
</h2>
<p className="text-white/60 mb-6">
<p className="text-white/80 mb-6">
Imaginez vos plus beaux jardins mis en valeur comme \u00e7a. C&rsquo;est ce que je cr\u00e9e pour les paysagistes du Nord.
</p>
<Link href="/#contact">
<Button size="lg" className="bg-green-600 hover:bg-green-700 border-green-600">
<Button size="lg" className="bg-gray-900 hover:bg-gray-800 border-gray-900">
Demander Mon Audit Gratuit
</Button>
</Link>