feat: préparation Payload CMS — couche d'abstraction contenu
Sépare données et affichage pour basculer vers Payload CMS sans réécrire les composants. Nouveaux fichiers : - lib/site-config.ts : source unique de vérité pour toutes les données du site (as const) - lib/content.ts : couche async entre données et composants (static aujourd'hui, Payload demain) - types/content.ts : types TypeScript partagés (Service, Realisation, Partner, BlogPost, etc.) - payload/ : schémas CollectionConfig et GlobalConfig commentés prêts à activer Données enrichies dans siteConfig : - partners : ajout du champ desc pour chaque partenaire - realisations : 6 entrées complètes avec categorie et color - blogPosts : 6 articles avec slug, titre, extrait, cat, date, readTime Refactorisations (composants → content layer) : - Navbar, Footer : importent siteConfig directement (client component) - app/page.tsx : async, Promise.all sur getServices/getTestimonials/getFAQ/getValues/getPartners/getRealisations - app/services/page.tsx : getServices() + getSiteConfig() - app/contact/page.tsx : getSiteConfig() pour phone, email, address, zones - app/realisations/page.tsx : getRealisations() + getSiteConfig() - app/partenaires/page.tsx : getPartners() - app/blog/page.tsx : getBlogPosts() - app/blog/[slug]/page.tsx : getBlogPost() + getBlogPosts() pour generateStaticParams - LocalSEOPage.tsx : siteConfig pour services list, phone, address - 5 pages service (construction-maison, renovation, assainissement, creation-acces, demolition) : getSiteConfig() pour phone - Pages légales et SEO locales : siteConfig importé pour données dynamiques Corrections URL : - Toutes les URLs canoniques obc-maconnerie.fr → obc-terrassement.fr (30+ fichiers) - layout.tsx : BASE_URL depuis siteConfig.url - robots.ts, sitemap.ts : BASE_URL depuis siteConfig.url - api/contact/route.ts : email fallback → obc-terrassement.fr https://claude.ai/code/session_01Uec4iHjcPwB1pU41idWEdF
This commit is contained in:
@@ -31,8 +31,8 @@ export async function POST(request: Request) {
|
|||||||
const { Resend } = await import("resend");
|
const { Resend } = await import("resend");
|
||||||
const resend = new Resend(process.env.RESEND_API_KEY);
|
const resend = new Resend(process.env.RESEND_API_KEY);
|
||||||
|
|
||||||
const fromEmail = process.env.RESEND_FROM_EMAIL || "OBC Maçonnerie <contact@obc-maconnerie.fr>";
|
const fromEmail = process.env.RESEND_FROM_EMAIL || "OBC Maçonnerie <contact@obc-terrassement.fr>";
|
||||||
const adminEmail = process.env.ADMIN_EMAIL || "contact@obc-maconnerie.fr";
|
const adminEmail = process.env.ADMIN_EMAIL || "contact@obc-terrassement.fr";
|
||||||
|
|
||||||
await resend.emails.send({
|
await resend.emails.send({
|
||||||
from: fromEmail,
|
from: fromEmail,
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import Navbar from "@/components/marketing/Navbar";
|
|||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
import ScrollReveal from "@/components/animations/ScrollReveal";
|
import ScrollReveal from "@/components/animations/ScrollReveal";
|
||||||
import ContactForm from "@/components/marketing/ContactForm";
|
import ContactForm from "@/components/marketing/ContactForm";
|
||||||
|
import { getSiteConfig } from "@/lib/content";
|
||||||
|
|
||||||
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
|
const config = await getSiteConfig();
|
||||||
|
return {
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: "Assainissement Maison Nord 59 | OBC Maçonnerie",
|
title: "Assainissement Maison Nord 59 | OBC Maçonnerie",
|
||||||
description:
|
description:
|
||||||
"Création et mise aux normes de systèmes d'assainissement dans le Nord (59). OBC Maçonnerie intervient à Orchies, Douai, Valenciennes et alentours. Devis gratuit.",
|
"Création et mise aux normes de systèmes d'assainissement dans le Nord (59). OBC Maçonnerie intervient à Orchies, Douai, Valenciennes et alentours. Devis gratuit.",
|
||||||
@@ -17,8 +21,9 @@ export const metadata: Metadata = {
|
|||||||
"assainissement Orchies",
|
"assainissement Orchies",
|
||||||
"assainissement Douai",
|
"assainissement Douai",
|
||||||
],
|
],
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/assainissement" },
|
alternates: { canonical: `${config.url}/assainissement` },
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const prestations = [
|
const prestations = [
|
||||||
{ icon: "🔍", title: "Diagnostic", desc: "Analyse de votre installation existante et vérification de sa conformité aux normes en vigueur." },
|
{ icon: "🔍", title: "Diagnostic", desc: "Analyse de votre installation existante et vérification de sa conformité aux normes en vigueur." },
|
||||||
@@ -29,7 +34,9 @@ const prestations = [
|
|||||||
{ icon: "💧", title: "Raccordement réseau", desc: "Connexion au réseau d'assainissement collectif lorsque celui-ci est disponible." },
|
{ icon: "💧", title: "Raccordement réseau", desc: "Connexion au réseau d'assainissement collectif lorsque celui-ci est disponible." },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function AssainissementPage() {
|
export default async function AssainissementPage() {
|
||||||
|
const config = await getSiteConfig();
|
||||||
|
const { phone, phoneRaw } = config;
|
||||||
return (
|
return (
|
||||||
<main id="main-content" className="min-h-screen">
|
<main id="main-content" className="min-h-screen">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
@@ -55,9 +62,7 @@ export default function AssainissementPage() {
|
|||||||
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors pulse-glow">
|
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors pulse-glow">
|
||||||
Demander un devis gratuit
|
Demander un devis gratuit
|
||||||
</Link>
|
</Link>
|
||||||
<a href="tel:0674453089" className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-7 py-3.5 rounded-xl transition-colors border border-white/20">
|
<a href={`tel:${phoneRaw}`} className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-7 py-3.5 rounded-xl transition-colors border border-white/20">{phone}</a>
|
||||||
06 74 45 30 89
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,137 +4,85 @@ import { notFound } from "next/navigation";
|
|||||||
import Navbar from "@/components/marketing/Navbar";
|
import Navbar from "@/components/marketing/Navbar";
|
||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
import ScrollReveal from "@/components/animations/ScrollReveal";
|
import ScrollReveal from "@/components/animations/ScrollReveal";
|
||||||
|
import { getBlogPost, getBlogPosts, getSiteConfig } from "@/lib/content";
|
||||||
|
|
||||||
type Props = { params: Promise<{ slug: string }> };
|
type Props = { params: Promise<{ slug: string }> };
|
||||||
|
|
||||||
const articles: Record<
|
// Corps des articles — FUTURE: champ rich text Payload CMS
|
||||||
string,
|
const articleContenu: Record<string, string[]> = {
|
||||||
{
|
"combien-coute-construction-maison-nord": [
|
||||||
titre: string;
|
"La construction d'une maison individuelle dans le Nord représente un investissement significatif. En 2025, le coût moyen se situe entre 1 200 € et 1 800 € par m² hors terrain et hors raccordements, selon les matériaux choisis et la complexité du projet.",
|
||||||
description: string;
|
"**Le prix du terrain** est souvent la première variable. Dans le secteur d'Orchies et de Mouchin, comptez entre 50 000 € et 120 000 € pour une parcelle constructible de 400 à 600 m².",
|
||||||
cat: string;
|
"**Le gros œuvre** (fondations, murs, dalle, toiture) représente environ 40 à 50% du budget total. C'est là qu'intervient OBC Maçonnerie avec son savoir-faire et son réseau de partenaires pour optimiser les coûts sans sacrifier la qualité.",
|
||||||
date: string;
|
"**Les finitions et corps de métier** (électricité, plomberie, chauffage, isolation, menuiserie, carrelage, peinture) représentent les 50 à 60% restants.",
|
||||||
readTime: string;
|
"Pour un projet de 100 m² habitable à Orchies ou Douai, un budget total entre 180 000 € et 280 000 € (hors terrain) est réaliste selon le niveau de finition souhaité.",
|
||||||
contenu: string[];
|
"Le meilleur conseil : contactez Benoît Colin pour une évaluation gratuite de votre projet. Il vous donnera une estimation précise adaptée à votre terrain et vos envies.",
|
||||||
}
|
],
|
||||||
> = {
|
"etapes-renovation-maison-ancienne": [
|
||||||
"combien-coute-construction-maison-nord": {
|
"Rénover une maison ancienne dans le Nord demande une méthodologie rigoureuse. Voici les grandes étapes pour mener votre projet à bien.",
|
||||||
titre: "Combien coûte la construction d'une maison dans le Nord en 2025 ?",
|
"**1. Le diagnostic** : Avant tout, il faut évaluer l'état du bâtiment. Charpente, toiture, murs porteurs, fondations, réseaux électriques et plomberie — tout doit être passé en revue. Un maçon expérimenté comme Benoît Colin peut repérer les problèmes invisibles à l'œil nu.",
|
||||||
description:
|
"**2. La démolition et le curage** : On enlève ce qui est vétuste ou inadapté — cloisons obsolètes, chapes abîmées, enduits défaillants — pour repartir sur de bonnes bases.",
|
||||||
"Budget, matériaux, terrain, main-d'œuvre — tout ce qu'il faut savoir pour estimer le coût de votre construction neuve dans le Nord.",
|
"**3. Le gros œuvre** : Reprises de fondations si nécessaire, traitement des murs humides, création d'ouvertures, modification de la structure. C'est le cœur du métier d'OBC Maçonnerie.",
|
||||||
cat: "Construction",
|
"**4. Les corps de métier** : Électricité, plomberie, chauffage, isolation. Grâce à son réseau de partenaires, Benoît coordonne chaque intervention dans le bon ordre.",
|
||||||
date: "15 février 2025",
|
"**5. Les finitions** : Menuiseries, carrelage, peinture, revêtements de sol. La touche finale qui donne tout son caractère à votre maison rénovée.",
|
||||||
readTime: "6 min",
|
"Chaque rénovation est unique. Contactez OBC Maçonnerie pour une évaluation gratuite de votre projet.",
|
||||||
contenu: [
|
],
|
||||||
"La construction d'une maison individuelle dans le Nord représente un investissement significatif. En 2025, le coût moyen se situe entre 1 200 € et 1 800 € par m² hors terrain et hors raccordements, selon les matériaux choisis et la complexité du projet.",
|
"assainissement-non-collectif-obligations": [
|
||||||
"**Le prix du terrain** est souvent la première variable. Dans le secteur d'Orchies et de Mouchin, comptez entre 50 000 € et 120 000 € pour une parcelle constructible de 400 à 600 m².",
|
"En France, environ 5 millions de logements sont équipés d'un assainissement non collectif (ANC). Si votre maison n'est pas raccordée au réseau public, vous êtes soumis à des obligations précises.",
|
||||||
"**Le gros œuvre** (fondations, murs, dalle, toiture) représente environ 40 à 50% du budget total. C'est là qu'intervient OBC Maçonnerie avec son savoir-faire et son réseau de partenaires pour optimiser les coûts sans sacrifier la qualité.",
|
"**Le contrôle SPANC** : Le Service Public d'Assainissement Non Collectif peut contrôler votre installation. En cas de non-conformité, vous avez en principe 4 ans pour mettre aux normes, ou moins si vous vendez le bien.",
|
||||||
"**Les finitions et corps de métier** (électricité, plomberie, chauffage, isolation, menuiserie, carrelage, peinture) représentent les 50 à 60% restants.",
|
"**La vente immobilière** : Depuis 2011, un diagnostic d'assainissement est obligatoire lors de toute vente. S'il révèle une non-conformité, l'acheteur doit réaliser les travaux dans l'année suivant l'acte de vente.",
|
||||||
"Pour un projet de 100 m² habitable à Orchies ou Douai, un budget total entre 180 000 € et 280 000 € (hors terrain) est réaliste selon le niveau de finition souhaité.",
|
"**Les principales normes** : Votre installation doit traiter correctement les eaux usées avant rejet dans le sol. Les normes imposent une fosse toutes eaux (ou une micro-station) et un dispositif d'épandage adapté à la surface disponible.",
|
||||||
"Le meilleur conseil : contactez Benoît Colin pour une évaluation gratuite de votre projet. Il vous donnera une estimation précise adaptée à votre terrain et vos envies.",
|
"**OBC Maçonnerie vous accompagne** dans la mise aux normes ou la création de votre système d'assainissement non collectif. Nous intervenons sur Orchies, Douai, Valenciennes et toute la zone.",
|
||||||
],
|
],
|
||||||
},
|
"ossature-bois-avantages": [
|
||||||
"etapes-renovation-maison-ancienne": {
|
"La construction en ossature bois connaît un vrai succès dans le Nord. Et pour cause : ce mode constructif présente de nombreux avantages techniques et économiques.",
|
||||||
titre: "Les étapes clés d'une rénovation de maison ancienne",
|
"**Performance thermique** : Le bois est un excellent isolant naturel. Une construction ossature bois bien conçue atteint facilement les exigences RE2020.",
|
||||||
description:
|
"**Rapidité de chantier** : Les éléments préfabriqués permettent de monter les murs en quelques jours. Le clos-couvert est obtenu très rapidement.",
|
||||||
"Vous avez acheté une maison ancienne dans le Nord et vous voulez la rénover ? Voici les étapes indispensables pour réussir votre projet.",
|
"**Légèreté** : L'ossature bois pèse 5 à 8 fois moins qu'une construction maçonnée, ce qui allège les fondations — un avantage sur les terrains argileux fréquents dans le Nord.",
|
||||||
cat: "Rénovation",
|
"**Polyvalence architecturale** : L'ossature bois permet des formes architecturales variées, des larges baies vitrées et une grande liberté de conception.",
|
||||||
date: "8 janvier 2025",
|
"**La combinaison idéale** : OBC Maçonnerie maîtrise la construction ossature bois et la maçonnerie traditionnelle. Benoît vous conseille sur la solution la plus adaptée à votre terrain et vos envies.",
|
||||||
readTime: "5 min",
|
],
|
||||||
contenu: [
|
"travaux-renovation-sans-permis-construction": [
|
||||||
"Rénover une maison ancienne dans le Nord demande une méthodologie rigoureuse. Voici les grandes étapes pour mener votre projet à bien.",
|
"Avant de démarrer des travaux de rénovation, il est important de savoir si vous avez besoin d'une autorisation administrative.",
|
||||||
"**1. Le diagnostic** : Avant tout, il faut évaluer l'état du bâtiment. Charpente, toiture, murs porteurs, fondations, réseaux électriques et plomberie — tout doit être passé en revue. Un maçon expérimenté comme Benoît Colin peut repérer les problèmes invisibles à l'œil nu.",
|
"**Aucune démarche requise** : Les travaux purement intérieurs (peinture, revêtements, redistribution de cloisons non porteuses, remplacement de fenêtres à l'identique) ne nécessitent généralement aucune démarche.",
|
||||||
"**2. La démolition et le curage** : On enlève ce qui est vétuste ou inadapté — cloisons obsolètes, chapes abîmées, enduits défaillants — pour repartir sur de bonnes bases.",
|
"**Déclaration préalable** : Pour les extensions jusqu'à 40 m² (en zone urbaine PLU), les changements de façade, les travaux modifiant l'aspect extérieur.",
|
||||||
"**3. Le gros œuvre** : Reprises de fondations si nécessaire, traitement des murs humides, création d'ouvertures, modification de la structure. C'est le cœur du métier d'OBC Maçonnerie.",
|
"**Permis de construire** : Obligatoire pour les extensions de plus de 40 m², la création d'une surface de plancher supérieure à 20 m² en dehors des zones PLU, ou les changements de destination.",
|
||||||
"**4. Les corps de métier** : Électricité, plomberie, chauffage, isolation. Grâce à son réseau de partenaires, Benoît coordonne chaque intervention dans le bon ordre.",
|
"**Cas des zones protégées** : Si votre maison est en zone ABF (Architecte des Bâtiments de France), les règles sont plus strictes. Renseignez-vous en mairie.",
|
||||||
"**5. Les finitions** : Menuiseries, carrelage, peinture, revêtements de sol. La touche finale qui donne tout son caractère à votre maison rénovée.",
|
"En cas de doute, OBC Maçonnerie vous accompagne dans vos démarches administratives. Benoît connaît bien les règles locales dans le secteur d'Orchies, Douai et Valenciennes.",
|
||||||
"Chaque rénovation est unique. Contactez OBC Maçonnerie pour une évaluation gratuite de votre projet.",
|
],
|
||||||
],
|
"fondations-maison-quels-types": [
|
||||||
},
|
"Les fondations sont la base de toute construction. Mal dimensionnées ou inadaptées au sol, elles peuvent entraîner des désordres graves. Voici les principaux types.",
|
||||||
"assainissement-non-collectif-obligations": {
|
"**Les semelles filantes** : Le type le plus courant pour les maisons individuelles. Elles répartissent les charges des murs porteurs sur une bande de terrain. Adaptées aux sols stables et homogènes.",
|
||||||
titre: "Assainissement non collectif : vos obligations légales",
|
"**Le radier** : Une dalle béton armé qui couvre toute la surface de la maison. Recommandé sur les terrains argileux, instables ou avec présence d'eau. Fréquent dans certains secteurs du Nord.",
|
||||||
description:
|
"**Les pieux** : Utilisés quand le sol de surface est insuffisant pour porter la maison. Des pieux sont enfoncés jusqu'à une couche de sol plus résistante.",
|
||||||
"Contrôle SPANC, mise aux normes, vente immobilière — tout ce que vous devez savoir sur l'assainissement non collectif.",
|
"**L'étude de sol** : Avant toute construction, une étude géotechnique (étude de sol) est vivement recommandée — et même obligatoire dans certains cas (zones argileuses). Elle permet de choisir le bon type de fondations.",
|
||||||
cat: "Assainissement",
|
"OBC Maçonnerie réalise vos fondations avec rigueur, après analyse du terrain. Benoît vous conseille sur la solution la plus adaptée à votre projet dans le Nord.",
|
||||||
date: "20 décembre 2024",
|
],
|
||||||
readTime: "4 min",
|
|
||||||
contenu: [
|
|
||||||
"En France, environ 5 millions de logements sont équipés d'un assainissement non collectif (ANC). Si votre maison n'est pas raccordée au réseau public, vous êtes soumis à des obligations précises.",
|
|
||||||
"**Le contrôle SPANC** : Le Service Public d'Assainissement Non Collectif peut contrôler votre installation. En cas de non-conformité, vous avez en principe 4 ans pour mettre aux normes, ou moins si vous vendez le bien.",
|
|
||||||
"**La vente immobilière** : Depuis 2011, un diagnostic d'assainissement est obligatoire lors de toute vente. S'il révèle une non-conformité, l'acheteur doit réaliser les travaux dans l'année suivant l'acte de vente.",
|
|
||||||
"**Les principales normes** : Votre installation doit traiter correctement les eaux usées avant rejet dans le sol. Les normes imposent une fosse toutes eaux (ou une micro-station) et un dispositif d'épandage adapté à la surface disponible.",
|
|
||||||
"**OBC Maçonnerie vous accompagne** dans la mise aux normes ou la création de votre système d'assainissement non collectif. Nous intervenons sur Orchies, Douai, Valenciennes et toute la zone.",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"ossature-bois-avantages": {
|
|
||||||
titre: "Ossature bois : pourquoi choisir ce mode constructif ?",
|
|
||||||
description:
|
|
||||||
"Légèreté, performance thermique, rapidité de construction — l'ossature bois a de nombreux avantages. OBC Maçonnerie vous explique.",
|
|
||||||
cat: "Construction",
|
|
||||||
date: "5 novembre 2024",
|
|
||||||
readTime: "5 min",
|
|
||||||
contenu: [
|
|
||||||
"La construction en ossature bois connaît un vrai succès dans le Nord. Et pour cause : ce mode constructif présente de nombreux avantages techniques et économiques.",
|
|
||||||
"**Performance thermique** : Le bois est un excellent isolant naturel. Une construction ossature bois bien conçue atteint facilement les exigences RE2020.",
|
|
||||||
"**Rapidité de chantier** : Les éléments préfabriqués permettent de monter les murs en quelques jours. Le clos-couvert est obtenu très rapidement.",
|
|
||||||
"**Légèreté** : L'ossature bois pèse 5 à 8 fois moins qu'une construction maçonnée, ce qui allège les fondations — un avantage sur les terrains argileux fréquents dans le Nord.",
|
|
||||||
"**Polyvalence architecturale** : L'ossature bois permet des formes architecturales variées, des larges baies vitrées et une grande liberté de conception.",
|
|
||||||
"**La combinaison idéale** : OBC Maçonnerie maîtrise la construction ossature bois et la maçonnerie traditionnelle. Benoît vous conseille sur la solution la plus adaptée à votre terrain et vos envies.",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"travaux-renovation-sans-permis-construction": {
|
|
||||||
titre: "Quels travaux de rénovation ne nécessitent pas de permis ?",
|
|
||||||
description:
|
|
||||||
"Permis de construire, déclaration préalable, simple déclaration — on vous explique les règles selon la nature de vos travaux.",
|
|
||||||
cat: "Rénovation",
|
|
||||||
date: "18 octobre 2024",
|
|
||||||
readTime: "4 min",
|
|
||||||
contenu: [
|
|
||||||
"Avant de démarrer des travaux de rénovation, il est important de savoir si vous avez besoin d'une autorisation administrative.",
|
|
||||||
"**Aucune démarche requise** : Les travaux purement intérieurs (peinture, revêtements, redistribution de cloisons non porteuses, remplacement de fenêtres à l'identique) ne nécessitent généralement aucune démarche.",
|
|
||||||
"**Déclaration préalable** : Pour les extensions jusqu'à 40 m² (en zone urbaine PLU), les changements de façade, les travaux modifiant l'aspect extérieur.",
|
|
||||||
"**Permis de construire** : Obligatoire pour les extensions de plus de 40 m², la création d'une surface de plancher supérieure à 20 m² en dehors des zones PLU, ou les changements de destination.",
|
|
||||||
"**Cas des zones protégées** : Si votre maison est en zone ABF (Architecte des Bâtiments de France), les règles sont plus strictes. Renseignez-vous en mairie.",
|
|
||||||
"En cas de doute, OBC Maçonnerie vous accompagne dans vos démarches administratives. Benoît connaît bien les règles locales dans le secteur d'Orchies, Douai et Valenciennes.",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"fondations-maison-quels-types": {
|
|
||||||
titre: "Les différents types de fondations pour une maison",
|
|
||||||
description:
|
|
||||||
"Semelles filantes, radier, pieux — quelles fondations choisir selon votre terrain et votre projet de construction ?",
|
|
||||||
cat: "Construction",
|
|
||||||
date: "2 septembre 2024",
|
|
||||||
readTime: "5 min",
|
|
||||||
contenu: [
|
|
||||||
"Les fondations sont la base de toute construction. Mal dimensionnées ou inadaptées au sol, elles peuvent entraîner des désordres graves. Voici les principaux types.",
|
|
||||||
"**Les semelles filantes** : Le type le plus courant pour les maisons individuelles. Elles répartissent les charges des murs porteurs sur une bande de terrain. Adaptées aux sols stables et homogènes.",
|
|
||||||
"**Le radier** : Une dalle béton armé qui couvre toute la surface de la maison. Recommandé sur les terrains argileux, instables ou avec présence d'eau. Fréquent dans certains secteurs du Nord.",
|
|
||||||
"**Les pieux** : Utilisés quand le sol de surface est insuffisant pour porter la maison. Des pieux sont enfoncés jusqu'à une couche de sol plus résistante.",
|
|
||||||
"**L'étude de sol** : Avant toute construction, une étude géotechnique (étude de sol) est vivement recommandée — et même obligatoire dans certains cas (zones argileuses). Elle permet de choisir le bon type de fondations.",
|
|
||||||
"OBC Maçonnerie réalise vos fondations avec rigueur, après analyse du terrain. Benoît vous conseille sur la solution la plus adaptée à votre projet dans le Nord.",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function generateStaticParams() {
|
export async function generateStaticParams() {
|
||||||
return Object.keys(articles).map((slug) => ({ slug }));
|
// FUTURE: utilise getBlogPosts() pour générer les slugs depuis Payload CMS
|
||||||
|
const posts = await getBlogPosts();
|
||||||
|
return posts.map((p) => ({ slug: p.slug }));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||||
const { slug } = await params;
|
const { slug } = await params;
|
||||||
const article = articles[slug];
|
const [post, config] = await Promise.all([getBlogPost(slug), getSiteConfig()]);
|
||||||
if (!article) return { title: "Article introuvable" };
|
if (!post) return { title: "Article introuvable" };
|
||||||
return {
|
return {
|
||||||
title: article.titre,
|
title: post.titre,
|
||||||
description: article.description,
|
description: post.extrait,
|
||||||
alternates: { canonical: `https://obc-maconnerie.fr/blog/${slug}` },
|
alternates: { canonical: `${config.url}/blog/${slug}` },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function BlogArticlePage({ params }: Props) {
|
export default async function BlogArticlePage({ params }: Props) {
|
||||||
const { slug } = await params;
|
const { slug } = await params;
|
||||||
const article = articles[slug];
|
const post = await getBlogPost(slug);
|
||||||
if (!article) notFound();
|
if (!post) notFound();
|
||||||
|
|
||||||
|
const contenu = articleContenu[slug] ?? [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main id="main-content" className="min-h-screen">
|
<main id="main-content" className="min-h-screen">
|
||||||
@@ -151,13 +99,13 @@ export default async function BlogArticlePage({ params }: Props) {
|
|||||||
</Link>
|
</Link>
|
||||||
<div className="flex items-center gap-3 mb-4">
|
<div className="flex items-center gap-3 mb-4">
|
||||||
<span className="bg-orange/20 text-orange text-xs font-semibold px-2.5 py-1 rounded-full">
|
<span className="bg-orange/20 text-orange text-xs font-semibold px-2.5 py-1 rounded-full">
|
||||||
{article.cat}
|
{post.cat}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-white/40 text-xs">{article.date}</span>
|
<span className="text-white/40 text-xs">{post.date}</span>
|
||||||
<span className="text-white/40 text-xs">· {article.readTime} de lecture</span>
|
<span className="text-white/40 text-xs">· {post.readTime} de lecture</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl md:text-4xl font-bold text-white leading-tight">
|
<h1 className="text-2xl md:text-4xl font-bold text-white leading-tight">
|
||||||
{article.titre}
|
{post.titre}
|
||||||
</h1>
|
</h1>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
@@ -178,7 +126,7 @@ export default async function BlogArticlePage({ params }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-5 text-text leading-relaxed">
|
<div className="space-y-5 text-text leading-relaxed">
|
||||||
{article.contenu.map((para, i) => (
|
{contenu.map((para, i) => (
|
||||||
<p key={i} className="text-base text-text-light">
|
<p key={i} className="text-base text-text-light">
|
||||||
{para.split(/(\*\*[^*]+\*\*)/).map((part, j) => {
|
{para.split(/(\*\*[^*]+\*\*)/).map((part, j) => {
|
||||||
if (part.startsWith("**") && part.endsWith("**")) {
|
if (part.startsWith("**") && part.endsWith("**")) {
|
||||||
|
|||||||
@@ -3,74 +3,23 @@ import Link from "next/link";
|
|||||||
import Navbar from "@/components/marketing/Navbar";
|
import Navbar from "@/components/marketing/Navbar";
|
||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
import ScrollReveal from "@/components/animations/ScrollReveal";
|
import ScrollReveal from "@/components/animations/ScrollReveal";
|
||||||
|
import { getBlogPosts, getSiteConfig } from "@/lib/content";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
title: "Blog Maçonnerie & Construction | Conseils OBC Maçonnerie",
|
const config = await getSiteConfig();
|
||||||
description:
|
return {
|
||||||
"Conseils, guides et actualités sur la construction de maison, la rénovation et le gros œuvre dans le Nord (59). Blog OBC Maçonnerie par Benoît Colin.",
|
title: "Blog Maçonnerie & Construction | Conseils OBC Maçonnerie",
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/blog" },
|
description:
|
||||||
};
|
"Conseils, guides et actualités sur la construction de maison, la rénovation et le gros œuvre dans le Nord (59). Blog OBC Maçonnerie par Benoît Colin.",
|
||||||
|
alternates: { canonical: `${config.url}/blog` },
|
||||||
const articles = [
|
};
|
||||||
{
|
}
|
||||||
slug: "combien-coute-construction-maison-nord",
|
|
||||||
titre: "Combien coûte la construction d'une maison dans le Nord en 2025 ?",
|
|
||||||
extrait:
|
|
||||||
"Budget, matériaux, terrain, main-d'œuvre — tout ce qu'il faut savoir pour estimer le coût de votre construction neuve dans le Nord.",
|
|
||||||
cat: "Construction",
|
|
||||||
date: "15 février 2025",
|
|
||||||
readTime: "6 min",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: "etapes-renovation-maison-ancienne",
|
|
||||||
titre: "Les étapes clés d'une rénovation de maison ancienne",
|
|
||||||
extrait:
|
|
||||||
"Vous avez acheté une maison ancienne dans le Nord et vous voulez la rénover ? Voici les étapes indispensables pour réussir votre projet.",
|
|
||||||
cat: "Rénovation",
|
|
||||||
date: "8 janvier 2025",
|
|
||||||
readTime: "5 min",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: "assainissement-non-collectif-obligations",
|
|
||||||
titre: "Assainissement non collectif : vos obligations légales",
|
|
||||||
extrait:
|
|
||||||
"Contrôle SPANC, mise aux normes, vente immobilière — tout ce que vous devez savoir sur l'assainissement non collectif.",
|
|
||||||
cat: "Assainissement",
|
|
||||||
date: "20 décembre 2024",
|
|
||||||
readTime: "4 min",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: "ossature-bois-avantages",
|
|
||||||
titre: "Ossature bois : pourquoi choisir ce mode constructif ?",
|
|
||||||
extrait:
|
|
||||||
"Légèreté, performance thermique, rapidité de construction — l'ossature bois a de nombreux avantages. OBC Maçonnerie vous explique.",
|
|
||||||
cat: "Construction",
|
|
||||||
date: "5 novembre 2024",
|
|
||||||
readTime: "5 min",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: "travaux-renovation-sans-permis-construction",
|
|
||||||
titre: "Quels travaux de rénovation ne nécessitent pas de permis ?",
|
|
||||||
extrait:
|
|
||||||
"Permis de construire, déclaration préalable, simple déclaration — on vous explique les règles selon la nature de vos travaux.",
|
|
||||||
cat: "Rénovation",
|
|
||||||
date: "18 octobre 2024",
|
|
||||||
readTime: "4 min",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: "fondations-maison-quels-types",
|
|
||||||
titre: "Les différents types de fondations pour une maison",
|
|
||||||
extrait:
|
|
||||||
"Semelles filantes, radier, pieux — quelles fondations choisir selon votre terrain et votre projet de construction ?",
|
|
||||||
cat: "Construction",
|
|
||||||
date: "2 septembre 2024",
|
|
||||||
readTime: "5 min",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const cats = ["Tous", "Construction", "Rénovation", "Assainissement"];
|
const cats = ["Tous", "Construction", "Rénovation", "Assainissement"];
|
||||||
|
|
||||||
export default function BlogPage() {
|
export default async function BlogPage() {
|
||||||
|
const articles = await getBlogPosts();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main id="main-content" className="min-h-screen">
|
<main id="main-content" className="min-h-screen">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export const metadata: Metadata = {
|
|||||||
title: "Conditions Générales de Vente | OBC Maçonnerie",
|
title: "Conditions Générales de Vente | OBC Maçonnerie",
|
||||||
description:
|
description:
|
||||||
"Conditions générales de vente d'OBC Maçonnerie — Benoît Colin, maçon à Mouchin (59310). Prestations de construction, rénovation et gros œuvre.",
|
"Conditions générales de vente d'OBC Maçonnerie — Benoît Colin, maçon à Mouchin (59310). Prestations de construction, rénovation et gros œuvre.",
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/cgv" },
|
alternates: { canonical: "https://obc-terrassement.fr/cgv" },
|
||||||
robots: { index: false, follow: false },
|
robots: { index: false, follow: false },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ import type { Metadata } from "next";
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Navbar from "@/components/marketing/Navbar";
|
import Navbar from "@/components/marketing/Navbar";
|
||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
|
import { siteConfig } from "@/lib/site-config";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Politique de Confidentialité | OBC Maçonnerie",
|
title: "Politique de Confidentialité | OBC Maçonnerie",
|
||||||
description:
|
description:
|
||||||
"Politique de confidentialité et protection des données personnelles du site OBC Maçonnerie, conformément au RGPD.",
|
"Politique de confidentialité et protection des données personnelles du site OBC Maçonnerie, conformément au RGPD.",
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/confidentialite" },
|
alternates: { canonical: "https://obc-terrassement.fr/confidentialite" },
|
||||||
robots: { index: false, follow: false },
|
robots: { index: false, follow: false },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -34,8 +35,8 @@ export default function Confidentialite() {
|
|||||||
<p><strong className="text-text">Benoît COLIN — OBC Maçonnerie</strong></p>
|
<p><strong className="text-text">Benoît COLIN — OBC Maçonnerie</strong></p>
|
||||||
<p>SIREN : 531 827 871</p>
|
<p>SIREN : 531 827 871</p>
|
||||||
<p>221 Route de Saint-Amand, 59310 Mouchin</p>
|
<p>221 Route de Saint-Amand, 59310 Mouchin</p>
|
||||||
<p>Tél : <a href="tel:0674453089" className="text-orange hover:underline">06 74 45 30 89</a></p>
|
<p>Tél : <a href={`tel:${siteConfig.phoneRaw}`} className="text-orange hover:underline">{siteConfig.phone}</a></p>
|
||||||
<p>Email : <a href="mailto:contact@obc-maconnerie.fr" className="text-orange hover:underline">contact@obc-maconnerie.fr</a></p>
|
<p>Email : <a href="mailto:contact@obc-terrassement.fr" className="text-orange hover:underline">contact@obc-terrassement.fr</a></p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -100,8 +101,8 @@ export default function Confidentialite() {
|
|||||||
Conformément au RGPD, vous disposez d'un droit d'accès, de rectification, d'effacement et de portabilité de vos données. Pour exercer ces droits, contactez-nous :
|
Conformément au RGPD, vous disposez d'un droit d'accès, de rectification, d'effacement et de portabilité de vos données. Pour exercer ces droits, contactez-nous :
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-3">
|
<p className="mt-3">
|
||||||
<a href="mailto:contact@obc-maconnerie.fr" className="text-orange font-semibold hover:underline">
|
<a href="mailto:contact@obc-terrassement.fr" className="text-orange font-semibold hover:underline">
|
||||||
contact@obc-maconnerie.fr
|
contact@obc-terrassement.fr
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const metadata: Metadata = {
|
|||||||
description:
|
description:
|
||||||
"OBC Maçonnerie intervient à Douai pour vos travaux de construction de maison, rénovation et gros œuvre. Benoît Colin, maçon expert. Devis gratuit.",
|
"OBC Maçonnerie intervient à Douai pour vos travaux de construction de maison, rénovation et gros œuvre. Benoît Colin, maçon expert. Devis gratuit.",
|
||||||
keywords: ["construction maison Douai", "maçon Douai", "rénovation Douai", "gros oeuvre Douai", "maçon rénovation Douai"],
|
keywords: ["construction maison Douai", "maçon Douai", "rénovation Douai", "gros oeuvre Douai", "maçon rénovation Douai"],
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/construction-maison-douai" },
|
alternates: { canonical: "https://obc-terrassement.fr/construction-maison-douai" },
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ConstructionMaisonDouaiPage() {
|
export default function ConstructionMaisonDouaiPage() {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const metadata: Metadata = {
|
|||||||
description:
|
description:
|
||||||
"OBC Maçonnerie intervient à Orchies pour vos travaux de construction de maison, rénovation et gros œuvre. Benoît Colin, maçon expert. Devis gratuit.",
|
"OBC Maçonnerie intervient à Orchies pour vos travaux de construction de maison, rénovation et gros œuvre. Benoît Colin, maçon expert. Devis gratuit.",
|
||||||
keywords: ["construction maison Orchies", "maçon Orchies", "rénovation Orchies", "gros oeuvre Orchies"],
|
keywords: ["construction maison Orchies", "maçon Orchies", "rénovation Orchies", "gros oeuvre Orchies"],
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/construction-maison-orchies" },
|
alternates: { canonical: "https://obc-terrassement.fr/construction-maison-orchies" },
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ConstructionMaisonOrchiesPage() {
|
export default function ConstructionMaisonOrchiesPage() {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const metadata: Metadata = {
|
|||||||
description:
|
description:
|
||||||
"OBC Maçonnerie intervient à Valenciennes pour vos travaux de construction de maison, rénovation et gros œuvre. Benoît Colin, maçon expert. Devis gratuit.",
|
"OBC Maçonnerie intervient à Valenciennes pour vos travaux de construction de maison, rénovation et gros œuvre. Benoît Colin, maçon expert. Devis gratuit.",
|
||||||
keywords: ["construction maison Valenciennes", "maçon Valenciennes", "rénovation Valenciennes", "gros oeuvre Valenciennes"],
|
keywords: ["construction maison Valenciennes", "maçon Valenciennes", "rénovation Valenciennes", "gros oeuvre Valenciennes"],
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/construction-maison-valenciennes" },
|
alternates: { canonical: "https://obc-terrassement.fr/construction-maison-valenciennes" },
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ConstructionMaisonValenciennesPage() {
|
export default function ConstructionMaisonValenciennesPage() {
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import Navbar from "@/components/marketing/Navbar";
|
|||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
import ScrollReveal from "@/components/animations/ScrollReveal";
|
import ScrollReveal from "@/components/animations/ScrollReveal";
|
||||||
import ContactForm from "@/components/marketing/ContactForm";
|
import ContactForm from "@/components/marketing/ContactForm";
|
||||||
|
import { getSiteConfig } from "@/lib/content";
|
||||||
|
|
||||||
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
|
const config = await getSiteConfig();
|
||||||
|
return {
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: "Construction de Maison dans le Nord | OBC Maçonnerie Orchies",
|
title: "Construction de Maison dans le Nord | OBC Maçonnerie Orchies",
|
||||||
description:
|
description:
|
||||||
"Construction neuve, fondations, ossature bois dans le Nord (59). OBC Maçonnerie vous accompagne de A à Z. Devis gratuit.",
|
"Construction neuve, fondations, ossature bois dans le Nord (59). OBC Maçonnerie vous accompagne de A à Z. Devis gratuit.",
|
||||||
@@ -17,8 +21,9 @@ export const metadata: Metadata = {
|
|||||||
"construction maison Douai",
|
"construction maison Douai",
|
||||||
"construction maison Valenciennes",
|
"construction maison Valenciennes",
|
||||||
],
|
],
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/construction-maison" },
|
alternates: { canonical: `${config.url}/construction-maison` },
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const etapes = [
|
const etapes = [
|
||||||
{ num: "01", title: "Étude & conseil", desc: "Benoît analyse votre terrain, votre plan et vos envies. Il adapte si besoin les plans d'architecte et vous conseille sur les matériaux." },
|
{ num: "01", title: "Étude & conseil", desc: "Benoît analyse votre terrain, votre plan et vos envies. Il adapte si besoin les plans d'architecte et vous conseille sur les matériaux." },
|
||||||
@@ -29,7 +34,9 @@ const etapes = [
|
|||||||
{ num: "06", title: "Remise des clés", desc: "Livraison de votre maison dans les délais convenus, avec un chantier propre et soigné." },
|
{ num: "06", title: "Remise des clés", desc: "Livraison de votre maison dans les délais convenus, avec un chantier propre et soigné." },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function ConstructionMaisonPage() {
|
export default async function ConstructionMaisonPage() {
|
||||||
|
const config = await getSiteConfig();
|
||||||
|
const { phone, phoneRaw } = config;
|
||||||
return (
|
return (
|
||||||
<main id="main-content" className="min-h-screen">
|
<main id="main-content" className="min-h-screen">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
@@ -56,9 +63,7 @@ export default function ConstructionMaisonPage() {
|
|||||||
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors pulse-glow">
|
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors pulse-glow">
|
||||||
Demander un devis gratuit
|
Demander un devis gratuit
|
||||||
</Link>
|
</Link>
|
||||||
<a href="tel:0674453089" className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-7 py-3.5 rounded-xl transition-colors border border-white/20">
|
<a href={`tel:${phoneRaw}`} className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-7 py-3.5 rounded-xl transition-colors border border-white/20">{phone}</a>
|
||||||
06 74 45 30 89
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,50 +3,46 @@ import Navbar from "@/components/marketing/Navbar";
|
|||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
import ScrollReveal from "@/components/animations/ScrollReveal";
|
import ScrollReveal from "@/components/animations/ScrollReveal";
|
||||||
import ContactForm from "@/components/marketing/ContactForm";
|
import ContactForm from "@/components/marketing/ContactForm";
|
||||||
|
import { getSiteConfig } from "@/lib/content";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
title: "Contact & Devis Gratuit | OBC Maçonnerie Nord",
|
const config = await getSiteConfig();
|
||||||
description:
|
return {
|
||||||
"Contactez OBC Maçonnerie pour un devis gratuit. Benoît Colin intervient à Orchies, Douai, Valenciennes et dans un rayon de 30km autour de Mouchin (59).",
|
title: "Contact & Devis Gratuit | OBC Maçonnerie Nord",
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/contact" },
|
description:
|
||||||
};
|
"Contactez OBC Maçonnerie pour un devis gratuit. Benoît Colin intervient à Orchies, Douai, Valenciennes et dans un rayon de 30km autour de Mouchin (59).",
|
||||||
|
alternates: { canonical: `${config.url}/contact` },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const infos = [
|
export default async function ContactPage() {
|
||||||
{
|
const config = await getSiteConfig();
|
||||||
icon: "📞",
|
const { phone, phoneRaw, email, address, zones, zoneDescription } = config;
|
||||||
titre: "Téléphone",
|
|
||||||
val: "06 74 45 30 89",
|
|
||||||
href: "tel:0674453089",
|
|
||||||
desc: "Lun–Ven 7h–19h",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "📍",
|
|
||||||
titre: "Adresse",
|
|
||||||
val: "221 Route de Saint-Amand, 59310 Mouchin",
|
|
||||||
href: undefined,
|
|
||||||
desc: "Rayon d'intervention : 30km",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "📧",
|
|
||||||
titre: "Email",
|
|
||||||
val: "contact@obc-maconnerie.fr",
|
|
||||||
href: "mailto:contact@obc-maconnerie.fr",
|
|
||||||
desc: "Réponse sous 24h",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const zones = [
|
const infos = [
|
||||||
"Orchies",
|
{
|
||||||
"Mouchin",
|
icon: "📞",
|
||||||
"Flines-lès-Raches",
|
titre: "Téléphone",
|
||||||
"Château-l'Abbaye",
|
val: phone,
|
||||||
"Mérignies",
|
href: `tel:${phoneRaw}`,
|
||||||
"Douai",
|
desc: "Lun–Ven 7h–19h",
|
||||||
"Valenciennes",
|
},
|
||||||
"Saint-Amand-les-Eaux",
|
{
|
||||||
];
|
icon: "📍",
|
||||||
|
titre: "Adresse",
|
||||||
|
val: address,
|
||||||
|
href: undefined as string | undefined,
|
||||||
|
desc: "Rayon d'intervention : 30km",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "📧",
|
||||||
|
titre: "Email",
|
||||||
|
val: email,
|
||||||
|
href: `mailto:${email}`,
|
||||||
|
desc: "Réponse sous 24h",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export default function ContactPage() {
|
|
||||||
return (
|
return (
|
||||||
<main id="main-content" className="min-h-screen">
|
<main id="main-content" className="min-h-screen">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
@@ -100,11 +96,11 @@ export default function ContactPage() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-text-muted text-xs italic">
|
<p className="text-text-muted text-xs italic">
|
||||||
Et toutes les communes dans un rayon de 20-30 km autour de Mouchin (Nord 59).
|
Et toutes les communes dans un rayon de {zoneDescription}.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="mt-8 bg-navy rounded-2xl p-6">
|
<div className="mt-8 bg-navy rounded-2xl p-6">
|
||||||
<h3 className="text-white font-bold mb-2">Devis gratuit & sans engagement</h3>
|
<h3 className="text-white font-bold mb-2">Devis gratuit & sans engagement</h3>
|
||||||
<p className="text-white/60 text-sm">
|
<p className="text-white/60 text-sm">
|
||||||
Benoît se déplace sur votre chantier pour évaluer votre projet, vous conseiller et vous remettre un devis clair et détaillé. Gratuit et sans engagement.
|
Benoît se déplace sur votre chantier pour évaluer votre projet, vous conseiller et vous remettre un devis clair et détaillé. Gratuit et sans engagement.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import Navbar from "@/components/marketing/Navbar";
|
|||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
import ScrollReveal from "@/components/animations/ScrollReveal";
|
import ScrollReveal from "@/components/animations/ScrollReveal";
|
||||||
import ContactForm from "@/components/marketing/ContactForm";
|
import ContactForm from "@/components/marketing/ContactForm";
|
||||||
|
import { getSiteConfig } from "@/lib/content";
|
||||||
|
|
||||||
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
|
const config = await getSiteConfig();
|
||||||
|
return {
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: "Création d'Accès, Voiries & Entrées | OBC Maçonnerie Nord",
|
title: "Création d'Accès, Voiries & Entrées | OBC Maçonnerie Nord",
|
||||||
description:
|
description:
|
||||||
"Création d'accès, voiries privées, entrées de propriété et chemins dans le Nord (59). OBC Maçonnerie à Orchies. Devis gratuit.",
|
"Création d'accès, voiries privées, entrées de propriété et chemins dans le Nord (59). OBC Maçonnerie à Orchies. Devis gratuit.",
|
||||||
@@ -17,8 +21,9 @@ export const metadata: Metadata = {
|
|||||||
"béton imprimé Nord",
|
"béton imprimé Nord",
|
||||||
"création accès Orchies",
|
"création accès Orchies",
|
||||||
],
|
],
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/creation-acces" },
|
alternates: { canonical: `${config.url}/creation-acces` },
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const types = [
|
const types = [
|
||||||
{ icon: "🚗", title: "Entrées de propriété", desc: "Création d'une entrée soignée en béton, béton imprimé, pavés ou gravier stabilisé — adaptée à votre maison." },
|
{ icon: "🚗", title: "Entrées de propriété", desc: "Création d'une entrée soignée en béton, béton imprimé, pavés ou gravier stabilisé — adaptée à votre maison." },
|
||||||
@@ -29,7 +34,9 @@ const types = [
|
|||||||
{ icon: "💧", title: "Drainage & évacuation", desc: "Mise en place de caniveaux, avaloirs et systèmes de drainage pour éviter les accumulations d'eau." },
|
{ icon: "💧", title: "Drainage & évacuation", desc: "Mise en place de caniveaux, avaloirs et systèmes de drainage pour éviter les accumulations d'eau." },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function CreationAccesPage() {
|
export default async function CreationAccesPage() {
|
||||||
|
const config = await getSiteConfig();
|
||||||
|
const { phone, phoneRaw } = config;
|
||||||
return (
|
return (
|
||||||
<main id="main-content" className="min-h-screen">
|
<main id="main-content" className="min-h-screen">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
@@ -55,9 +62,7 @@ export default function CreationAccesPage() {
|
|||||||
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors pulse-glow">
|
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors pulse-glow">
|
||||||
Demander un devis gratuit
|
Demander un devis gratuit
|
||||||
</Link>
|
</Link>
|
||||||
<a href="tel:0674453089" className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-7 py-3.5 rounded-xl transition-colors border border-white/20">
|
<a href={`tel:${phoneRaw}`} className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-7 py-3.5 rounded-xl transition-colors border border-white/20">{phone}</a>
|
||||||
06 74 45 30 89
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import Navbar from "@/components/marketing/Navbar";
|
|||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
import ScrollReveal from "@/components/animations/ScrollReveal";
|
import ScrollReveal from "@/components/animations/ScrollReveal";
|
||||||
import ContactForm from "@/components/marketing/ContactForm";
|
import ContactForm from "@/components/marketing/ContactForm";
|
||||||
|
import { getSiteConfig } from "@/lib/content";
|
||||||
|
|
||||||
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
|
const config = await getSiteConfig();
|
||||||
|
return {
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: "Démolition Maison Nord 59 | OBC Maçonnerie",
|
title: "Démolition Maison Nord 59 | OBC Maçonnerie",
|
||||||
description:
|
description:
|
||||||
"Démolition totale ou partielle de maison, murs porteurs, bâtiments dans le Nord (59). OBC Maçonnerie à Orchies. Toutes garanties de sécurité. Devis gratuit.",
|
"Démolition totale ou partielle de maison, murs porteurs, bâtiments dans le Nord (59). OBC Maçonnerie à Orchies. Toutes garanties de sécurité. Devis gratuit.",
|
||||||
@@ -17,8 +21,9 @@ export const metadata: Metadata = {
|
|||||||
"démolition Orchies",
|
"démolition Orchies",
|
||||||
"démolition Douai",
|
"démolition Douai",
|
||||||
],
|
],
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/demolition" },
|
alternates: { canonical: `${config.url}/demolition` },
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const types = [
|
const types = [
|
||||||
{ icon: "🏚️", title: "Démolition totale", desc: "Destruction complète d'un bâtiment résidentiel ou annexe, avec évacuation des gravats et remise en état du terrain." },
|
{ icon: "🏚️", title: "Démolition totale", desc: "Destruction complète d'un bâtiment résidentiel ou annexe, avec évacuation des gravats et remise en état du terrain." },
|
||||||
@@ -29,7 +34,9 @@ const types = [
|
|||||||
{ icon: "🏠", title: "Curage intérieur", desc: "Enlèvement complet des éléments intérieurs (cloisons, planchers, revêtements) avant une rénovation lourde." },
|
{ icon: "🏠", title: "Curage intérieur", desc: "Enlèvement complet des éléments intérieurs (cloisons, planchers, revêtements) avant une rénovation lourde." },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function DemolitionPage() {
|
export default async function DemolitionPage() {
|
||||||
|
const config = await getSiteConfig();
|
||||||
|
const { phone, phoneRaw } = config;
|
||||||
return (
|
return (
|
||||||
<main id="main-content" className="min-h-screen">
|
<main id="main-content" className="min-h-screen">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
@@ -55,9 +62,7 @@ export default function DemolitionPage() {
|
|||||||
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors pulse-glow">
|
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors pulse-glow">
|
||||||
Demander un devis gratuit
|
Demander un devis gratuit
|
||||||
</Link>
|
</Link>
|
||||||
<a href="tel:0674453089" className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-7 py-3.5 rounded-xl transition-colors border border-white/20">
|
<a href={`tel:${phoneRaw}`} className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-7 py-3.5 rounded-xl transition-colors border border-white/20">{phone}</a>
|
||||||
06 74 45 30 89
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import CookieBanner from "@/components/CookieBanner";
|
import CookieBanner from "@/components/CookieBanner";
|
||||||
|
import { siteConfig } from "@/lib/site-config";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
const BASE_URL = process.env.NEXT_PUBLIC_APP_URL || "https://obc-maconnerie.fr";
|
const BASE_URL = process.env.NEXT_PUBLIC_APP_URL || siteConfig.url;
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
metadataBase: new URL(BASE_URL),
|
metadataBase: new URL(BASE_URL),
|
||||||
@@ -95,8 +96,8 @@ export default function RootLayout({
|
|||||||
name: "OBC Maçonnerie",
|
name: "OBC Maçonnerie",
|
||||||
description:
|
description:
|
||||||
"Construction de maison, rénovation, assainissement et gros œuvre dans le Nord",
|
"Construction de maison, rénovation, assainissement et gros œuvre dans le Nord",
|
||||||
telephone: "06 74 45 30 89",
|
telephone: siteConfig.phone,
|
||||||
email: "contact@obc-maconnerie.fr",
|
email: siteConfig.email,
|
||||||
url: BASE_URL,
|
url: BASE_URL,
|
||||||
logo: `${BASE_URL}/icon-512.svg`,
|
logo: `${BASE_URL}/icon-512.svg`,
|
||||||
image: `${BASE_URL}/og-image.jpg`,
|
image: `${BASE_URL}/og-image.jpg`,
|
||||||
@@ -143,7 +144,7 @@ export default function RootLayout({
|
|||||||
},
|
},
|
||||||
contactPoint: {
|
contactPoint: {
|
||||||
"@type": "ContactPoint",
|
"@type": "ContactPoint",
|
||||||
telephone: "06 74 45 30 89",
|
telephone: siteConfig.phone,
|
||||||
contactType: "customer service",
|
contactType: "customer service",
|
||||||
availableLanguage: "French",
|
availableLanguage: "French",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const metadata: Metadata = {
|
|||||||
description:
|
description:
|
||||||
"OBC Maçonnerie intervient à Flines-lès-Raches pour vos travaux de construction, rénovation et gros œuvre. Benoît Colin, maçon expert. Devis gratuit.",
|
"OBC Maçonnerie intervient à Flines-lès-Raches pour vos travaux de construction, rénovation et gros œuvre. Benoît Colin, maçon expert. Devis gratuit.",
|
||||||
keywords: ["maçon Flines-lès-Raches", "construction Flines Raches", "rénovation Flines Raches", "maçon Flines Nord"],
|
keywords: ["maçon Flines-lès-Raches", "construction Flines Raches", "rénovation Flines Raches", "maçon Flines Nord"],
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/macon-flines-lez-raches" },
|
alternates: { canonical: "https://obc-terrassement.fr/macon-flines-lez-raches" },
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function MaconFlinesPage() {
|
export default function MaconFlinesPage() {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const metadata: Metadata = {
|
|||||||
description:
|
description:
|
||||||
"OBC Maçonnerie est basée à Mouchin (59310). Benoît Colin, maçon expert local. Construction, rénovation, assainissement, gros œuvre. Devis gratuit.",
|
"OBC Maçonnerie est basée à Mouchin (59310). Benoît Colin, maçon expert local. Construction, rénovation, assainissement, gros œuvre. Devis gratuit.",
|
||||||
keywords: ["maçon Mouchin", "entreprise maçonnerie Mouchin", "construction Mouchin", "rénovation Mouchin"],
|
keywords: ["maçon Mouchin", "entreprise maçonnerie Mouchin", "construction Mouchin", "rénovation Mouchin"],
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/macon-mouchin" },
|
alternates: { canonical: "https://obc-terrassement.fr/macon-mouchin" },
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function MaconMouchinPage() {
|
export default function MaconMouchinPage() {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const metadata: Metadata = {
|
|||||||
description:
|
description:
|
||||||
"OBC Maçonnerie intervient à Saint-Amand-les-Eaux pour vos travaux de construction, rénovation, assainissement et gros œuvre. Devis gratuit.",
|
"OBC Maçonnerie intervient à Saint-Amand-les-Eaux pour vos travaux de construction, rénovation, assainissement et gros œuvre. Devis gratuit.",
|
||||||
keywords: ["maçon Saint-Amand-les-Eaux", "construction Saint-Amand", "rénovation Saint-Amand les Eaux", "maçon Saint-Amand Nord"],
|
keywords: ["maçon Saint-Amand-les-Eaux", "construction Saint-Amand", "rénovation Saint-Amand les Eaux", "maçon Saint-Amand Nord"],
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/macon-saint-amand-les-eaux" },
|
alternates: { canonical: "https://obc-terrassement.fr/macon-saint-amand-les-eaux" },
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function MaconSaintAmandPage() {
|
export default function MaconSaintAmandPage() {
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ import type { Metadata } from "next";
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Navbar from "@/components/marketing/Navbar";
|
import Navbar from "@/components/marketing/Navbar";
|
||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
|
import { siteConfig } from "@/lib/site-config";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Mentions Légales | OBC Maçonnerie",
|
title: "Mentions Légales | OBC Maçonnerie",
|
||||||
description:
|
description:
|
||||||
"Mentions légales du site OBC Maçonnerie — Benoît Colin, maçon à Mouchin (59310). SIREN 531 827 871.",
|
"Mentions légales du site OBC Maçonnerie — Benoît Colin, maçon à Mouchin (59310). SIREN 531 827 871.",
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/mentions-legales" },
|
alternates: { canonical: "https://obc-terrassement.fr/mentions-legales" },
|
||||||
robots: { index: false, follow: false },
|
robots: { index: false, follow: false },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ export default function MentionsLegales() {
|
|||||||
|
|
||||||
<div className="space-y-10 text-text-light text-sm leading-relaxed">
|
<div className="space-y-10 text-text-light text-sm leading-relaxed">
|
||||||
<p className="italic text-text-muted">
|
<p className="italic text-text-muted">
|
||||||
Conformément aux dispositions de la loi n° 2004-575 du 21 juin 2004 pour la confiance en l'économie numérique (LCEN), voici les informations légales du site <strong className="text-text">obc-maconnerie.fr</strong>.
|
Conformément aux dispositions de la loi n° 2004-575 du 21 juin 2004 pour la confiance en l'économie numérique (LCEN), voici les informations légales du site <strong className="text-text">obc-terrassement.fr</strong>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
@@ -43,8 +44,8 @@ export default function MentionsLegales() {
|
|||||||
<li><strong className="text-text">Statut :</strong> Entreprise individuelle</li>
|
<li><strong className="text-text">Statut :</strong> Entreprise individuelle</li>
|
||||||
<li><strong className="text-text">SIREN :</strong> 531 827 871</li>
|
<li><strong className="text-text">SIREN :</strong> 531 827 871</li>
|
||||||
<li><strong className="text-text">Siège social :</strong> 221 Route de Saint-Amand, 59310 Mouchin, France</li>
|
<li><strong className="text-text">Siège social :</strong> 221 Route de Saint-Amand, 59310 Mouchin, France</li>
|
||||||
<li><strong className="text-text">Téléphone :</strong> <a href="tel:0674453089" className="text-orange hover:underline">06 74 45 30 89</a></li>
|
<li><strong className="text-text">Téléphone :</strong> <a href={`tel:${siteConfig.phoneRaw}`} className="text-orange hover:underline">{siteConfig.phone}</a></li>
|
||||||
<li><strong className="text-text">Email :</strong> <a href="mailto:contact@obc-maconnerie.fr" className="text-orange hover:underline">contact@obc-maconnerie.fr</a></li>
|
<li><strong className="text-text">Email :</strong> <a href="mailto:contact@obc-terrassement.fr" className="text-orange hover:underline">contact@obc-terrassement.fr</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<p className="mt-3"><strong className="text-text">Directeur de la publication :</strong> Benoît COLIN</p>
|
<p className="mt-3"><strong className="text-text">Directeur de la publication :</strong> Benoît COLIN</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
458
app/page.tsx
458
app/page.tsx
@@ -4,181 +4,53 @@ import Navbar from "@/components/marketing/Navbar";
|
|||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
import ScrollReveal from "@/components/animations/ScrollReveal";
|
import ScrollReveal from "@/components/animations/ScrollReveal";
|
||||||
import ContactForm from "@/components/marketing/ContactForm";
|
import ContactForm from "@/components/marketing/ContactForm";
|
||||||
|
import {
|
||||||
|
getSiteConfig,
|
||||||
|
getServices,
|
||||||
|
getTestimonials,
|
||||||
|
getFAQ,
|
||||||
|
getValues,
|
||||||
|
getPartners,
|
||||||
|
getRealisations,
|
||||||
|
} from "@/lib/content";
|
||||||
|
import type { Service, Testimonial, FAQItem } from "@/types/content";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
title: "OBC Maçonnerie | Constructeur & Maçon à Orchies (Nord 59)",
|
const config = await getSiteConfig();
|
||||||
description:
|
return {
|
||||||
"Benoît Colin, maçon expert à Mouchin. Construction de maison, rénovation, assainissement et gros œuvre dans un rayon de 30km autour d'Orchies. Devis gratuit.",
|
title: config.seo.title,
|
||||||
alternates: {
|
description: config.seo.description,
|
||||||
canonical: "https://obc-maconnerie.fr",
|
alternates: { canonical: config.url },
|
||||||
},
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
const services = [
|
function ServiceCard({ service }: { service: Service }) {
|
||||||
{
|
const href = service.slug === "conseil" ? "/contact" : `/${service.slug}`;
|
||||||
icon: "🏠",
|
return (
|
||||||
title: "Construction de maison",
|
<Link
|
||||||
desc: "Fondations, ossature bois, gros œuvre — on bâtit votre projet de A à Z avec vous.",
|
href={href}
|
||||||
href: "/construction-maison",
|
className="group block bg-bg-white border border-border rounded-2xl p-6 hover:border-orange hover:shadow-lg transition-all duration-300 card-hover"
|
||||||
},
|
>
|
||||||
{
|
<div className="text-3xl mb-4">{service.icon}</div>
|
||||||
icon: "🔨",
|
<h3 className="text-navy font-bold text-lg mb-2 group-hover:text-orange transition-colors">
|
||||||
title: "Rénovation",
|
{service.title}
|
||||||
desc: "Maison ou appartement, on s'adapte à votre projet et vos envies.",
|
</h3>
|
||||||
href: "/renovation",
|
<p className="text-text-light text-sm leading-relaxed">{service.shortDescription}</p>
|
||||||
},
|
<div className="mt-4 flex items-center gap-1 text-orange text-sm font-semibold">
|
||||||
{
|
En savoir plus
|
||||||
icon: "💧",
|
<svg className="w-4 h-4 group-hover:translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
title: "Assainissement",
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||||
desc: "Mise aux normes et création de systèmes d'assainissement fiables.",
|
</svg>
|
||||||
href: "/assainissement",
|
</div>
|
||||||
},
|
</Link>
|
||||||
{
|
);
|
||||||
icon: "🚧",
|
}
|
||||||
title: "Création d'accès",
|
|
||||||
desc: "Voiries, entrées, chemins — on crée vos accès sur mesure.",
|
|
||||||
href: "/creation-acces",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🏗️",
|
|
||||||
title: "Démolition",
|
|
||||||
desc: "Démolition totale ou partielle, avec toutes les garanties de sécurité.",
|
|
||||||
href: "/demolition",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🤝",
|
|
||||||
title: "Conseil & Accompagnement",
|
|
||||||
desc: "Benoît vous éclaire dans vos choix : matériaux, plans, adaptations — on réfléchit ensemble.",
|
|
||||||
href: "/contact",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const pilliers = [
|
|
||||||
{
|
|
||||||
icon: "📍",
|
|
||||||
title: "Proche de vous",
|
|
||||||
desc: "Disponible, à l'écoute, Benoît intervient dans votre secteur local et prend le temps de comprendre votre projet.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "💡",
|
|
||||||
title: "Conseil expert",
|
|
||||||
desc: "Il guide vos choix de matériaux et adapte les plans d'architecte pour un résultat qui vous ressemble.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🛡️",
|
|
||||||
title: "Acteur de confiance",
|
|
||||||
desc: "Transparent à chaque étape, Benoît rassure, explique et vous tient informé de l'avancement du chantier.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "❤️",
|
|
||||||
title: "Passionné du métier",
|
|
||||||
desc: "\"On ne fait jamais deux fois la même maison.\" Benoît aime être au cœur de chaque projet, de A à Z.",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const partenaires = [
|
|
||||||
{ label: "Électricité", icon: "⚡" },
|
|
||||||
{ label: "Plomberie", icon: "🔧" },
|
|
||||||
{ label: "Charpente", icon: "🪵" },
|
|
||||||
{ label: "Couverture", icon: "🏚️" },
|
|
||||||
{ label: "Isolation", icon: "🧱" },
|
|
||||||
{ label: "Menuiserie", icon: "🚪" },
|
|
||||||
{ label: "Carrelage", icon: "🔳" },
|
|
||||||
{ label: "Peinture", icon: "🎨" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const villes = [
|
|
||||||
"Orchies",
|
|
||||||
"Mouchin",
|
|
||||||
"Flines-lès-Raches",
|
|
||||||
"Château-l'Abbaye",
|
|
||||||
"Mérignies",
|
|
||||||
"Douai",
|
|
||||||
"Valenciennes",
|
|
||||||
"Saint-Amand-les-Eaux",
|
|
||||||
];
|
|
||||||
|
|
||||||
const realisations = [
|
|
||||||
{
|
|
||||||
title: "Construction d'une maison individuelle",
|
|
||||||
desc: "Fondations, gros œuvre et ossature — livraison clé en main à Orchies.",
|
|
||||||
cat: "Construction neuve",
|
|
||||||
color: "bg-navy",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Rénovation complète d'une maison de ville",
|
|
||||||
desc: "Restructuration intérieure, cloisons, escalier réhabilité à Douai.",
|
|
||||||
cat: "Rénovation",
|
|
||||||
color: "bg-stone",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Création d'un accès et chemin d'entrée",
|
|
||||||
desc: "Voirie et entrée béton imprimé, aménagement paysager à Mérignies.",
|
|
||||||
cat: "Création d'accès",
|
|
||||||
color: "bg-orange",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const temoignages = [
|
|
||||||
{
|
|
||||||
nom: "Christophe & Marie L.",
|
|
||||||
lieu: "Orchies",
|
|
||||||
projet: "Construction maison",
|
|
||||||
texte:
|
|
||||||
"Benoît nous a accompagnés de A à Z dans la construction de notre maison. Il a su adapter le plan d'architecte à nos envies tout en respectant notre budget. Disponible, professionnel, et vraiment à l'écoute. On recommande les yeux fermés.",
|
|
||||||
note: 5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
nom: "Sophie D.",
|
|
||||||
lieu: "Douai",
|
|
||||||
projet: "Rénovation",
|
|
||||||
texte:
|
|
||||||
"On lui a confié la rénovation complète de notre maison de 1970. Benoît a pris le temps de tout nous expliquer, a proposé des solutions auxquelles on n'avait pas pensé, et le résultat est magnifique. Un vrai professionnel.",
|
|
||||||
note: 5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
nom: "Famille Moreau",
|
|
||||||
lieu: "Saint-Amand-les-Eaux",
|
|
||||||
projet: "Assainissement",
|
|
||||||
texte:
|
|
||||||
"Mise aux normes de notre système d'assainissement réalisée dans les délais et en toute transparence. Benoît nous a expliqué chaque étape. Très sérieux et propre dans son travail.",
|
|
||||||
note: 5,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const faqs = [
|
|
||||||
{
|
|
||||||
q: "Dans quelle zone intervenez-vous ?",
|
|
||||||
a: "OBC Maçonnerie intervient dans un rayon de 20 à 30 km autour de Mouchin (59310) : Orchies, Flines-lès-Raches, Château-l'Abbaye, Mérignies, Douai, Valenciennes, Saint-Amand-les-Eaux et les communes alentour.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
q: "Faites-vous des devis gratuits ?",
|
|
||||||
a: "Oui, absolument. Le devis est gratuit et sans engagement. Contactez Benoît par téléphone ou via le formulaire, il se déplace pour évaluer votre projet.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
q: "Pouvez-vous adapter un plan d'architecte ?",
|
|
||||||
a: "Oui, c'est même l'une de nos spécialités. Benoît collabore directement avec vous pour adapter les plans à vos envies, votre budget et les contraintes du terrain.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
q: "Combien de temps dure une construction de maison ?",
|
|
||||||
a: "Une construction neuve prend en moyenne 10 à 18 mois selon la complexité du projet, les conditions météo et les délais de livraison des matériaux. Benoît vous donne un calendrier dès la signature.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
q: "Travaillez-vous avec d'autres artisans ?",
|
|
||||||
a: "Oui. OBC Maçonnerie dispose d'un réseau de partenaires de confiance pour tous les corps de métier : électricité, plomberie, charpente, isolation, menuiserie, carrelage, peinture et couverture. Vous avez un seul interlocuteur pour coordonner l'ensemble.",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
function StarRating({ note }: { note: number }) {
|
function StarRating({ note }: { note: number }) {
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-0.5">
|
<div className="flex gap-0.5">
|
||||||
{Array.from({ length: 5 }).map((_, i) => (
|
{Array.from({ length: 5 }).map((_, i) => (
|
||||||
<svg
|
<svg key={i} className={`w-4 h-4 ${i < note ? "text-orange" : "text-border"}`} fill="currentColor" viewBox="0 0 20 20">
|
||||||
key={i}
|
|
||||||
className={`w-4 h-4 ${i < note ? "text-orange" : "text-border"}`}
|
|
||||||
fill="currentColor"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
>
|
|
||||||
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
|
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
|
||||||
</svg>
|
</svg>
|
||||||
))}
|
))}
|
||||||
@@ -186,68 +58,90 @@ function StarRating({ note }: { note: number }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function HomePage() {
|
function TestimonialCard({ t }: { t: Testimonial }) {
|
||||||
|
const serviceLabel: Record<string, string> = {
|
||||||
|
"construction-maison": "Construction de maison",
|
||||||
|
renovation: "Rénovation",
|
||||||
|
assainissement: "Assainissement",
|
||||||
|
"creation-acces": "Création d'accès",
|
||||||
|
demolition: "Démolition",
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="bg-white/5 border border-white/10 rounded-2xl p-6 h-full flex flex-col">
|
||||||
|
<StarRating note={t.rating} />
|
||||||
|
<p className="text-white/80 text-sm leading-relaxed mt-4 flex-1 italic">“{t.text}”</p>
|
||||||
|
<div className="mt-5 pt-4 border-t border-white/10">
|
||||||
|
<p className="text-white font-semibold text-sm">{t.name}</p>
|
||||||
|
<p className="text-white/40 text-xs">{t.ville} — {serviceLabel[t.service] ?? t.service}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function FAQAccordion({ item }: { item: FAQItem }) {
|
||||||
|
return (
|
||||||
|
<details className="group bg-bg-white border border-border rounded-2xl overflow-hidden">
|
||||||
|
<summary className="flex items-center justify-between px-6 py-4 cursor-pointer font-semibold text-navy hover:text-orange transition-colors list-none">
|
||||||
|
{item.question}
|
||||||
|
<svg className="w-5 h-5 text-text-muted group-open:rotate-180 transition-transform shrink-0 ml-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||||||
|
</svg>
|
||||||
|
</summary>
|
||||||
|
<div className="px-6 pb-5 text-text-light text-sm leading-relaxed border-t border-border-light pt-4">
|
||||||
|
{item.answer}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function HomePage() {
|
||||||
|
const [config, services, testimonials, faqItems, values, partners, realisations] =
|
||||||
|
await Promise.all([
|
||||||
|
getSiteConfig(),
|
||||||
|
getServices(),
|
||||||
|
getTestimonials(),
|
||||||
|
getFAQ(),
|
||||||
|
getValues(),
|
||||||
|
getPartners(),
|
||||||
|
getRealisations(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const { hero, zones, zoneDescription, partnersTitle, partnersMessage, phone, phoneRaw } = config;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main id="main-content" className="min-h-screen">
|
<main id="main-content" className="min-h-screen">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
{/* ── SECTION 1 — HERO ── */}
|
{/* ── SECTION 1 — HERO ── */}
|
||||||
<section className="relative bg-navy overflow-hidden pt-20 pb-24 md:pt-28 md:pb-32">
|
<section className="relative bg-navy overflow-hidden pt-20 pb-24 md:pt-28 md:pb-32">
|
||||||
{/* Background texture */}
|
<div className="absolute inset-0 opacity-5" style={{ backgroundImage: "repeating-linear-gradient(45deg,#fff 0,#fff 1px,transparent 0,transparent 50%)", backgroundSize: "20px 20px" }} />
|
||||||
<div className="absolute inset-0 opacity-5">
|
|
||||||
<div
|
|
||||||
className="absolute inset-0"
|
|
||||||
style={{
|
|
||||||
backgroundImage:
|
|
||||||
"repeating-linear-gradient(45deg, #fff 0, #fff 1px, transparent 0, transparent 50%)",
|
|
||||||
backgroundSize: "20px 20px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="relative max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
<div className="relative max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||||
{/* Badge */}
|
<div className="inline-flex items-center gap-2 bg-white/10 border border-white/20 rounded-full px-4 py-1.5 mb-6">
|
||||||
<div className="inline-flex items-center gap-2 bg-white/10 border border-white/20 rounded-full px-4 py-1.5 mb-6 animate-hero-text-1">
|
|
||||||
<span className="w-2 h-2 bg-green-400 rounded-full animate-pulse" />
|
<span className="w-2 h-2 bg-green-400 rounded-full animate-pulse" />
|
||||||
<span className="text-white/80 text-sm">
|
<span className="text-white/80 text-sm">{hero.badge}</span>
|
||||||
Disponible, à l'écoute — Benoît vous accompagne de la première pierre à la remise des clés
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="text-4xl md:text-6xl font-bold text-white leading-tight mb-6 animate-hero-text-2">
|
<h1 className="text-4xl md:text-6xl font-bold text-white leading-tight mb-6">
|
||||||
Maçon & Constructeur<br />
|
Maçon & Constructeur<br />
|
||||||
<span className="text-orange">dans le Nord</span>
|
<span className="text-orange">dans le Nord</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p className="text-white/70 text-lg md:text-xl max-w-2xl mx-auto mb-8 animate-hero-text-3">
|
<p className="text-white/70 text-lg md:text-xl max-w-2xl mx-auto mb-8">{hero.subtitle}</p>
|
||||||
Construction de maison, rénovation, assainissement et gros œuvre —
|
|
||||||
expertise autour d'Orchies, Douai et Valenciennes.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="flex flex-col sm:flex-row gap-4 justify-center animate-hero-text-3">
|
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||||
<Link
|
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-8 py-4 rounded-xl text-base transition-colors pulse-glow">
|
||||||
href="/contact"
|
{hero.cta}
|
||||||
className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-8 py-4 rounded-xl text-base transition-colors pulse-glow"
|
|
||||||
>
|
|
||||||
Demander un devis gratuit
|
|
||||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||||
</svg>
|
</svg>
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link href="/realisations" className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-8 py-4 rounded-xl text-base transition-colors border border-white/20">
|
||||||
href="/realisations"
|
{hero.ctaSecondary}
|
||||||
className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-8 py-4 rounded-xl text-base transition-colors border border-white/20"
|
|
||||||
>
|
|
||||||
Voir nos réalisations
|
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stats */}
|
|
||||||
<div className="mt-14 grid grid-cols-3 gap-6 max-w-lg mx-auto border-t border-white/10 pt-10">
|
<div className="mt-14 grid grid-cols-3 gap-6 max-w-lg mx-auto border-t border-white/10 pt-10">
|
||||||
{[
|
{hero.stats.map((s) => (
|
||||||
{ val: "15+", label: "ans d'expérience" },
|
|
||||||
{ val: "200+", label: "chantiers réalisés" },
|
|
||||||
{ val: "30km", label: "de rayon d'action" },
|
|
||||||
].map((s) => (
|
|
||||||
<div key={s.label} className="text-center">
|
<div key={s.label} className="text-center">
|
||||||
<div className="text-2xl md:text-3xl font-bold text-orange">{s.val}</div>
|
<div className="text-2xl md:text-3xl font-bold text-orange">{s.val}</div>
|
||||||
<div className="text-white/50 text-xs mt-1">{s.label}</div>
|
<div className="text-white/50 text-xs mt-1">{s.label}</div>
|
||||||
@@ -269,26 +163,10 @@ export default function HomePage() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{services.map((s, i) => (
|
{services.map((s, i) => (
|
||||||
<ScrollReveal key={s.title} direction="up" delay={i * 80}>
|
<ScrollReveal key={s.slug} direction="up" delay={i * 80}>
|
||||||
<Link
|
<ServiceCard service={s} />
|
||||||
href={s.href}
|
|
||||||
className="group block bg-bg-white border border-border rounded-2xl p-6 hover:border-orange hover:shadow-lg transition-all duration-300 card-hover"
|
|
||||||
>
|
|
||||||
<div className="text-3xl mb-4">{s.icon}</div>
|
|
||||||
<h3 className="text-navy font-bold text-lg mb-2 group-hover:text-orange transition-colors">
|
|
||||||
{s.title}
|
|
||||||
</h3>
|
|
||||||
<p className="text-text-light text-sm leading-relaxed">{s.desc}</p>
|
|
||||||
<div className="mt-4 flex items-center gap-1 text-orange text-sm font-semibold">
|
|
||||||
En savoir plus
|
|
||||||
<svg className="w-4 h-4 group-hover:translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -304,14 +182,13 @@ export default function HomePage() {
|
|||||||
<h2 className="text-3xl md:text-4xl font-bold text-navy mt-2">Pourquoi choisir OBC Maçonnerie ?</h2>
|
<h2 className="text-3xl md:text-4xl font-bold text-navy mt-2">Pourquoi choisir OBC Maçonnerie ?</h2>
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||||
{pilliers.map((p, i) => (
|
{values.map((v, i) => (
|
||||||
<ScrollReveal key={p.title} direction="up" delay={i * 100}>
|
<ScrollReveal key={v.title} direction="up" delay={i * 100}>
|
||||||
<div className="bg-bg-white rounded-2xl p-6 border border-border text-center h-full">
|
<div className="bg-bg-white rounded-2xl p-6 border border-border text-center h-full">
|
||||||
<div className="text-4xl mb-4">{p.icon}</div>
|
<div className="text-4xl mb-4">{v.icon}</div>
|
||||||
<h3 className="text-navy font-bold text-lg mb-3">{p.title}</h3>
|
<h3 className="text-navy font-bold text-lg mb-3">{v.title}</h3>
|
||||||
<p className="text-text-light text-sm leading-relaxed">{p.desc}</p>
|
<p className="text-text-light text-sm leading-relaxed">{v.description}</p>
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
))}
|
))}
|
||||||
@@ -325,17 +202,12 @@ export default function HomePage() {
|
|||||||
<ScrollReveal direction="up">
|
<ScrollReveal direction="up">
|
||||||
<div className="text-center mb-12">
|
<div className="text-center mb-12">
|
||||||
<span className="text-orange text-sm font-semibold uppercase tracking-widest">Un réseau solide</span>
|
<span className="text-orange text-sm font-semibold uppercase tracking-widest">Un réseau solide</span>
|
||||||
<h2 className="text-3xl md:text-4xl font-bold text-navy mt-2">
|
<h2 className="text-3xl md:text-4xl font-bold text-navy mt-2">{partnersTitle}</h2>
|
||||||
Seul on va vite, ensemble on va plus loin.
|
<p className="text-text-light mt-4 max-w-xl mx-auto">{partnersMessage}</p>
|
||||||
</h2>
|
|
||||||
<p className="text-text-light mt-4 max-w-xl mx-auto">
|
|
||||||
Grâce à notre réseau de partenaires de confiance, nous coordonnons l'ensemble des corps de métier pour que votre maison prenne forme de A à Z.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-4">
|
<div className="grid grid-cols-2 sm:grid-cols-4 gap-4">
|
||||||
{partenaires.map((p, i) => (
|
{partners.map((p, i) => (
|
||||||
<ScrollReveal key={p.label} direction="up" delay={i * 60}>
|
<ScrollReveal key={p.label} direction="up" delay={i * 60}>
|
||||||
<div className="bg-bg-white border border-border rounded-xl p-4 text-center hover:border-orange hover:shadow-md transition-all">
|
<div className="bg-bg-white border border-border rounded-xl p-4 text-center hover:border-orange hover:shadow-md transition-all">
|
||||||
<div className="text-2xl mb-2">{p.icon}</div>
|
<div className="text-2xl mb-2">{p.icon}</div>
|
||||||
@@ -344,16 +216,12 @@ export default function HomePage() {
|
|||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ScrollReveal direction="up" delay={200}>
|
<ScrollReveal direction="up" delay={200}>
|
||||||
<div className="mt-10 bg-navy rounded-2xl p-6 md:p-8 text-center">
|
<div className="mt-10 bg-navy rounded-2xl p-6 md:p-8 text-center">
|
||||||
<p className="text-white text-base md:text-lg font-medium">
|
<p className="text-white text-base md:text-lg font-medium">
|
||||||
Un seul interlocuteur pour coordonner l'ensemble de votre projet — de la démolition à la remise des clés.
|
Un seul interlocuteur pour coordonner l'ensemble de votre projet — de la démolition à la remise des clés.
|
||||||
</p>
|
</p>
|
||||||
<Link
|
<Link href="/partenaires" className="inline-flex items-center gap-2 mt-4 text-orange-light hover:text-white font-semibold transition-colors">
|
||||||
href="/partenaires"
|
|
||||||
className="inline-flex items-center gap-2 mt-4 text-orange-light hover:text-white font-semibold transition-colors"
|
|
||||||
>
|
|
||||||
Découvrir notre réseau
|
Découvrir notre réseau
|
||||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||||
@@ -369,33 +237,25 @@ export default function HomePage() {
|
|||||||
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||||
<ScrollReveal direction="up">
|
<ScrollReveal direction="up">
|
||||||
<span className="text-orange text-sm font-semibold uppercase tracking-widest">Secteur d'activité</span>
|
<span className="text-orange text-sm font-semibold uppercase tracking-widest">Secteur d'activité</span>
|
||||||
<h2 className="text-3xl md:text-4xl font-bold text-navy mt-2 mb-4">
|
<h2 className="text-3xl md:text-4xl font-bold text-navy mt-2 mb-4">Nous intervenons dans toute la région</h2>
|
||||||
Nous intervenons dans toute la région
|
|
||||||
</h2>
|
|
||||||
<p className="text-text-light max-w-xl mx-auto mb-10">
|
<p className="text-text-light max-w-xl mx-auto mb-10">
|
||||||
OBC Maçonnerie intervient dans un rayon de 20 à 30 km autour de Mouchin (Nord 59).
|
OBC Maçonnerie intervient dans un rayon de {zoneDescription}.
|
||||||
</p>
|
</p>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|
||||||
<div className="flex flex-wrap justify-center gap-3 mb-8">
|
<div className="flex flex-wrap justify-center gap-3 mb-8">
|
||||||
{villes.map((v, i) => (
|
{zones.map((v, i) => (
|
||||||
<ScrollReveal key={v} direction="up" delay={i * 50}>
|
<ScrollReveal key={v} direction="up" delay={i * 50}>
|
||||||
<span className="inline-flex items-center gap-1.5 bg-bg-white border border-border text-navy font-medium text-sm px-4 py-2 rounded-full hover:border-orange hover:shadow-sm transition-all">
|
<span className="inline-flex items-center gap-1.5 bg-bg-white border border-border text-navy font-medium text-sm px-4 py-2 rounded-full hover:border-orange hover:shadow-sm transition-all">
|
||||||
<span className="text-orange">📍</span>
|
<span className="text-orange">📍</span>{v}
|
||||||
{v}
|
|
||||||
</span>
|
</span>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ScrollReveal direction="up" delay={100}>
|
<ScrollReveal direction="up" delay={100}>
|
||||||
<p className="text-text-light text-sm italic">
|
<p className="text-text-light text-sm italic">
|
||||||
Et dans toutes les communes à 20-30 km autour de Mouchin — contactez-nous pour vérifier votre zone.
|
Et dans toutes les communes à {zoneDescription} — contactez-nous pour vérifier votre zone.
|
||||||
</p>
|
</p>
|
||||||
<Link
|
<Link href="/contact" className="inline-flex items-center gap-2 mt-6 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors">
|
||||||
href="/contact"
|
|
||||||
className="inline-flex items-center gap-2 mt-6 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors"
|
|
||||||
>
|
|
||||||
Demander un devis dans ma commune
|
Demander un devis dans ma commune
|
||||||
</Link>
|
</Link>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
@@ -411,34 +271,28 @@ export default function HomePage() {
|
|||||||
<h2 className="text-3xl md:text-4xl font-bold text-navy mt-2">Aperçu de nos réalisations</h2>
|
<h2 className="text-3xl md:text-4xl font-bold text-navy mt-2">Aperçu de nos réalisations</h2>
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
{realisations.map((r, i) => (
|
{realisations.map((r, i) => {
|
||||||
<ScrollReveal key={r.title} direction="up" delay={i * 100}>
|
const colors = ["bg-navy", "bg-stone", "bg-orange"];
|
||||||
<div className="bg-bg-white rounded-2xl overflow-hidden border border-border hover:shadow-lg transition-all group card-hover">
|
return (
|
||||||
<div className={`${r.color} h-44 flex items-center justify-center`}>
|
<ScrollReveal key={r.title} direction="up" delay={i * 100}>
|
||||||
<span className="text-white/20 text-8xl font-bold">{i + 1}</span>
|
<div className="bg-bg-white rounded-2xl overflow-hidden border border-border hover:shadow-lg transition-all group card-hover">
|
||||||
|
<div className={`${colors[i % colors.length]} h-44 flex items-center justify-center`}>
|
||||||
|
<span className="text-white/20 text-8xl font-bold">{i + 1}</span>
|
||||||
|
</div>
|
||||||
|
<div className="p-5">
|
||||||
|
<span className="inline-block bg-bg-muted text-text-light text-xs font-semibold px-2 py-1 rounded-full mb-2">{r.ville}</span>
|
||||||
|
<h3 className="text-navy font-bold text-base mb-1 group-hover:text-orange transition-colors">{r.title}</h3>
|
||||||
|
<p className="text-text-light text-sm">{r.description}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-5">
|
</ScrollReveal>
|
||||||
<span className="inline-block bg-bg-muted text-text-light text-xs font-semibold px-2 py-1 rounded-full mb-2">
|
);
|
||||||
{r.cat}
|
})}
|
||||||
</span>
|
|
||||||
<h3 className="text-navy font-bold text-base mb-1 group-hover:text-orange transition-colors">
|
|
||||||
{r.title}
|
|
||||||
</h3>
|
|
||||||
<p className="text-text-light text-sm">{r.desc}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ScrollReveal>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ScrollReveal direction="up" delay={150}>
|
<ScrollReveal direction="up" delay={150}>
|
||||||
<div className="text-center mt-8">
|
<div className="text-center mt-8">
|
||||||
<Link
|
<Link href="/realisations" className="inline-flex items-center gap-2 border-2 border-navy text-navy hover:bg-navy hover:text-white font-bold px-7 py-3.5 rounded-xl transition-colors">
|
||||||
href="/realisations"
|
|
||||||
className="inline-flex items-center gap-2 border-2 border-navy text-navy hover:bg-navy hover:text-white font-bold px-7 py-3.5 rounded-xl transition-colors"
|
|
||||||
>
|
|
||||||
Voir toutes nos réalisations
|
Voir toutes nos réalisations
|
||||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||||
@@ -458,20 +312,10 @@ export default function HomePage() {
|
|||||||
<h2 className="text-3xl md:text-4xl font-bold text-white mt-2">Témoignages clients</h2>
|
<h2 className="text-3xl md:text-4xl font-bold text-white mt-2">Témoignages clients</h2>
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
{temoignages.map((t, i) => (
|
{testimonials.map((t, i) => (
|
||||||
<ScrollReveal key={t.nom} direction="up" delay={i * 100}>
|
<ScrollReveal key={t.name} direction="up" delay={i * 100}>
|
||||||
<div className="bg-white/5 border border-white/10 rounded-2xl p-6 h-full flex flex-col">
|
<TestimonialCard t={t} />
|
||||||
<StarRating note={t.note} />
|
|
||||||
<p className="text-white/80 text-sm leading-relaxed mt-4 flex-1 italic">
|
|
||||||
“{t.texte}”
|
|
||||||
</p>
|
|
||||||
<div className="mt-5 pt-4 border-t border-white/10">
|
|
||||||
<p className="text-white font-semibold text-sm">{t.nom}</p>
|
|
||||||
<p className="text-white/40 text-xs">{t.lieu} — {t.projet}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -487,26 +331,10 @@ export default function HomePage() {
|
|||||||
<h2 className="text-3xl md:text-4xl font-bold text-navy mt-2">FAQ</h2>
|
<h2 className="text-3xl md:text-4xl font-bold text-navy mt-2">FAQ</h2>
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{faqs.map((f, i) => (
|
{faqItems.map((f, i) => (
|
||||||
<ScrollReveal key={f.q} direction="up" delay={i * 60}>
|
<ScrollReveal key={f.question} direction="up" delay={i * 60}>
|
||||||
<details className="group bg-bg-white border border-border rounded-2xl overflow-hidden">
|
<FAQAccordion item={f} />
|
||||||
<summary className="flex items-center justify-between px-6 py-4 cursor-pointer font-semibold text-navy hover:text-orange transition-colors list-none">
|
|
||||||
{f.q}
|
|
||||||
<svg
|
|
||||||
className="w-5 h-5 text-text-muted group-open:rotate-180 transition-transform shrink-0 ml-4"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
|
||||||
</svg>
|
|
||||||
</summary>
|
|
||||||
<div className="px-6 pb-5 text-text-light text-sm leading-relaxed border-t border-border-light pt-4">
|
|
||||||
{f.a}
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -522,9 +350,7 @@ export default function HomePage() {
|
|||||||
<h2 className="text-3xl md:text-4xl font-bold text-navy mt-2">Parlez-nous de votre projet</h2>
|
<h2 className="text-3xl md:text-4xl font-bold text-navy mt-2">Parlez-nous de votre projet</h2>
|
||||||
<p className="text-text-light mt-3">
|
<p className="text-text-light mt-3">
|
||||||
Réponse sous 24h — ou appelez directement Benoît au{" "}
|
Réponse sous 24h — ou appelez directement Benoît au{" "}
|
||||||
<a href="tel:0674453089" className="text-orange font-bold hover:underline">
|
<a href={`tel:${phoneRaw}`} className="text-orange font-bold hover:underline">{phone}</a>
|
||||||
06 74 45 30 89
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|||||||
@@ -3,58 +3,21 @@ import Link from "next/link";
|
|||||||
import Navbar from "@/components/marketing/Navbar";
|
import Navbar from "@/components/marketing/Navbar";
|
||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
import ScrollReveal from "@/components/animations/ScrollReveal";
|
import ScrollReveal from "@/components/animations/ScrollReveal";
|
||||||
|
import { getPartners, getSiteConfig } from "@/lib/content";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
title: "Notre Réseau de Partenaires | OBC Maçonnerie Nord",
|
const config = await getSiteConfig();
|
||||||
description:
|
return {
|
||||||
"OBC Maçonnerie coordonne un réseau d'artisans partenaires de confiance pour livrer votre maison de A à Z : électricité, plomberie, charpente, isolation, menuiserie, carrelage, peinture.",
|
title: "Notre Réseau de Partenaires | OBC Maçonnerie Nord",
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/partenaires" },
|
description:
|
||||||
};
|
"OBC Maçonnerie coordonne un réseau d'artisans partenaires de confiance pour livrer votre maison de A à Z : électricité, plomberie, charpente, isolation, menuiserie, carrelage, peinture.",
|
||||||
|
alternates: { canonical: `${config.url}/partenaires` },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const partenaires = [
|
export default async function PartenairesPage() {
|
||||||
{
|
const partenaires = await getPartners();
|
||||||
icon: "⚡",
|
|
||||||
metier: "Électricité",
|
|
||||||
desc: "Installation électrique aux normes NF C 15-100, tableau de distribution, prises, éclairage.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🔧",
|
|
||||||
metier: "Plomberie",
|
|
||||||
desc: "Plomberie sanitaire, chauffage central, installation de salles de bains et cuisines.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🪵",
|
|
||||||
metier: "Charpente",
|
|
||||||
desc: "Charpente traditionnelle ou industrielle, structure bois pour combles aménageables ou non.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🏚️",
|
|
||||||
metier: "Couverture",
|
|
||||||
desc: "Pose de toiture, tuiles, ardoises, zinc — étanchéité et finitions soignées.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🧱",
|
|
||||||
metier: "Isolation",
|
|
||||||
desc: "Isolation thermique et phonique par l'intérieur ou l'extérieur, combles, planchers.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🚪",
|
|
||||||
metier: "Menuiserie",
|
|
||||||
desc: "Fenêtres, portes, vérandas, volets — menuiserie bois, PVC ou aluminium.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🔳",
|
|
||||||
metier: "Carrelage & Revêtements",
|
|
||||||
desc: "Pose de carrelage, parquet, faïence — pour sols et murs, intérieur et extérieur.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🎨",
|
|
||||||
metier: "Peinture",
|
|
||||||
desc: "Peinture intérieure et extérieure, enduits décoratifs, ravalement de façade.",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function PartenairesPage() {
|
|
||||||
return (
|
return (
|
||||||
<main id="main-content" className="min-h-screen">
|
<main id="main-content" className="min-h-screen">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
@@ -88,10 +51,10 @@ export default function PartenairesPage() {
|
|||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-5">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-5">
|
||||||
{partenaires.map((p, i) => (
|
{partenaires.map((p, i) => (
|
||||||
<ScrollReveal key={p.metier} direction="up" delay={i * 70}>
|
<ScrollReveal key={p.label} direction="up" delay={i * 70}>
|
||||||
<div className="bg-bg-white border border-border rounded-2xl p-5 text-center h-full hover:border-orange hover:shadow-md transition-all">
|
<div className="bg-bg-white border border-border rounded-2xl p-5 text-center h-full hover:border-orange hover:shadow-md transition-all">
|
||||||
<div className="text-4xl mb-3">{p.icon}</div>
|
<div className="text-4xl mb-3">{p.icon}</div>
|
||||||
<h3 className="text-navy font-bold text-base mb-2">{p.metier}</h3>
|
<h3 className="text-navy font-bold text-base mb-2">{p.label}</h3>
|
||||||
<p className="text-text-light text-xs leading-relaxed">{p.desc}</p>
|
<p className="text-text-light text-xs leading-relaxed">{p.desc}</p>
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|||||||
@@ -3,62 +3,24 @@ import Link from "next/link";
|
|||||||
import Navbar from "@/components/marketing/Navbar";
|
import Navbar from "@/components/marketing/Navbar";
|
||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
import ScrollReveal from "@/components/animations/ScrollReveal";
|
import ScrollReveal from "@/components/animations/ScrollReveal";
|
||||||
|
import { getRealisations, getSiteConfig } from "@/lib/content";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
title: "Nos Réalisations | Chantiers OBC Maçonnerie Nord",
|
const config = await getSiteConfig();
|
||||||
description:
|
return {
|
||||||
"Découvrez les réalisations d'OBC Maçonnerie : constructions de maisons, rénovations, assainissement et créations d'accès dans le Nord (59). Galerie photos.",
|
title: "Nos Réalisations | Chantiers OBC Maçonnerie Nord",
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/realisations" },
|
description:
|
||||||
};
|
"Découvrez les réalisations d'OBC Maçonnerie : constructions de maisons, rénovations, assainissement et créations d'accès dans le Nord (59). Galerie photos.",
|
||||||
|
alternates: { canonical: `${config.url}/realisations` },
|
||||||
const realisations = [
|
};
|
||||||
{
|
}
|
||||||
categorie: "Construction neuve",
|
|
||||||
titre: "Maison individuelle à Orchies",
|
|
||||||
desc: "Construction d'une maison de 130 m² — fondations, gros œuvre, dalle béton et ossature.",
|
|
||||||
zone: "Orchies (59)",
|
|
||||||
color: "bg-navy",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
categorie: "Rénovation",
|
|
||||||
titre: "Rénovation complète à Douai",
|
|
||||||
desc: "Restructuration intérieure complète d'une maison de ville : abattage de cloisons, création d'un escalier neuf, doublages.",
|
|
||||||
zone: "Douai (59)",
|
|
||||||
color: "bg-stone",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
categorie: "Assainissement",
|
|
||||||
titre: "Mise aux normes à Saint-Amand",
|
|
||||||
desc: "Remplacement d'une fosse septique vétuste par une micro-station d'épuration conforme aux normes.",
|
|
||||||
zone: "Saint-Amand-les-Eaux (59)",
|
|
||||||
color: "bg-navy-light",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
categorie: "Création d'accès",
|
|
||||||
titre: "Entrée en béton imprimé à Mérignies",
|
|
||||||
desc: "Création d'une entrée de propriété en béton imprimé effet pavés, avec caniveau de drainage.",
|
|
||||||
zone: "Mérignies (59)",
|
|
||||||
color: "bg-orange",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
categorie: "Construction neuve",
|
|
||||||
titre: "Extension ossature bois à Flines",
|
|
||||||
desc: "Agrandissement d'une maison existante par extension ossature bois, fondations et dalle.",
|
|
||||||
zone: "Flines-lès-Raches (59)",
|
|
||||||
color: "bg-navy",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
categorie: "Démolition",
|
|
||||||
titre: "Démolition & reconstruction à Valenciennes",
|
|
||||||
desc: "Démolition d'un bâtiment annexe et curage d'une grange pour préparer une rénovation complète.",
|
|
||||||
zone: "Valenciennes (59)",
|
|
||||||
color: "bg-stone",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const cats = ["Tous", "Construction neuve", "Rénovation", "Assainissement", "Création d'accès", "Démolition"];
|
const cats = ["Tous", "Construction neuve", "Rénovation", "Assainissement", "Création d'accès", "Démolition"];
|
||||||
|
|
||||||
export default function RealisationsPage() {
|
export default async function RealisationsPage() {
|
||||||
|
const [realisations, config] = await Promise.all([getRealisations(), getSiteConfig()]);
|
||||||
|
const { phone, phoneRaw } = config;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main id="main-content" className="min-h-screen">
|
<main id="main-content" className="min-h-screen">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
@@ -100,7 +62,7 @@ export default function RealisationsPage() {
|
|||||||
<div className="max-w-6xl mx-auto px-4 sm:px-6">
|
<div className="max-w-6xl mx-auto px-4 sm:px-6">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{realisations.map((r, i) => (
|
{realisations.map((r, i) => (
|
||||||
<ScrollReveal key={r.titre} direction="up" delay={i * 80}>
|
<ScrollReveal key={r.title} direction="up" delay={i * 80}>
|
||||||
<div className="bg-bg-white border border-border rounded-2xl overflow-hidden hover:shadow-lg transition-all group card-hover">
|
<div className="bg-bg-white border border-border rounded-2xl overflow-hidden hover:shadow-lg transition-all group card-hover">
|
||||||
<div className={`${r.color} h-48 flex items-center justify-center relative`}>
|
<div className={`${r.color} h-48 flex items-center justify-center relative`}>
|
||||||
<span className="text-white/10 text-8xl font-black">{i + 1}</span>
|
<span className="text-white/10 text-8xl font-black">{i + 1}</span>
|
||||||
@@ -112,12 +74,12 @@ export default function RealisationsPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="p-5">
|
<div className="p-5">
|
||||||
<h3 className="text-navy font-bold text-base mb-2 group-hover:text-orange transition-colors">
|
<h3 className="text-navy font-bold text-base mb-2 group-hover:text-orange transition-colors">
|
||||||
{r.titre}
|
{r.title}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-text-light text-sm leading-relaxed mb-3">{r.desc}</p>
|
<p className="text-text-light text-sm leading-relaxed mb-3">{r.description}</p>
|
||||||
<div className="flex items-center gap-1 text-text-muted text-xs">
|
<div className="flex items-center gap-1 text-text-muted text-xs">
|
||||||
<span>📍</span>
|
<span>📍</span>
|
||||||
<span>{r.zone}</span>
|
<span>{r.ville}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -141,10 +103,10 @@ export default function RealisationsPage() {
|
|||||||
Demander un devis gratuit
|
Demander un devis gratuit
|
||||||
</Link>
|
</Link>
|
||||||
<a
|
<a
|
||||||
href="tel:0674453089"
|
href={`tel:${phoneRaw}`}
|
||||||
className="inline-flex items-center justify-center gap-2 border-2 border-navy text-navy hover:bg-navy hover:text-white font-bold px-7 py-3.5 rounded-xl transition-colors"
|
className="inline-flex items-center justify-center gap-2 border-2 border-navy text-navy hover:bg-navy hover:text-white font-bold px-7 py-3.5 rounded-xl transition-colors"
|
||||||
>
|
>
|
||||||
06 74 45 30 89
|
{phone}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const metadata: Metadata = {
|
|||||||
description:
|
description:
|
||||||
"Rénovation de maison et appartement à Douai. OBC Maçonnerie, maçon expert en rénovation dans le Nord (59). Devis gratuit.",
|
"Rénovation de maison et appartement à Douai. OBC Maçonnerie, maçon expert en rénovation dans le Nord (59). Devis gratuit.",
|
||||||
keywords: ["rénovation maison Douai", "maçon rénovation Douai", "rénovation appartement Douai", "travaux rénovation Douai"],
|
keywords: ["rénovation maison Douai", "maçon rénovation Douai", "rénovation appartement Douai", "travaux rénovation Douai"],
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/renovation-maison-douai" },
|
alternates: { canonical: "https://obc-terrassement.fr/renovation-maison-douai" },
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RenovationMaisonDouaiPage() {
|
export default function RenovationMaisonDouaiPage() {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const metadata: Metadata = {
|
|||||||
description:
|
description:
|
||||||
"Rénovation de maison et appartement à Orchies. OBC Maçonnerie, maçon expert en rénovation dans le Nord (59). Devis gratuit.",
|
"Rénovation de maison et appartement à Orchies. OBC Maçonnerie, maçon expert en rénovation dans le Nord (59). Devis gratuit.",
|
||||||
keywords: ["rénovation maison Orchies", "maçon rénovation Orchies", "rénovation appartement Orchies"],
|
keywords: ["rénovation maison Orchies", "maçon rénovation Orchies", "rénovation appartement Orchies"],
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/renovation-maison-orchies" },
|
alternates: { canonical: "https://obc-terrassement.fr/renovation-maison-orchies" },
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RenovationMaisonOrchiesPage() {
|
export default function RenovationMaisonOrchiesPage() {
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import Navbar from "@/components/marketing/Navbar";
|
|||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
import ScrollReveal from "@/components/animations/ScrollReveal";
|
import ScrollReveal from "@/components/animations/ScrollReveal";
|
||||||
import ContactForm from "@/components/marketing/ContactForm";
|
import ContactForm from "@/components/marketing/ContactForm";
|
||||||
|
import { getSiteConfig } from "@/lib/content";
|
||||||
|
|
||||||
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
|
const config = await getSiteConfig();
|
||||||
|
return {
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: "Rénovation Maison & Appartement Nord 59 | OBC Maçonnerie",
|
title: "Rénovation Maison & Appartement Nord 59 | OBC Maçonnerie",
|
||||||
description:
|
description:
|
||||||
"Rénovation complète ou partielle de maison et appartement dans le Nord. Benoît Colin vous conseille et adapte chaque projet. Devis gratuit.",
|
"Rénovation complète ou partielle de maison et appartement dans le Nord. Benoît Colin vous conseille et adapte chaque projet. Devis gratuit.",
|
||||||
@@ -17,8 +21,9 @@ export const metadata: Metadata = {
|
|||||||
"rénovation maison Orchies",
|
"rénovation maison Orchies",
|
||||||
"travaux rénovation Nord",
|
"travaux rénovation Nord",
|
||||||
],
|
],
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/renovation" },
|
alternates: { canonical: `${config.url}/renovation` },
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const typesTravaux = [
|
const typesTravaux = [
|
||||||
{ icon: "🏚️", title: "Rénovation complète", desc: "Restructuration totale d'une maison ancienne, de la démolition des cloisons existantes à la pose des revêtements." },
|
{ icon: "🏚️", title: "Rénovation complète", desc: "Restructuration totale d'une maison ancienne, de la démolition des cloisons existantes à la pose des revêtements." },
|
||||||
@@ -29,7 +34,9 @@ const typesTravaux = [
|
|||||||
{ icon: "🏠", title: "Rénovation appartement", desc: "Transformation d'appartements : redistribution des pièces, mise aux normes, travaux de second œuvre." },
|
{ icon: "🏠", title: "Rénovation appartement", desc: "Transformation d'appartements : redistribution des pièces, mise aux normes, travaux de second œuvre." },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function RenovationPage() {
|
export default async function RenovationPage() {
|
||||||
|
const config = await getSiteConfig();
|
||||||
|
const { phone, phoneRaw } = config;
|
||||||
return (
|
return (
|
||||||
<main id="main-content" className="min-h-screen">
|
<main id="main-content" className="min-h-screen">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
@@ -55,9 +62,7 @@ export default function RenovationPage() {
|
|||||||
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors pulse-glow">
|
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors pulse-glow">
|
||||||
Demander un devis gratuit
|
Demander un devis gratuit
|
||||||
</Link>
|
</Link>
|
||||||
<a href="tel:0674453089" className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-7 py-3.5 rounded-xl transition-colors border border-white/20">
|
<a href={`tel:${phoneRaw}`} className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-7 py-3.5 rounded-xl transition-colors border border-white/20">{phone}</a>
|
||||||
06 74 45 30 89
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { MetadataRoute } from "next";
|
import type { MetadataRoute } from "next";
|
||||||
|
import { siteConfig } from "@/lib/site-config";
|
||||||
|
|
||||||
const BASE_URL = process.env.NEXT_PUBLIC_APP_URL || "https://obc-maconnerie.fr";
|
const BASE_URL = process.env.NEXT_PUBLIC_APP_URL || siteConfig.url;
|
||||||
|
|
||||||
export default function robots(): MetadataRoute.Robots {
|
export default function robots(): MetadataRoute.Robots {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -3,65 +3,23 @@ import Link from "next/link";
|
|||||||
import Navbar from "@/components/marketing/Navbar";
|
import Navbar from "@/components/marketing/Navbar";
|
||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
import ScrollReveal from "@/components/animations/ScrollReveal";
|
import ScrollReveal from "@/components/animations/ScrollReveal";
|
||||||
|
import { getServices, getSiteConfig } from "@/lib/content";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Nos Services | Construction, Rénovation, Assainissement",
|
title: "Nos Services | Construction, Rénovation, Assainissement",
|
||||||
description:
|
description:
|
||||||
"Tous les services d'OBC Maçonnerie : construction de maison, rénovation, assainissement, création d'accès et démolition dans le Nord (59). Devis gratuit.",
|
"Tous les services d'OBC Maçonnerie : construction de maison, rénovation, assainissement, création d'accès et démolition dans le Nord (59). Devis gratuit.",
|
||||||
alternates: { canonical: "https://obc-maconnerie.fr/services" },
|
alternates: { canonical: "https://obc-terrassement.fr/services" },
|
||||||
};
|
};
|
||||||
|
|
||||||
const services = [
|
export default async function ServicesPage() {
|
||||||
{
|
const [services, config] = await Promise.all([getServices(), getSiteConfig()]);
|
||||||
icon: "🏠",
|
const { phone, phoneRaw } = config;
|
||||||
title: "Construction de maison",
|
|
||||||
desc: "De la conception au gros œuvre, Benoît Colin vous accompagne dans la construction de votre maison individuelle. Fondations, ossature bois, dalles, murs porteurs — tout est pris en charge avec rigueur et savoir-faire.",
|
|
||||||
href: "/construction-maison",
|
|
||||||
points: ["Maison individuelle", "Ossature bois", "Fondations", "Gros œuvre complet"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🔨",
|
|
||||||
title: "Rénovation",
|
|
||||||
desc: "Que ce soit une rénovation partielle ou complète, OBC Maçonnerie s'adapte à votre projet. Maison ancienne, appartement, restructuration intérieure — chaque chantier est unique et traité comme tel.",
|
|
||||||
href: "/renovation",
|
|
||||||
points: ["Rénovation complète", "Restructuration intérieure", "Maison de ville", "Extension"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "💧",
|
|
||||||
title: "Assainissement",
|
|
||||||
desc: "Mise aux normes de votre système d'assainissement, création d'un nouveau dispositif ou réhabilitation de l'existant. OBC Maçonnerie réalise vos travaux d'assainissement dans les règles de l'art.",
|
|
||||||
href: "/assainissement",
|
|
||||||
points: ["Assainissement individuel", "Mise aux normes", "Fosse septique", "Épandage"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🚧",
|
|
||||||
title: "Création d'accès",
|
|
||||||
desc: "Voiries, entrées de propriété, chemins, allées — OBC Maçonnerie crée vos accès selon vos besoins et vos envies. Béton, béton imprimé, pavés ou grave compactée.",
|
|
||||||
href: "/creation-acces",
|
|
||||||
points: ["Voiries privées", "Entrées de propriété", "Chemins ruraux", "Béton imprimé"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🏗️",
|
|
||||||
title: "Démolition",
|
|
||||||
desc: "Démolition totale ou partielle de bâtiment, destruction de murs porteurs, dépose de chapes — OBC Maçonnerie intervient avec tout le matériel et les garanties de sécurité nécessaires.",
|
|
||||||
href: "/demolition",
|
|
||||||
points: ["Démolition totale", "Démolition partielle", "Murs porteurs", "Évacuation des gravats"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "🤝",
|
|
||||||
title: "Conseil & Accompagnement",
|
|
||||||
desc: "Benoît vous guide à chaque étape de votre projet : choix des matériaux, adaptation de plans, coordination des artisans partenaires. Un seul interlocuteur pour un projet serein.",
|
|
||||||
href: "/contact",
|
|
||||||
points: ["Conseils matériaux", "Adaptation de plans", "Coordination artisans", "Suivi de chantier"],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function ServicesPage() {
|
|
||||||
return (
|
return (
|
||||||
<main id="main-content" className="min-h-screen">
|
<main id="main-content" className="min-h-screen">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
{/* Hero */}
|
|
||||||
<section className="bg-navy py-16 md:py-20">
|
<section className="bg-navy py-16 md:py-20">
|
||||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 text-center">
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 text-center">
|
||||||
<ScrollReveal direction="up">
|
<ScrollReveal direction="up">
|
||||||
@@ -74,61 +32,54 @@ export default function ServicesPage() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Services */}
|
|
||||||
<section className="py-16 md:py-20 bg-bg">
|
<section className="py-16 md:py-20 bg-bg">
|
||||||
<div className="max-w-5xl mx-auto px-4 sm:px-6 space-y-8">
|
<div className="max-w-5xl mx-auto px-4 sm:px-6 space-y-8">
|
||||||
{services.map((s, i) => (
|
{services.map((s, i) => {
|
||||||
<ScrollReveal key={s.title} direction="up" delay={i * 60}>
|
const href = s.slug === "conseil" ? "/contact" : `/${s.slug}`;
|
||||||
<div className="bg-bg-white border border-border rounded-2xl p-6 md:p-8 flex flex-col md:flex-row gap-6">
|
return (
|
||||||
<div className="text-5xl shrink-0">{s.icon}</div>
|
<ScrollReveal key={s.slug} direction="up" delay={i * 60}>
|
||||||
<div className="flex-1">
|
<div className="bg-bg-white border border-border rounded-2xl p-6 md:p-8 flex flex-col md:flex-row gap-6">
|
||||||
<h2 className="text-xl font-bold text-navy mb-2">{s.title}</h2>
|
<div className="text-5xl shrink-0">{s.icon}</div>
|
||||||
<p className="text-text-light text-sm leading-relaxed mb-4">{s.desc}</p>
|
<div className="flex-1">
|
||||||
<div className="flex flex-wrap gap-2 mb-5">
|
<h2 className="text-xl font-bold text-navy mb-2">{s.title}</h2>
|
||||||
{s.points.map((p) => (
|
<p className="text-text-light text-sm leading-relaxed mb-4">{s.longDescription}</p>
|
||||||
<span key={p} className="bg-bg-muted text-text-light text-xs font-medium px-3 py-1 rounded-full">
|
<div className="flex flex-wrap gap-2 mb-5">
|
||||||
{p}
|
{s.keywords.map((k) => (
|
||||||
</span>
|
<span key={k} className="bg-bg-muted text-text-light text-xs font-medium px-3 py-1 rounded-full">
|
||||||
))}
|
{k}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<Link
|
||||||
|
href={href}
|
||||||
|
className="inline-flex items-center gap-1.5 text-orange font-semibold text-sm hover:underline"
|
||||||
|
>
|
||||||
|
En savoir plus
|
||||||
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||||
|
</svg>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<Link
|
|
||||||
href={s.href}
|
|
||||||
className="inline-flex items-center gap-1.5 text-orange font-semibold text-sm hover:underline"
|
|
||||||
>
|
|
||||||
En savoir plus
|
|
||||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
|
||||||
</svg>
|
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ScrollReveal>
|
||||||
</ScrollReveal>
|
);
|
||||||
))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* CTA */}
|
|
||||||
<section className="py-16 bg-stone-bg">
|
<section className="py-16 bg-stone-bg">
|
||||||
<div className="max-w-2xl mx-auto px-4 text-center">
|
<div className="max-w-2xl mx-auto px-4 text-center">
|
||||||
<ScrollReveal direction="up">
|
<ScrollReveal direction="up">
|
||||||
<h2 className="text-2xl md:text-3xl font-bold text-navy mb-4">
|
<h2 className="text-2xl md:text-3xl font-bold text-navy mb-4">Vous avez un projet ? Parlons-en.</h2>
|
||||||
Vous avez un projet ? Parlons-en.
|
|
||||||
</h2>
|
|
||||||
<p className="text-text-light mb-6">
|
<p className="text-text-light mb-6">
|
||||||
Benoît se déplace gratuitement pour évaluer votre projet et vous remettre un devis détaillé.
|
Benoît se déplace gratuitement pour évaluer votre projet et vous remettre un devis détaillé.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||||
<Link
|
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors">
|
||||||
href="/contact"
|
|
||||||
className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors"
|
|
||||||
>
|
|
||||||
Demander un devis gratuit
|
Demander un devis gratuit
|
||||||
</Link>
|
</Link>
|
||||||
<a
|
<a href={`tel:${phoneRaw}`} className="inline-flex items-center justify-center gap-2 border-2 border-navy text-navy hover:bg-navy hover:text-white font-bold px-7 py-3.5 rounded-xl transition-colors">
|
||||||
href="tel:0674453089"
|
{phone}
|
||||||
className="inline-flex items-center justify-center gap-2 border-2 border-navy text-navy hover:bg-navy hover:text-white font-bold px-7 py-3.5 rounded-xl transition-colors"
|
|
||||||
>
|
|
||||||
06 74 45 30 89
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { MetadataRoute } from "next";
|
import type { MetadataRoute } from "next";
|
||||||
|
import { siteConfig } from "@/lib/site-config";
|
||||||
|
|
||||||
const BASE_URL = process.env.NEXT_PUBLIC_APP_URL || "https://obc-maconnerie.fr";
|
const BASE_URL = process.env.NEXT_PUBLIC_APP_URL || siteConfig.url;
|
||||||
|
|
||||||
export default function sitemap(): MetadataRoute.Sitemap {
|
export default function sitemap(): MetadataRoute.Sitemap {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|||||||
@@ -1,6 +1,19 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { siteConfig } from "@/lib/site-config";
|
||||||
|
|
||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
dirigeant,
|
||||||
|
phone,
|
||||||
|
phoneRaw,
|
||||||
|
address,
|
||||||
|
siren,
|
||||||
|
footerServicesNav,
|
||||||
|
footerMainNav,
|
||||||
|
footerLegalNav,
|
||||||
|
} = siteConfig;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="bg-navy text-white pt-12 pb-6">
|
<footer className="bg-navy text-white pt-12 pb-6">
|
||||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
@@ -17,35 +30,33 @@ export default function Footer() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-white/70 text-sm leading-relaxed mb-4 max-w-xs">
|
<p className="text-white/70 text-sm leading-relaxed mb-4 max-w-xs">
|
||||||
Benoît Colin, maçon expert en construction de maison, rénovation et gros œuvre dans le Nord. De la première pierre à la remise des clés.
|
{dirigeant}, maçon expert en construction de maison, rénovation et gros
|
||||||
|
œuvre dans le Nord. De la première pierre à la remise des clés.
|
||||||
</p>
|
</p>
|
||||||
<a
|
<a
|
||||||
href="tel:0674453089"
|
href={`tel:${phoneRaw}`}
|
||||||
className="inline-flex items-center gap-2 text-orange-light font-bold text-base hover:text-white transition-colors"
|
className="inline-flex items-center gap-2 text-orange-light font-bold text-base hover:text-white transition-colors"
|
||||||
>
|
>
|
||||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||||
</svg>
|
</svg>
|
||||||
06 74 45 30 89
|
{phone}
|
||||||
</a>
|
</a>
|
||||||
<p className="text-white/40 text-xs mt-2">
|
<p className="text-white/40 text-xs mt-2">{address}</p>
|
||||||
221 Route de Saint-Amand, 59310 Mouchin
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Services */}
|
{/* Services */}
|
||||||
<div>
|
<div>
|
||||||
<h4 className="text-white font-semibold text-sm mb-4 uppercase tracking-wide">Services</h4>
|
<h4 className="text-white font-semibold text-sm mb-4 uppercase tracking-wide">
|
||||||
|
Services
|
||||||
|
</h4>
|
||||||
<ul className="space-y-2">
|
<ul className="space-y-2">
|
||||||
{[
|
{footerServicesNav.map((item) => (
|
||||||
{ href: "/construction-maison", label: "Construction de maison" },
|
|
||||||
{ href: "/renovation", label: "Rénovation" },
|
|
||||||
{ href: "/assainissement", label: "Assainissement" },
|
|
||||||
{ href: "/creation-acces", label: "Création d'accès" },
|
|
||||||
{ href: "/demolition", label: "Démolition" },
|
|
||||||
].map((item) => (
|
|
||||||
<li key={item.href}>
|
<li key={item.href}>
|
||||||
<Link href={item.href} className="text-white/60 hover:text-white text-sm transition-colors">
|
<Link
|
||||||
|
href={item.href}
|
||||||
|
className="text-white/60 hover:text-white text-sm transition-colors"
|
||||||
|
>
|
||||||
{item.label}
|
{item.label}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
@@ -53,33 +64,33 @@ export default function Footer() {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Navigation */}
|
{/* Navigation + Légal */}
|
||||||
<div>
|
<div>
|
||||||
<h4 className="text-white font-semibold text-sm mb-4 uppercase tracking-wide">Navigation</h4>
|
<h4 className="text-white font-semibold text-sm mb-4 uppercase tracking-wide">
|
||||||
|
Navigation
|
||||||
|
</h4>
|
||||||
<ul className="space-y-2">
|
<ul className="space-y-2">
|
||||||
{[
|
{footerMainNav.map((item) => (
|
||||||
{ href: "/", label: "Accueil" },
|
|
||||||
{ href: "/realisations", label: "Réalisations" },
|
|
||||||
{ href: "/partenaires", label: "Partenaires" },
|
|
||||||
{ href: "/contact", label: "Contact" },
|
|
||||||
{ href: "/blog", label: "Blog" },
|
|
||||||
].map((item) => (
|
|
||||||
<li key={item.href}>
|
<li key={item.href}>
|
||||||
<Link href={item.href} className="text-white/60 hover:text-white text-sm transition-colors">
|
<Link
|
||||||
|
href={item.href}
|
||||||
|
className="text-white/60 hover:text-white text-sm transition-colors"
|
||||||
|
>
|
||||||
{item.label}
|
{item.label}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
<h4 className="text-white font-semibold text-sm mb-3 mt-5 uppercase tracking-wide">Légal</h4>
|
<h4 className="text-white font-semibold text-sm mb-3 mt-5 uppercase tracking-wide">
|
||||||
|
Légal
|
||||||
|
</h4>
|
||||||
<ul className="space-y-2">
|
<ul className="space-y-2">
|
||||||
{[
|
{footerLegalNav.map((item) => (
|
||||||
{ href: "/mentions-legales", label: "Mentions légales" },
|
|
||||||
{ href: "/confidentialite", label: "Confidentialité" },
|
|
||||||
{ href: "/cgv", label: "CGV" },
|
|
||||||
].map((item) => (
|
|
||||||
<li key={item.href}>
|
<li key={item.href}>
|
||||||
<Link href={item.href} className="text-white/60 hover:text-white text-sm transition-colors">
|
<Link
|
||||||
|
href={item.href}
|
||||||
|
className="text-white/60 hover:text-white text-sm transition-colors"
|
||||||
|
>
|
||||||
{item.label}
|
{item.label}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
@@ -91,10 +102,12 @@ export default function Footer() {
|
|||||||
{/* Bottom */}
|
{/* Bottom */}
|
||||||
<div className="pt-6 flex flex-col md:flex-row items-center justify-between gap-3">
|
<div className="pt-6 flex flex-col md:flex-row items-center justify-between gap-3">
|
||||||
<p className="text-white/40 text-xs text-center md:text-left">
|
<p className="text-white/40 text-xs text-center md:text-left">
|
||||||
© {new Date().getFullYear()} OBC Maçonnerie — Benoît Colin · SIREN 531 827 871
|
© {new Date().getFullYear()} {name} — {dirigeant} · SIREN{" "}
|
||||||
|
{siren.replace(/(\d{3})(\d{3})(\d{3})/, "$1 $2 $3")}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-white/40 text-xs text-center md:text-right">
|
<p className="text-white/40 text-xs text-center md:text-right">
|
||||||
Orchies · Mouchin · Douai · Valenciennes · Saint-Amand-les-Eaux —{" "}
|
Orchies · Mouchin · Douai · Valenciennes ·
|
||||||
|
Saint-Amand-les-Eaux —{" "}
|
||||||
<span className="text-white/30">Site réalisé par HookLab</span>
|
<span className="text-white/30">Site réalisé par HookLab</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import Navbar from "@/components/marketing/Navbar";
|
|||||||
import Footer from "@/components/marketing/Footer";
|
import Footer from "@/components/marketing/Footer";
|
||||||
import ScrollReveal from "@/components/animations/ScrollReveal";
|
import ScrollReveal from "@/components/animations/ScrollReveal";
|
||||||
import ContactForm from "@/components/marketing/ContactForm";
|
import ContactForm from "@/components/marketing/ContactForm";
|
||||||
|
import { siteConfig } from "@/lib/site-config";
|
||||||
|
|
||||||
interface LocalSEOPageProps {
|
interface LocalSEOPageProps {
|
||||||
ville: string;
|
ville: string;
|
||||||
@@ -14,13 +15,13 @@ interface LocalSEOPageProps {
|
|||||||
distanceMouchin?: string;
|
distanceMouchin?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const services = [
|
// Services dérivés de siteConfig (sans "conseil" qui redirige vers /contact)
|
||||||
{ icon: "🏠", label: "Construction de maison", href: "/construction-maison" },
|
const services = siteConfig.footerServicesNav.map((s) => {
|
||||||
{ icon: "🔨", label: "Rénovation", href: "/renovation" },
|
const found = siteConfig.services.find(
|
||||||
{ icon: "💧", label: "Assainissement", href: "/assainissement" },
|
(sc) => sc.title === s.label || `/${sc.slug}` === s.href
|
||||||
{ icon: "🚧", label: "Création d'accès", href: "/creation-acces" },
|
);
|
||||||
{ icon: "🏗️", label: "Démolition", href: "/demolition" },
|
return { icon: found?.icon ?? "🔧", label: s.label, href: s.href };
|
||||||
];
|
});
|
||||||
|
|
||||||
export default function LocalSEOPage({
|
export default function LocalSEOPage({
|
||||||
ville,
|
ville,
|
||||||
@@ -31,6 +32,8 @@ export default function LocalSEOPage({
|
|||||||
texteLocal,
|
texteLocal,
|
||||||
distanceMouchin,
|
distanceMouchin,
|
||||||
}: LocalSEOPageProps) {
|
}: LocalSEOPageProps) {
|
||||||
|
const { phone, phoneRaw, address } = siteConfig;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main id="main-content" className="min-h-screen">
|
<main id="main-content" className="min-h-screen">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
@@ -57,8 +60,8 @@ export default function LocalSEOPage({
|
|||||||
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors pulse-glow">
|
<Link href="/contact" className="inline-flex items-center justify-center gap-2 bg-orange hover:bg-orange-hover text-white font-bold px-7 py-3.5 rounded-xl transition-colors pulse-glow">
|
||||||
Demander un devis gratuit
|
Demander un devis gratuit
|
||||||
</Link>
|
</Link>
|
||||||
<a href="tel:0674453089" className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-7 py-3.5 rounded-xl transition-colors border border-white/20">
|
<a href={`tel:${phoneRaw}`} className="inline-flex items-center justify-center gap-2 bg-white/10 hover:bg-white/20 text-white font-semibold px-7 py-3.5 rounded-xl transition-colors border border-white/20">
|
||||||
06 74 45 30 89
|
{phone}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
@@ -116,9 +119,9 @@ export default function LocalSEOPage({
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-navy font-bold text-sm">Benoît Colin — OBC Maçonnerie</p>
|
<p className="text-navy font-bold text-sm">Benoît Colin — OBC Maçonnerie</p>
|
||||||
<p className="text-text-muted text-xs">221 Route de Saint-Amand, 59310 Mouchin</p>
|
<p className="text-text-muted text-xs">{address}</p>
|
||||||
<a href="tel:0674453089" className="text-orange font-bold text-sm hover:underline">
|
<a href={`tel:${phoneRaw}`} className="text-orange font-bold text-sm hover:underline">
|
||||||
06 74 45 30 89
|
{phone}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,16 +2,11 @@
|
|||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { siteConfig } from "@/lib/site-config";
|
||||||
const navLinks = [
|
|
||||||
{ href: "/services", label: "Nos services" },
|
|
||||||
{ href: "/realisations", label: "Réalisations" },
|
|
||||||
{ href: "/partenaires", label: "Partenaires" },
|
|
||||||
{ href: "/contact", label: "Contact" },
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function Navbar() {
|
export default function Navbar() {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const { name, phone, phoneRaw, nav } = siteConfig;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
@@ -22,9 +17,9 @@ export default function Navbar() {
|
|||||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div className="flex items-center justify-between h-16">
|
<div className="flex items-center justify-between h-16">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<Link href="/" className="flex items-center gap-2.5" aria-label="OBC Maçonnerie - Accueil">
|
<Link href="/" className="flex items-center gap-2.5" aria-label={`${name} - Accueil`}>
|
||||||
<div className="w-9 h-9 bg-navy rounded-lg flex items-center justify-center shrink-0">
|
<div className="w-9 h-9 bg-navy rounded-lg flex items-center justify-center shrink-0">
|
||||||
<span className="text-white font-bold text-sm">OBC</span>
|
<span className="text-white font-bold text-xs">OBC</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col leading-tight">
|
<div className="flex flex-col leading-tight">
|
||||||
<span className="text-navy font-bold text-sm leading-none">OBC</span>
|
<span className="text-navy font-bold text-sm leading-none">OBC</span>
|
||||||
@@ -34,7 +29,7 @@ export default function Navbar() {
|
|||||||
|
|
||||||
{/* Desktop links */}
|
{/* Desktop links */}
|
||||||
<div className="hidden md:flex items-center gap-6">
|
<div className="hidden md:flex items-center gap-6">
|
||||||
{navLinks.map((link) => (
|
{nav.map((link) => (
|
||||||
<Link
|
<Link
|
||||||
key={link.href}
|
key={link.href}
|
||||||
href={link.href}
|
href={link.href}
|
||||||
@@ -48,13 +43,13 @@ export default function Navbar() {
|
|||||||
{/* CTA desktop */}
|
{/* CTA desktop */}
|
||||||
<div className="hidden md:block">
|
<div className="hidden md:block">
|
||||||
<a
|
<a
|
||||||
href="tel:0674453089"
|
href={`tel:${phoneRaw}`}
|
||||||
className="inline-flex items-center gap-2 bg-orange text-white font-bold text-sm px-5 py-2.5 rounded-xl hover:bg-orange-hover transition-colors pulse-glow"
|
className="inline-flex items-center gap-2 bg-orange text-white font-bold text-sm px-5 py-2.5 rounded-xl hover:bg-orange-hover transition-colors"
|
||||||
>
|
>
|
||||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||||
</svg>
|
</svg>
|
||||||
06 74 45 30 89
|
{phone}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -80,7 +75,7 @@ export default function Navbar() {
|
|||||||
{/* Mobile menu */}
|
{/* Mobile menu */}
|
||||||
{open && (
|
{open && (
|
||||||
<div className="md:hidden border-t border-border py-4 space-y-1">
|
<div className="md:hidden border-t border-border py-4 space-y-1">
|
||||||
{navLinks.map((link) => (
|
{nav.map((link) => (
|
||||||
<Link
|
<Link
|
||||||
key={link.href}
|
key={link.href}
|
||||||
href={link.href}
|
href={link.href}
|
||||||
@@ -92,14 +87,14 @@ export default function Navbar() {
|
|||||||
))}
|
))}
|
||||||
<div className="pt-2">
|
<div className="pt-2">
|
||||||
<a
|
<a
|
||||||
href="tel:0674453089"
|
href={`tel:${phoneRaw}`}
|
||||||
onClick={() => setOpen(false)}
|
onClick={() => setOpen(false)}
|
||||||
className="flex items-center justify-center gap-2 bg-orange text-white font-bold text-sm px-5 py-3 rounded-xl mt-2"
|
className="flex items-center justify-center gap-2 bg-orange text-white font-bold text-sm px-5 py-3 rounded-xl mt-2"
|
||||||
>
|
>
|
||||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||||
</svg>
|
</svg>
|
||||||
Appeler Benoît — 06 74 45 30 89
|
{phone}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
85
lib/content.ts
Normal file
85
lib/content.ts
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
// lib/content.ts
|
||||||
|
// Couche d'abstraction entre les données et les composants.
|
||||||
|
//
|
||||||
|
// AUJOURD'HUI : lit siteConfig (données statiques en JSON)
|
||||||
|
// DEMAIN : remplacer chaque return par un appel Payload CMS
|
||||||
|
// Les composants n'ont JAMAIS à changer.
|
||||||
|
//
|
||||||
|
// Exemple de migration future :
|
||||||
|
// - return siteConfig.services
|
||||||
|
// + return await payload.find({ collection: 'services' }).then(r => r.docs)
|
||||||
|
|
||||||
|
import { siteConfig } from "./site-config";
|
||||||
|
import type {
|
||||||
|
Service,
|
||||||
|
Realisation,
|
||||||
|
Testimonial,
|
||||||
|
FAQItem,
|
||||||
|
BlogPost,
|
||||||
|
Partner,
|
||||||
|
NavItem,
|
||||||
|
} from "@/types/content";
|
||||||
|
|
||||||
|
// ── Navigation ────────────────────────────────────────────────
|
||||||
|
export async function getNavItems(): Promise<NavItem[]> {
|
||||||
|
// FUTURE: return await payload.findGlobal({ slug: 'navigation' })
|
||||||
|
return [...siteConfig.nav];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Config globale ────────────────────────────────────────────
|
||||||
|
export async function getSiteConfig() {
|
||||||
|
// FUTURE: return await payload.findGlobal({ slug: 'site-settings' })
|
||||||
|
return siteConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Services ──────────────────────────────────────────────────
|
||||||
|
export async function getServices(): Promise<Service[]> {
|
||||||
|
// FUTURE: return await payload.find({ collection: 'services', sort: 'order' }).then(r => r.docs)
|
||||||
|
return [...siteConfig.services];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getServiceBySlug(slug: string): Promise<Service | null> {
|
||||||
|
// FUTURE: return await payload.find({ collection: 'services', where: { slug: { equals: slug } } }).then(r => r.docs[0] ?? null)
|
||||||
|
return siteConfig.services.find((s) => s.slug === slug) ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Réalisations ──────────────────────────────────────────────
|
||||||
|
export async function getRealisations(): Promise<Realisation[]> {
|
||||||
|
// FUTURE: return await payload.find({ collection: 'realisations', sort: '-publishedAt' }).then(r => r.docs)
|
||||||
|
return [...siteConfig.realisations];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Témoignages ───────────────────────────────────────────────
|
||||||
|
export async function getTestimonials(): Promise<Testimonial[]> {
|
||||||
|
// FUTURE: return await payload.find({ collection: 'testimonials', where: { featured: { equals: true } } }).then(r => r.docs)
|
||||||
|
return [...siteConfig.testimonials];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── FAQ ───────────────────────────────────────────────────────
|
||||||
|
export async function getFAQ(): Promise<FAQItem[]> {
|
||||||
|
// FUTURE: return await payload.find({ collection: 'faq', sort: 'order' }).then(r => r.docs)
|
||||||
|
return [...siteConfig.faq];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Partenaires ───────────────────────────────────────────────
|
||||||
|
export async function getPartners(): Promise<Partner[]> {
|
||||||
|
// FUTURE: return await payload.find({ collection: 'partners', sort: 'order' }).then(r => r.docs)
|
||||||
|
return [...siteConfig.partners];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Blog ──────────────────────────────────────────────────────
|
||||||
|
export async function getBlogPosts(): Promise<BlogPost[]> {
|
||||||
|
// FUTURE: return await payload.find({ collection: 'articles', where: { status: { equals: 'published' } }, sort: '-publishedAt' }).then(r => r.docs)
|
||||||
|
return [...siteConfig.blogPosts];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getBlogPost(slug: string): Promise<BlogPost | null> {
|
||||||
|
// FUTURE: return await payload.find({ collection: 'articles', where: { slug: { equals: slug } } }).then(r => r.docs[0] ?? null)
|
||||||
|
return siteConfig.blogPosts.find((p) => p.slug === slug) ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Valeurs / Piliers ─────────────────────────────────────────
|
||||||
|
export async function getValues() {
|
||||||
|
// FUTURE: return await payload.find({ collection: 'values', sort: 'order' }).then(r => r.docs)
|
||||||
|
return [...siteConfig.values];
|
||||||
|
}
|
||||||
380
lib/site-config.ts
Normal file
380
lib/site-config.ts
Normal file
@@ -0,0 +1,380 @@
|
|||||||
|
// lib/site-config.ts
|
||||||
|
// Source unique de vérité pour toutes les données du site OBC Maçonnerie.
|
||||||
|
// Toute modification de contenu (textes, services, FAQ...) se fait ICI.
|
||||||
|
// Les composants consomment ces données via lib/content.ts — jamais en dur.
|
||||||
|
|
||||||
|
export const siteConfig = {
|
||||||
|
name: "OBC Maçonnerie",
|
||||||
|
dirigeant: "Benoît Colin",
|
||||||
|
phone: "06 74 45 30 89",
|
||||||
|
phoneRaw: "0674453089",
|
||||||
|
email: "contact@obc-terrassement.fr",
|
||||||
|
address: "221 Route de Saint-Amand, 59310 Mouchin",
|
||||||
|
addressLine1: "221 Route de Saint-Amand",
|
||||||
|
addressLocality: "Mouchin",
|
||||||
|
addressPostalCode: "59310",
|
||||||
|
addressRegion: "Hauts-de-France",
|
||||||
|
addressCountry: "FR",
|
||||||
|
siren: "531827871",
|
||||||
|
url: "https://obc-terrassement.fr",
|
||||||
|
|
||||||
|
zones: [
|
||||||
|
"Orchies",
|
||||||
|
"Mouchin",
|
||||||
|
"Flines-lès-Raches",
|
||||||
|
"Château-l'Abbaye",
|
||||||
|
"Mérignies",
|
||||||
|
"Douai",
|
||||||
|
"Valenciennes",
|
||||||
|
"Saint-Amand-les-Eaux",
|
||||||
|
],
|
||||||
|
zoneDescription: "20 à 30 km autour de Mouchin (Nord 59)",
|
||||||
|
|
||||||
|
nav: [
|
||||||
|
{ label: "Accueil", href: "/" },
|
||||||
|
{ label: "Services", href: "/services" },
|
||||||
|
{ label: "Réalisations", href: "/realisations" },
|
||||||
|
{ label: "Blog", href: "/blog" },
|
||||||
|
{ label: "Contact", href: "/contact" },
|
||||||
|
],
|
||||||
|
|
||||||
|
footerServicesNav: [
|
||||||
|
{ label: "Construction de maison", href: "/construction-maison" },
|
||||||
|
{ label: "Rénovation", href: "/renovation" },
|
||||||
|
{ label: "Assainissement", href: "/assainissement" },
|
||||||
|
{ label: "Création d'accès", href: "/creation-acces" },
|
||||||
|
{ label: "Démolition", href: "/demolition" },
|
||||||
|
],
|
||||||
|
|
||||||
|
footerMainNav: [
|
||||||
|
{ label: "Accueil", href: "/" },
|
||||||
|
{ label: "Réalisations", href: "/realisations" },
|
||||||
|
{ label: "Partenaires", href: "/partenaires" },
|
||||||
|
{ label: "Contact", href: "/contact" },
|
||||||
|
{ label: "Blog", href: "/blog" },
|
||||||
|
],
|
||||||
|
|
||||||
|
footerLegalNav: [
|
||||||
|
{ label: "Mentions légales", href: "/mentions-legales" },
|
||||||
|
{ label: "Confidentialité", href: "/confidentialite" },
|
||||||
|
{ label: "CGV", href: "/cgv" },
|
||||||
|
],
|
||||||
|
|
||||||
|
seo: {
|
||||||
|
title: "OBC Maçonnerie | Constructeur & Maçon à Orchies (Nord 59)",
|
||||||
|
description:
|
||||||
|
"Benoît Colin, maçon expert à Mouchin. Construction de maison, rénovation, assainissement et gros œuvre dans un rayon de 30km autour d'Orchies. Devis gratuit.",
|
||||||
|
},
|
||||||
|
|
||||||
|
hero: {
|
||||||
|
title: "Maçon & Constructeur dans le Nord",
|
||||||
|
subtitle:
|
||||||
|
"Construction de maison, rénovation, assainissement et gros œuvre — expertise autour d'Orchies",
|
||||||
|
cta: "Demander un devis gratuit",
|
||||||
|
ctaSecondary: "Voir nos réalisations",
|
||||||
|
badge:
|
||||||
|
"Disponible, à l'écoute, Benoît vous accompagne de la première pierre à la remise des clés",
|
||||||
|
stats: [
|
||||||
|
{ val: "15+", label: "ans d'expérience" },
|
||||||
|
{ val: "200+", label: "chantiers réalisés" },
|
||||||
|
{ val: "30km", label: "de rayon d'action" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
services: [
|
||||||
|
{
|
||||||
|
slug: "construction-maison",
|
||||||
|
title: "Construction de maison",
|
||||||
|
shortDescription:
|
||||||
|
"Fondations, ossature bois, gros œuvre — on bâtit votre projet de A à Z avec vous.",
|
||||||
|
longDescription:
|
||||||
|
"De la conception des fondations à la pose du toit, Benoît vous accompagne à chaque étape de votre construction. Maison individuelle, ossature bois, béton banché — chaque projet est unique.",
|
||||||
|
icon: "🏠",
|
||||||
|
keywords: [
|
||||||
|
"construction maison Nord",
|
||||||
|
"maçon construction maison Orchies",
|
||||||
|
"fondation ossature bois Nord",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: "renovation",
|
||||||
|
title: "Rénovation",
|
||||||
|
shortDescription:
|
||||||
|
"Maison ou appartement, on s'adapte à votre projet et vos envies.",
|
||||||
|
longDescription:
|
||||||
|
"Rénovation partielle ou complète, intérieure et extérieure. Benoît adapte chaque projet à votre budget et vos envies. Restructuration, création d'ouvertures, extension.",
|
||||||
|
icon: "🔨",
|
||||||
|
keywords: [
|
||||||
|
"rénovation maison Nord 59",
|
||||||
|
"maçon rénovation Douai",
|
||||||
|
"maçon rénovation Valenciennes",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: "assainissement",
|
||||||
|
title: "Assainissement",
|
||||||
|
shortDescription:
|
||||||
|
"Mise aux normes et création de systèmes d'assainissement fiables.",
|
||||||
|
longDescription:
|
||||||
|
"Installation et mise aux normes de vos systèmes d'assainissement individuel et collectif. Fosse toutes eaux, micro-station, épandage — dans les règles de l'art.",
|
||||||
|
icon: "💧",
|
||||||
|
keywords: [
|
||||||
|
"assainissement maison Nord",
|
||||||
|
"assainissement individuel Nord 59",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: "creation-acces",
|
||||||
|
title: "Création d'accès",
|
||||||
|
shortDescription: "Voiries, entrées, chemins — on crée vos accès sur mesure.",
|
||||||
|
longDescription:
|
||||||
|
"Création de voiries, entrées de propriété et chemins d'accès. Béton, béton imprimé, pavés, gravier stabilisé — travail soigné et durable.",
|
||||||
|
icon: "🚧",
|
||||||
|
keywords: [
|
||||||
|
"création accès maison Nord",
|
||||||
|
"voirie entrée propriété Nord 59",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: "demolition",
|
||||||
|
title: "Démolition",
|
||||||
|
shortDescription:
|
||||||
|
"Démolition totale ou partielle, avec toutes les garanties de sécurité.",
|
||||||
|
longDescription:
|
||||||
|
"Démolition de bâtiments, murs et ouvrages en toute sécurité. Évacuation des gravats incluse. Préparation du terrain pour votre future construction.",
|
||||||
|
icon: "🏗️",
|
||||||
|
keywords: [
|
||||||
|
"démolition maison Nord 59",
|
||||||
|
"démolition bâtiment Nord",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: "conseil",
|
||||||
|
title: "Conseil & Accompagnement",
|
||||||
|
shortDescription:
|
||||||
|
"Benoît vous éclaire dans vos choix : matériaux, plans, adaptations — on réfléchit ensemble.",
|
||||||
|
longDescription:
|
||||||
|
"Un seul interlocuteur pour tout votre projet. Benoît analyse votre plan, vous conseille sur les matériaux et coordonne les artisans partenaires.",
|
||||||
|
icon: "🤝",
|
||||||
|
keywords: [
|
||||||
|
"entrepreneur maçon Nord 59",
|
||||||
|
"gros œuvre Nord",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
title: "Proche de vous",
|
||||||
|
description:
|
||||||
|
"Disponible, à l'écoute. Benoît se déplace sur votre chantier pour comprendre votre projet et vous proposer les meilleures solutions.",
|
||||||
|
icon: "📍",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Conseil expert",
|
||||||
|
description:
|
||||||
|
"Il vous guide dans vos choix de matériaux, adapte les plans d'architecte, suggère des améliorations auxquelles vous n'avez pas pensé.",
|
||||||
|
icon: "💡",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Acteur de confiance",
|
||||||
|
description:
|
||||||
|
"Transparent à chaque étape, il vous rassure et vous explique chaque décision. Pas de surprise, pas de mauvaise nouvelle.",
|
||||||
|
icon: "🛡️",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Passionné du métier",
|
||||||
|
description:
|
||||||
|
"On ne fait jamais deux fois la même maison. Benoît réfléchit avec vous pour que le résultat vous ressemble.",
|
||||||
|
icon: "❤️",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
partners: [
|
||||||
|
{ label: "Électricité", icon: "⚡", desc: "Installation électrique aux normes NF C 15-100, tableau de distribution, prises, éclairage." },
|
||||||
|
{ label: "Plomberie", icon: "🔧", desc: "Plomberie sanitaire, chauffage central, installation de salles de bains et cuisines." },
|
||||||
|
{ label: "Charpente", icon: "🪵", desc: "Charpente traditionnelle ou industrielle, structure bois pour combles aménageables ou non." },
|
||||||
|
{ label: "Couverture", icon: "🏚️", desc: "Pose de toiture, tuiles, ardoises, zinc — étanchéité et finitions soignées." },
|
||||||
|
{ label: "Isolation", icon: "🧱", desc: "Isolation thermique et phonique par l'intérieur ou l'extérieur, combles, planchers." },
|
||||||
|
{ label: "Menuiserie", icon: "🚪", desc: "Fenêtres, portes, vérandas, volets — menuiserie bois, PVC ou aluminium." },
|
||||||
|
{ label: "Carrelage", icon: "🔳", desc: "Pose de carrelage, parquet, faïence — pour sols et murs, intérieur et extérieur." },
|
||||||
|
{ label: "Peinture", icon: "🎨", desc: "Peinture intérieure et extérieure, enduits décoratifs, ravalement de façade." },
|
||||||
|
],
|
||||||
|
partnersTitle: "Seul on va vite, ensemble on va plus loin.",
|
||||||
|
partnersMessage:
|
||||||
|
"Grâce à notre réseau de partenaires de confiance, nous coordonnons l'ensemble des corps de métier pour que votre maison prenne forme de A à Z.",
|
||||||
|
|
||||||
|
faq: [
|
||||||
|
{
|
||||||
|
question: "Dans quelle zone intervenez-vous ?",
|
||||||
|
answer:
|
||||||
|
"Nous intervenons dans un rayon de 20 à 30 km autour de Mouchin (59310) : Orchies, Flines-lès-Raches, Château-l'Abbaye, Mérignies, Douai, Valenciennes, Saint-Amand-les-Eaux et les communes alentour.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Faites-vous des devis gratuits ?",
|
||||||
|
answer:
|
||||||
|
"Oui, le devis est gratuit et sans engagement. Benoît se déplace sur votre chantier pour évaluer votre projet et vous remettre une estimation détaillée.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Pouvez-vous adapter un plan d'architecte ?",
|
||||||
|
answer:
|
||||||
|
"Absolument. C'est même l'une de nos spécialités. Benoît analyse votre plan et vous suggère des adaptations pour optimiser l'espace, le rendu final et votre budget.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Combien de temps dure une construction de maison ?",
|
||||||
|
answer:
|
||||||
|
"En moyenne, comptez 10 à 18 mois pour une construction neuve selon la complexité du projet et les délais de livraison des matériaux. Benoît vous donnera un calendrier précis lors du devis.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Travaillez-vous avec d'autres artisans ?",
|
||||||
|
answer:
|
||||||
|
"Oui. Nous coordonnons un réseau de partenaires de confiance (électriciens, plombiers, charpentiers, couvreurs, menuisiers, carreleurs, peintres) pour vous livrer une maison complète avec un seul interlocuteur.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
testimonials: [
|
||||||
|
{
|
||||||
|
name: "Christophe & Marie L.",
|
||||||
|
ville: "Orchies",
|
||||||
|
service: "construction-maison",
|
||||||
|
text: "Benoît nous a accompagnés de A à Z dans la construction de notre maison. Il a su adapter le plan d'architecte à nos envies tout en respectant notre budget. Disponible, professionnel, et vraiment à l'écoute. On recommande les yeux fermés.",
|
||||||
|
rating: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Sophie D.",
|
||||||
|
ville: "Douai",
|
||||||
|
service: "renovation",
|
||||||
|
text: "On lui a confié la rénovation complète de notre maison de 1970. Benoît a pris le temps de tout nous expliquer, a proposé des solutions auxquelles on n'avait pas pensé, et le résultat est magnifique. Un vrai professionnel.",
|
||||||
|
rating: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Famille Moreau",
|
||||||
|
ville: "Saint-Amand-les-Eaux",
|
||||||
|
service: "assainissement",
|
||||||
|
text: "Mise aux normes de notre système d'assainissement réalisée dans les délais et en toute transparence. Benoît nous a expliqué chaque étape. Très sérieux et propre dans son travail.",
|
||||||
|
rating: 5,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
realisations: [
|
||||||
|
{
|
||||||
|
title: "Maison individuelle à Orchies",
|
||||||
|
ville: "Orchies (59)",
|
||||||
|
service: "construction-maison",
|
||||||
|
categorie: "Construction neuve",
|
||||||
|
description:
|
||||||
|
"Construction d'une maison de 130 m² — fondations, gros œuvre, dalle béton et ossature.",
|
||||||
|
color: "bg-navy",
|
||||||
|
image: "/images/realisations/chantier-1.jpg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Rénovation complète à Douai",
|
||||||
|
ville: "Douai (59)",
|
||||||
|
service: "renovation",
|
||||||
|
categorie: "Rénovation",
|
||||||
|
description:
|
||||||
|
"Restructuration intérieure complète d'une maison de ville : abattage de cloisons, création d'un escalier neuf, doublages.",
|
||||||
|
color: "bg-stone",
|
||||||
|
image: "/images/realisations/chantier-2.jpg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Mise aux normes à Saint-Amand",
|
||||||
|
ville: "Saint-Amand-les-Eaux (59)",
|
||||||
|
service: "assainissement",
|
||||||
|
categorie: "Assainissement",
|
||||||
|
description:
|
||||||
|
"Remplacement d'une fosse septique vétuste par une micro-station d'épuration conforme aux normes.",
|
||||||
|
color: "bg-navy-light",
|
||||||
|
image: "/images/realisations/chantier-3.jpg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Entrée en béton imprimé à Mérignies",
|
||||||
|
ville: "Mérignies (59)",
|
||||||
|
service: "creation-acces",
|
||||||
|
categorie: "Création d'accès",
|
||||||
|
description:
|
||||||
|
"Création d'une entrée de propriété en béton imprimé effet pavés, avec caniveau de drainage.",
|
||||||
|
color: "bg-orange",
|
||||||
|
image: "/images/realisations/chantier-4.jpg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Extension ossature bois à Flines",
|
||||||
|
ville: "Flines-lès-Raches (59)",
|
||||||
|
service: "construction-maison",
|
||||||
|
categorie: "Construction neuve",
|
||||||
|
description:
|
||||||
|
"Agrandissement d'une maison existante par extension ossature bois, fondations et dalle.",
|
||||||
|
color: "bg-navy",
|
||||||
|
image: "/images/realisations/chantier-5.jpg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Démolition & reconstruction à Valenciennes",
|
||||||
|
ville: "Valenciennes (59)",
|
||||||
|
service: "demolition",
|
||||||
|
categorie: "Démolition",
|
||||||
|
description:
|
||||||
|
"Démolition d'un bâtiment annexe et curage d'une grange pour préparer une rénovation complète.",
|
||||||
|
color: "bg-stone",
|
||||||
|
image: "/images/realisations/chantier-6.jpg",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
blogPosts: [
|
||||||
|
{
|
||||||
|
slug: "combien-coute-construction-maison-nord",
|
||||||
|
titre: "Combien coûte la construction d'une maison dans le Nord en 2025 ?",
|
||||||
|
extrait:
|
||||||
|
"Budget, matériaux, terrain, main-d'œuvre — tout ce qu'il faut savoir pour estimer le coût de votre construction neuve dans le Nord.",
|
||||||
|
cat: "Construction",
|
||||||
|
date: "15 février 2025",
|
||||||
|
readTime: "6 min",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: "etapes-renovation-maison-ancienne",
|
||||||
|
titre: "Les étapes clés d'une rénovation de maison ancienne",
|
||||||
|
extrait:
|
||||||
|
"Vous avez acheté une maison ancienne dans le Nord et vous voulez la rénover ? Voici les étapes indispensables pour réussir votre projet.",
|
||||||
|
cat: "Rénovation",
|
||||||
|
date: "8 janvier 2025",
|
||||||
|
readTime: "5 min",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: "assainissement-non-collectif-obligations",
|
||||||
|
titre: "Assainissement non collectif : vos obligations légales",
|
||||||
|
extrait:
|
||||||
|
"Contrôle SPANC, mise aux normes, vente immobilière — tout ce que vous devez savoir sur l'assainissement non collectif.",
|
||||||
|
cat: "Assainissement",
|
||||||
|
date: "20 décembre 2024",
|
||||||
|
readTime: "4 min",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: "ossature-bois-avantages",
|
||||||
|
titre: "Ossature bois : pourquoi choisir ce mode constructif ?",
|
||||||
|
extrait:
|
||||||
|
"Légèreté, performance thermique, rapidité de construction — l'ossature bois a de nombreux avantages. OBC Maçonnerie vous explique.",
|
||||||
|
cat: "Construction",
|
||||||
|
date: "5 novembre 2024",
|
||||||
|
readTime: "5 min",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: "travaux-renovation-sans-permis-construction",
|
||||||
|
titre: "Quels travaux de rénovation ne nécessitent pas de permis ?",
|
||||||
|
extrait:
|
||||||
|
"Permis de construire, déclaration préalable, simple déclaration — on vous explique les règles selon la nature de vos travaux.",
|
||||||
|
cat: "Rénovation",
|
||||||
|
date: "18 octobre 2024",
|
||||||
|
readTime: "4 min",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: "fondations-maison-quels-types",
|
||||||
|
titre: "Les différents types de fondations pour une maison",
|
||||||
|
extrait:
|
||||||
|
"Semelles filantes, radier, pieux — quelles fondations choisir selon votre terrain et votre projet de construction ?",
|
||||||
|
cat: "Construction",
|
||||||
|
date: "2 septembre 2024",
|
||||||
|
readTime: "5 min",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type SiteConfig = typeof siteConfig;
|
||||||
54
payload/README.md
Normal file
54
payload/README.md
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# Payload CMS — Préparation
|
||||||
|
|
||||||
|
Ce dossier contient les schémas Payload CMS commentés, prêts à être activés
|
||||||
|
quand le projet bascule de contenu statique vers un CMS administrable.
|
||||||
|
|
||||||
|
## Architecture cible
|
||||||
|
|
||||||
|
```
|
||||||
|
payload/
|
||||||
|
├── collections/
|
||||||
|
│ ├── Articles.ts → Articles de blog
|
||||||
|
│ ├── Realisations.ts → Galerie chantiers
|
||||||
|
│ ├── Services.ts → Services proposés
|
||||||
|
│ ├── Testimonials.ts → Avis clients
|
||||||
|
│ └── FAQ.ts → Questions fréquentes
|
||||||
|
└── globals/
|
||||||
|
└── SiteSettings.ts → Paramètres globaux du site
|
||||||
|
```
|
||||||
|
|
||||||
|
## Migration (3 étapes)
|
||||||
|
|
||||||
|
### Étape 1 — Installer Payload CMS
|
||||||
|
```bash
|
||||||
|
npm install payload @payloadcms/db-postgres @payloadcms/richtext-lexical
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 2 — Activer les collections
|
||||||
|
Décommenter le code dans chaque fichier `collections/*.ts` et `globals/*.ts`,
|
||||||
|
puis créer `payload.config.ts` à la racine :
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { buildConfig } from 'payload'
|
||||||
|
import { Services } from './payload/collections/Services'
|
||||||
|
import { Realisations } from './payload/collections/Realisations'
|
||||||
|
import { Articles } from './payload/collections/Articles'
|
||||||
|
import { Testimonials } from './payload/collections/Testimonials'
|
||||||
|
import { FAQ } from './payload/collections/FAQ'
|
||||||
|
import { SiteSettings } from './payload/globals/SiteSettings'
|
||||||
|
|
||||||
|
export default buildConfig({
|
||||||
|
collections: [Services, Realisations, Articles, Testimonials, FAQ],
|
||||||
|
globals: [SiteSettings],
|
||||||
|
// ...db, admin, etc.
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 3 — Mettre à jour lib/content.ts
|
||||||
|
Remplacer les `return siteConfig.xxx` par les appels Payload commentés.
|
||||||
|
**Les composants n'ont pas à changer.**
|
||||||
|
|
||||||
|
## Données actuelles
|
||||||
|
|
||||||
|
Toutes les données sont dans `lib/site-config.ts`.
|
||||||
|
Les composants les consomment via `lib/content.ts`.
|
||||||
94
payload/collections/Articles.ts
Normal file
94
payload/collections/Articles.ts
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
// payload/collections/Articles.ts
|
||||||
|
// Schéma Payload CMS pour les articles de blog.
|
||||||
|
// COMMENTÉ — activé lors de la migration vers Payload.
|
||||||
|
|
||||||
|
/*
|
||||||
|
import type { CollectionConfig } from 'payload'
|
||||||
|
import { lexicalEditor } from '@payloadcms/richtext-lexical'
|
||||||
|
|
||||||
|
export const Articles: CollectionConfig = {
|
||||||
|
slug: 'articles',
|
||||||
|
admin: {
|
||||||
|
useAsTitle: 'title',
|
||||||
|
defaultColumns: ['title', 'category', 'status', 'publishedAt'],
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'title',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Titre de l\'article',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'slug',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
unique: true,
|
||||||
|
label: 'URL (slug)',
|
||||||
|
admin: {
|
||||||
|
description: 'ex: combien-coute-construction-maison-nord',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'excerpt',
|
||||||
|
type: 'textarea',
|
||||||
|
label: 'Extrait (meta description)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'content',
|
||||||
|
type: 'richText',
|
||||||
|
editor: lexicalEditor(),
|
||||||
|
label: 'Contenu complet',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'category',
|
||||||
|
type: 'select',
|
||||||
|
options: [
|
||||||
|
{ label: 'Construction', value: 'construction' },
|
||||||
|
{ label: 'Rénovation', value: 'renovation' },
|
||||||
|
{ label: 'Assainissement', value: 'assainissement' },
|
||||||
|
{ label: 'Conseils', value: 'conseils' },
|
||||||
|
],
|
||||||
|
label: 'Catégorie',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'publishedAt',
|
||||||
|
type: 'date',
|
||||||
|
label: 'Date de publication',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'status',
|
||||||
|
type: 'select',
|
||||||
|
options: [
|
||||||
|
{ label: 'Brouillon', value: 'draft' },
|
||||||
|
{ label: 'Publié', value: 'published' },
|
||||||
|
],
|
||||||
|
defaultValue: 'draft',
|
||||||
|
label: 'Statut',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'seoTitle',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Titre SEO (optionnel — remplace title)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'seoDescription',
|
||||||
|
type: 'textarea',
|
||||||
|
label: 'Description SEO (optionnel — remplace excerpt)',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type PayloadArticle = {
|
||||||
|
id: string;
|
||||||
|
slug: string;
|
||||||
|
title: string;
|
||||||
|
excerpt: string;
|
||||||
|
content: unknown; // Lexical rich text
|
||||||
|
category: string;
|
||||||
|
publishedAt: string;
|
||||||
|
status: "draft" | "published";
|
||||||
|
seoTitle?: string;
|
||||||
|
seoDescription?: string;
|
||||||
|
};
|
||||||
42
payload/collections/FAQ.ts
Normal file
42
payload/collections/FAQ.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// payload/collections/FAQ.ts
|
||||||
|
// Schéma Payload CMS pour la FAQ.
|
||||||
|
// COMMENTÉ — activé lors de la migration vers Payload.
|
||||||
|
|
||||||
|
/*
|
||||||
|
import type { CollectionConfig } from 'payload'
|
||||||
|
|
||||||
|
export const FAQ: CollectionConfig = {
|
||||||
|
slug: 'faq',
|
||||||
|
admin: {
|
||||||
|
useAsTitle: 'question',
|
||||||
|
defaultColumns: ['question', 'order'],
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'question',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Question',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'answer',
|
||||||
|
type: 'textarea',
|
||||||
|
required: true,
|
||||||
|
label: 'Réponse',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'order',
|
||||||
|
type: 'number',
|
||||||
|
label: 'Ordre d\'affichage',
|
||||||
|
defaultValue: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type PayloadFAQItem = {
|
||||||
|
id: string;
|
||||||
|
question: string;
|
||||||
|
answer: string;
|
||||||
|
order: number;
|
||||||
|
};
|
||||||
84
payload/collections/Realisations.ts
Normal file
84
payload/collections/Realisations.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
// payload/collections/Realisations.ts
|
||||||
|
// Schéma Payload CMS pour les réalisations / portfolio.
|
||||||
|
// COMMENTÉ — activé lors de la migration vers Payload.
|
||||||
|
|
||||||
|
/*
|
||||||
|
import type { CollectionConfig } from 'payload'
|
||||||
|
|
||||||
|
export const Realisations: CollectionConfig = {
|
||||||
|
slug: 'realisations',
|
||||||
|
admin: {
|
||||||
|
useAsTitle: 'title',
|
||||||
|
defaultColumns: ['title', 'ville', 'service', 'publishedAt'],
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'title',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Titre du chantier',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ville',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Ville',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'service',
|
||||||
|
type: 'relationship',
|
||||||
|
relationTo: 'services',
|
||||||
|
label: 'Service associé',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'description',
|
||||||
|
type: 'textarea',
|
||||||
|
label: 'Description courte',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'image',
|
||||||
|
type: 'upload',
|
||||||
|
relationTo: 'media',
|
||||||
|
label: 'Photo principale',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'gallery',
|
||||||
|
type: 'array',
|
||||||
|
label: 'Galerie photos',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'image',
|
||||||
|
type: 'upload',
|
||||||
|
relationTo: 'media',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'caption',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'featured',
|
||||||
|
type: 'checkbox',
|
||||||
|
label: 'Mettre en avant (page accueil)',
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'publishedAt',
|
||||||
|
type: 'date',
|
||||||
|
label: 'Date du chantier',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type PayloadRealisation = {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
ville: string;
|
||||||
|
service: string;
|
||||||
|
description: string;
|
||||||
|
image: string;
|
||||||
|
featured: boolean;
|
||||||
|
publishedAt: string;
|
||||||
|
};
|
||||||
78
payload/collections/Services.ts
Normal file
78
payload/collections/Services.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// payload/collections/Services.ts
|
||||||
|
// Schéma Payload CMS pour les services OBC Maçonnerie.
|
||||||
|
// COMMENTÉ — activé lors de la migration vers Payload.
|
||||||
|
//
|
||||||
|
// Pour activer : décommenter et importer dans payload.config.ts
|
||||||
|
|
||||||
|
/*
|
||||||
|
import type { CollectionConfig } from 'payload'
|
||||||
|
|
||||||
|
export const Services: CollectionConfig = {
|
||||||
|
slug: 'services',
|
||||||
|
admin: {
|
||||||
|
useAsTitle: 'title',
|
||||||
|
defaultColumns: ['title', 'slug', 'updatedAt'],
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'slug',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
unique: true,
|
||||||
|
admin: { description: 'Identifiant URL (ex: construction-maison)' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'title',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Titre du service',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'shortDescription',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Description courte (carte home page)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'longDescription',
|
||||||
|
type: 'textarea',
|
||||||
|
label: 'Description longue (page dédiée)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'icon',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Emoji icône',
|
||||||
|
admin: { description: 'ex: 🏠' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'keywords',
|
||||||
|
type: 'array',
|
||||||
|
label: 'Mots-clés SEO',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'keyword',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'order',
|
||||||
|
type: 'number',
|
||||||
|
label: 'Ordre d\'affichage',
|
||||||
|
defaultValue: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Type exporté pour l'autocomplétion — reste actif même sans Payload
|
||||||
|
export type PayloadService = {
|
||||||
|
id: string;
|
||||||
|
slug: string;
|
||||||
|
title: string;
|
||||||
|
shortDescription: string;
|
||||||
|
longDescription: string;
|
||||||
|
icon: string;
|
||||||
|
keywords: { keyword: string }[];
|
||||||
|
order: number;
|
||||||
|
};
|
||||||
64
payload/collections/Testimonials.ts
Normal file
64
payload/collections/Testimonials.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// payload/collections/Testimonials.ts
|
||||||
|
// Schéma Payload CMS pour les témoignages clients.
|
||||||
|
// COMMENTÉ — activé lors de la migration vers Payload.
|
||||||
|
|
||||||
|
/*
|
||||||
|
import type { CollectionConfig } from 'payload'
|
||||||
|
|
||||||
|
export const Testimonials: CollectionConfig = {
|
||||||
|
slug: 'testimonials',
|
||||||
|
admin: {
|
||||||
|
useAsTitle: 'name',
|
||||||
|
defaultColumns: ['name', 'ville', 'service', 'rating', 'featured'],
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
required: true,
|
||||||
|
label: 'Nom du client',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ville',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Ville',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'service',
|
||||||
|
type: 'relationship',
|
||||||
|
relationTo: 'services',
|
||||||
|
label: 'Service concerné',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'text',
|
||||||
|
type: 'textarea',
|
||||||
|
required: true,
|
||||||
|
label: 'Témoignage',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'rating',
|
||||||
|
type: 'number',
|
||||||
|
min: 1,
|
||||||
|
max: 5,
|
||||||
|
defaultValue: 5,
|
||||||
|
label: 'Note (1 à 5)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'featured',
|
||||||
|
type: 'checkbox',
|
||||||
|
label: 'Afficher sur la page d\'accueil',
|
||||||
|
defaultValue: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type PayloadTestimonial = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
ville: string;
|
||||||
|
service: string;
|
||||||
|
text: string;
|
||||||
|
rating: number;
|
||||||
|
featured: boolean;
|
||||||
|
};
|
||||||
95
payload/globals/SiteSettings.ts
Normal file
95
payload/globals/SiteSettings.ts
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
// payload/globals/SiteSettings.ts
|
||||||
|
// Schéma Payload CMS pour les paramètres globaux du site.
|
||||||
|
// COMMENTÉ — activé lors de la migration vers Payload.
|
||||||
|
//
|
||||||
|
// Permet à Benoît (ou à un admin) de modifier les infos
|
||||||
|
// de contact, le texte du hero, etc. sans toucher au code.
|
||||||
|
|
||||||
|
/*
|
||||||
|
import type { GlobalConfig } from 'payload'
|
||||||
|
|
||||||
|
export const SiteSettings: GlobalConfig = {
|
||||||
|
slug: 'site-settings',
|
||||||
|
admin: {
|
||||||
|
group: 'Paramètres',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
// ── Informations de contact ───────────────────────────────
|
||||||
|
{
|
||||||
|
name: 'contact',
|
||||||
|
type: 'group',
|
||||||
|
label: 'Contact',
|
||||||
|
fields: [
|
||||||
|
{ name: 'phone', type: 'text', label: 'Téléphone' },
|
||||||
|
{ name: 'email', type: 'email', label: 'Email' },
|
||||||
|
{ name: 'address', type: 'text', label: 'Adresse complète' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// ── Hero page d'accueil ───────────────────────────────────
|
||||||
|
{
|
||||||
|
name: 'hero',
|
||||||
|
type: 'group',
|
||||||
|
label: 'Section Hero (page d\'accueil)',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', label: 'Titre H1' },
|
||||||
|
{ name: 'subtitle', type: 'textarea', label: 'Sous-titre' },
|
||||||
|
{ name: 'badge', type: 'text', label: 'Badge/accroche' },
|
||||||
|
{ name: 'cta', type: 'text', label: 'CTA principal' },
|
||||||
|
{ name: 'ctaSecondary', type: 'text', label: 'CTA secondaire' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// ── Zone d'intervention ────────────────────────────────────
|
||||||
|
{
|
||||||
|
name: 'zones',
|
||||||
|
type: 'array',
|
||||||
|
label: 'Villes d\'intervention',
|
||||||
|
fields: [
|
||||||
|
{ name: 'city', type: 'text', label: 'Ville' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'zoneDescription',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Description zone (ex: 20 à 30 km autour de Mouchin)',
|
||||||
|
},
|
||||||
|
// ── SEO global ────────────────────────────────────────────
|
||||||
|
{
|
||||||
|
name: 'seo',
|
||||||
|
type: 'group',
|
||||||
|
label: 'SEO global',
|
||||||
|
fields: [
|
||||||
|
{ name: 'title', type: 'text', label: 'Titre SEO par défaut' },
|
||||||
|
{ name: 'description', type: 'textarea', label: 'Description SEO par défaut' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// ── Message partenaires ───────────────────────────────────
|
||||||
|
{
|
||||||
|
name: 'partnersMessage',
|
||||||
|
type: 'textarea',
|
||||||
|
label: 'Message section partenaires',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type PayloadSiteSettings = {
|
||||||
|
contact: {
|
||||||
|
phone: string;
|
||||||
|
email: string;
|
||||||
|
address: string;
|
||||||
|
};
|
||||||
|
hero: {
|
||||||
|
title: string;
|
||||||
|
subtitle: string;
|
||||||
|
badge: string;
|
||||||
|
cta: string;
|
||||||
|
ctaSecondary: string;
|
||||||
|
};
|
||||||
|
zones: { city: string }[];
|
||||||
|
zoneDescription: string;
|
||||||
|
seo: {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
partnersMessage: string;
|
||||||
|
};
|
||||||
62
types/content.ts
Normal file
62
types/content.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// types/content.ts
|
||||||
|
// Types partagés entre lib/content.ts et les composants.
|
||||||
|
// Ces types correspondent exactement aux schémas Payload CMS futurs
|
||||||
|
// définis dans /payload/collections/*.ts
|
||||||
|
|
||||||
|
export type NavItem = {
|
||||||
|
label: string;
|
||||||
|
href: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Service = {
|
||||||
|
slug: string;
|
||||||
|
title: string;
|
||||||
|
shortDescription: string;
|
||||||
|
longDescription: string;
|
||||||
|
icon: string;
|
||||||
|
keywords: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Realisation = {
|
||||||
|
title: string;
|
||||||
|
ville: string;
|
||||||
|
service: string;
|
||||||
|
categorie: string;
|
||||||
|
description: string;
|
||||||
|
color: string;
|
||||||
|
image: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Testimonial = {
|
||||||
|
name: string;
|
||||||
|
ville: string;
|
||||||
|
service: string;
|
||||||
|
text: string;
|
||||||
|
rating: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FAQItem = {
|
||||||
|
question: string;
|
||||||
|
answer: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Partner = {
|
||||||
|
label: string;
|
||||||
|
icon: string;
|
||||||
|
desc: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BlogPost = {
|
||||||
|
slug: string;
|
||||||
|
titre: string;
|
||||||
|
extrait: string;
|
||||||
|
cat: string;
|
||||||
|
date: string;
|
||||||
|
readTime: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Value = {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
icon: string;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user