feat: Transform HookLab to OBC Maçonnerie showcase site

Complete transformation of the Next.js project into a professional
showcase site for OBC Maçonnerie (Benoît Colin, maçon in Nord 59).

Key changes:
- Remove all HookLab/Sanity/Supabase/Stripe/admin/training infrastructure
- Full OBC Maçonnerie identity: logo, colors, contact info, SIREN
- Schema.org LocalBusiness structured data for Benoît Colin
- SEO metadata for all pages targeting Nord 59 keywords

New pages created (23 total):
- Home page with 10 sections (hero, services, pillars, partners,
  zone, realisations, testimonials, FAQ, contact form, footer)
- Service pages: construction-maison, renovation, assainissement,
  creation-acces, demolition, services
- Secondary pages: realisations, partenaires, contact
- Blog: listing + 6 SEO articles with static content
- 8 local SEO pages: Orchies, Douai, Valenciennes, Mouchin,
  Flines-lès-Raches, Saint-Amand-les-Eaux
- Legal pages: mentions-legales, cgv, confidentialite (OBC adapted)

Components:
- Navbar with OBC branding + mobile menu
- Footer with dark navy theme, services + navigation links
- ContactForm client component (devis request)
- LocalSEOPage reusable component for local SEO pages
- CookieBanner updated with OBC cookie key

Config:
- layout.tsx: OBC metadata, Schema.org, no Sanity CDN
- globals.css: stone color variables added
- next.config.ts: removed Sanity CDN remotePatterns
- sitemap.ts: all 30 OBC pages
- robots.ts: allow all except /api/
- api/contact/route.ts: OBC devis email template

https://claude.ai/code/session_01Uec4iHjcPwB1pU41idWEdF
This commit is contained in:
Claude
2026-02-27 09:05:03 +00:00
parent 45d080197a
commit 3adcec00b7
113 changed files with 3134 additions and 11663 deletions

View File

@@ -1,218 +0,0 @@
// Types pour la base de données Supabase
export type Database = {
public: {
Tables: {
profiles: {
Row: {
id: string;
email: string;
full_name: string | null;
persona: "jeune" | "parent" | null;
stripe_customer_id: string | null;
subscription_status: "inactive" | "active" | "cancelled" | "paused";
subscription_tier: "coaching" | "suivi" | null;
subscription_end_date: string | null;
is_admin: boolean;
created_at: string;
updated_at: string;
};
Insert: {
id: string;
email: string;
full_name?: string | null;
persona?: "jeune" | "parent" | null;
stripe_customer_id?: string | null;
subscription_status?: "inactive" | "active" | "cancelled" | "paused";
subscription_tier?: "coaching" | "suivi" | null;
subscription_end_date?: string | null;
is_admin?: boolean;
created_at?: string;
updated_at?: string;
};
Update: {
id?: string;
email?: string;
full_name?: string | null;
persona?: "jeune" | "parent" | null;
stripe_customer_id?: string | null;
subscription_status?: "inactive" | "active" | "cancelled" | "paused";
subscription_tier?: "coaching" | "suivi" | null;
subscription_end_date?: string | null;
is_admin?: boolean;
updated_at?: string;
};
};
candidatures: {
Row: {
id: string;
email: string;
firstname: string;
phone: string;
persona: string;
age: number;
experience: string;
time_daily: string;
availability: string;
start_date: string;
motivation: string;
monthly_goal: string;
biggest_fear: string;
tiktok_username: string | null;
status: "pending" | "approved" | "rejected";
created_at: string;
};
Insert: {
id?: string;
email: string;
firstname: string;
phone: string;
persona: string;
age: number;
experience: string;
time_daily: string;
availability: string;
start_date: string;
motivation: string;
monthly_goal: string;
biggest_fear: string;
tiktok_username?: string | null;
status?: "pending" | "approved" | "rejected";
created_at?: string;
};
Update: {
email?: string;
firstname?: string;
phone?: string;
persona?: string;
age?: number;
experience?: string;
time_daily?: string;
availability?: string;
start_date?: string;
motivation?: string;
monthly_goal?: string;
biggest_fear?: string;
tiktok_username?: string | null;
status?: "pending" | "approved" | "rejected";
};
};
modules: {
Row: {
id: string;
title: string;
description: string | null;
week_number: number;
order_index: number;
content_type: "video" | "pdf" | "text" | "quiz" | null;
content_url: string | null;
duration_minutes: number | null;
is_published: boolean;
created_at: string;
};
Insert: {
id?: string;
title: string;
description?: string | null;
week_number: number;
order_index: number;
content_type?: "video" | "pdf" | "text" | "quiz" | null;
content_url?: string | null;
duration_minutes?: number | null;
is_published?: boolean;
created_at?: string;
};
Update: {
title?: string;
description?: string | null;
week_number?: number;
order_index?: number;
content_type?: "video" | "pdf" | "text" | "quiz" | null;
content_url?: string | null;
duration_minutes?: number | null;
is_published?: boolean;
};
};
user_progress: {
Row: {
id: string;
user_id: string;
module_id: string;
completed: boolean;
completed_at: string | null;
notes: string | null;
created_at: string;
};
Insert: {
id?: string;
user_id: string;
module_id: string;
completed?: boolean;
completed_at?: string | null;
notes?: string | null;
created_at?: string;
};
Update: {
completed?: boolean;
completed_at?: string | null;
notes?: string | null;
};
};
payments: {
Row: {
id: string;
user_id: string;
stripe_payment_intent_id: string;
amount: number;
currency: string;
status: string;
metadata: Record<string, unknown> | null;
created_at: string;
};
Insert: {
id?: string;
user_id: string;
stripe_payment_intent_id: string;
amount: number;
currency?: string;
status: string;
metadata?: Record<string, unknown> | null;
created_at?: string;
};
Update: {
status?: string;
metadata?: Record<string, unknown> | null;
};
};
site_images: {
Row: {
key: string;
url: string;
label: string | null;
updated_at: string;
};
Insert: {
key: string;
url: string;
label?: string | null;
updated_at?: string;
};
Update: {
key?: string;
url?: string;
label?: string | null;
updated_at?: string;
};
};
};
};
};
// Types helpers
export type Profile = Database["public"]["Tables"]["profiles"]["Row"];
export type Candidature = Database["public"]["Tables"]["candidatures"]["Row"];
export type CandidatureInsert = Database["public"]["Tables"]["candidatures"]["Insert"];
export type Module = Database["public"]["Tables"]["modules"]["Row"];
export type UserProgress = Database["public"]["Tables"]["user_progress"]["Row"];
export type Payment = Database["public"]["Tables"]["payments"]["Row"];
export type ModuleInsert = Database["public"]["Tables"]["modules"]["Insert"];
export type ModuleUpdate = Database["public"]["Tables"]["modules"]["Update"];