Site vitrine “services à domicile” optimisé pour le SEO local (Île‑de‑France & Normandie), hébergé sur Netlify. Stack moderne, CI stricte, accessibilité et sécurité prises au sérieux.
- Aperçu
- Démo & Liens
- Captures (Screenshots)
- Stack & Architecture
- Fonctionnalités clés
- Qualité & CI
- Démarrage & Scripts
- Déploiement Netlify
- Audit automatisé de PR
- Sécurité & Headers
- Accessibilité (WCAG AA)
- Performance (Core Web Vitals)
- SEO technique
- Variables d’environnement
- Infos à renseigner (TODO)
- Contribuer
- Licence
Ce projet React + TypeScript (Vite) propose:
- Pages locales
/zones/:region/:city(Île‑de‑France, Normandie) - Métadonnées par page (Helmet), JSON‑LD structurés (WebSite, Service, Breadcrumb, FAQ)
- Sitemap & robots générés automatiquement
- Intégration future d’avis Google via Netlify Functions
- Design tokens CSS + Tailwind, animations discrètes, CTA “Appeler” bien mis en avant
- Live: https://www.rcp-multiservices.com/
- robots.txt: https://www.rcp-multiservices.com/robots.txt
- sitemap.xml: https://www.rcp-multiservices.com/sitemap.xml
Générez et insérez automatiquement les captures dans le README:
# installez Puppeteer si nécessaire
npm i -D puppeteer
# capture et mise à jour du README
npm run screenshots- React 18, TypeScript 5, Vite 5, Tailwind CSS 3
- Routing via React Router
- Helmet pour SEO (title, description, canonical, OG/Twitter)
- JSON‑LD injecté côté client
- Netlify Functions pour avis Google (endpoints sécurisés)
Arborescence (extraits):
- src/
- components/ (Header, GoogleReviewsBadge, QuickCall, Reviews, MapZones)
- pages/ (Home, Services, Contact, ZonesIndex, Region, City, Legal, Privacy, 404)
- routes/ (AppRoutes)
- data/ (locations.json + types/helpers)
- utils/ (styles, SEO helpers, openingHours)
- lib/ (env, reviews)
- public/ (robots.txt, 404.html, screenshots/)
- scripts/ (generate-sitemap.mjs, sync-tokens.mjs)
- netlify.toml (headers, redirects, functions)
Note monorepo: Le dossier next/ contient un prototype Next.js non utilisé en production. Il est conservé à titre d’exemple mais hors périmètre CI/Build.
- SEO Local:
- Pages ville depuis
src/data/locations.json - Helmet + JSON‑LD par page
- Sitemap postbuild, robots.txt pointant vers sitemap
- Pages ville depuis
- Accessibilité:
- Skip link (#main), landmarks clairs, aria‑hidden sur SVG décoratifs
- UX:
- Hero avec CTA “Appeler” + badges de réassurance
- “Comment ça marche” (3 étapes)
- “Villes proches” (maillage interne)
- Carte interactive Leaflet (zones)
- Performances:
- Lazy loading, dimensions d’images explicites
- Preconnect pour images & tuiles
- Sécurité:
- Headers: HSTS, XFO, nosniff, Referrer‑Policy, Permissions‑Policy, COOP/CORP
- CSP restrictive (avec style‑src 'unsafe‑inline' compatible Leaflet)
- Consentement cookies:
- Bannière de consentement (nécessaires toujours actifs, analytics optionnel)
- Analytics (GA4) et Microsoft Clarity initialisés uniquement si consentement + variables d’environnement présentes
- ESLint strict (type‑aware), TypeScript strict
- Prettier format:check
- Vitest avec couverture minimale ≥ 80% (tests unitaires couvrant pages, lib, utils)
- Build Vite
- Audit sécurité (npm audit)
- CI GitHub Actions (Format, Lint, Typecheck, Test, Build, Audit)
- Installer:
npm install
- Développement:
npm run dev
- Format / Lint / Typecheck / Tests:
npm run format:check/npm run formatnpm run lint/npm run lint:cinpm run typechecknpm run test/npm run test:ci
- Build & Preview:
npm run build(puispostbuildgénèredist/sitemap.xml)npm run preview
netlify.toml:- publish:
dist - functions:
netlify/functions - redirects:
/api/*→/.netlify/functions/:splat - headers (sécurité + cache immuable sur assets/images)
- publish:
- Domaine:
www.rcp-multiservices.comen primary- Redirection apex → www configurée
- CSP:
- Pour activer GA4, ajoutez
https://www.googletagmanager.comàscript-src - Pour activer Microsoft Clarity, ajoutez
https://www.clarity.msàscript-src
- Pour activer GA4, ajoutez
Exécutez un audit qualité automatisé sur l’URL de prévisualisation (Netlify/Vercel) de la Pull Request.
Pré-requis (optionnels mais recommandés):
- Lighthouse + Chrome launcher:
npm i -D lighthouse chrome-launcher - Puppeteer + Axe:
npm i -D puppeteer axe-core
Commandes:
# avec variable d'environnement
BASE_URL="https://deploy-preview-123--rcp-multiservices.netlify.app" npm run audit:site
# ou en argument
npm run audit:site -- "https://deploy-preview-123--rcp-multiservices.netlify.app"Le script scripts/audit.mjs:
- Valide tous les liens du site via le sitemap (404/5xx)
- Lance Lighthouse (si installé) et remonte les scores Performance, Accessibilité, Bonnes pratiques, SEO
- Lance Axe sur 3 pages (Accueil, Services, Contact) et liste les violations crit./serious
- Inspecte les en‑têtes HTTP (HSTS, XFO, XCTO, CSP, Referrer‑Policy, Permissions‑Policy, COOP/CORP)
- Vérifie
/robots.txt, `/sitemapde la homepage (title, description, OG)
Sortie:
- Un rapport Markdown est écrit dans
./audit-report.mdque vous pouvez copier-coller dans le commentaire de la PR.
- Strict‑Transport‑Security, X‑Frame‑Options, X‑Content‑Type‑Options, Referrer‑Policy, Permissions‑Policy
- Cross‑Origin‑Opener‑Policy, Cross‑Origin‑Resource‑Policy
- CSP (Note): Leaflet utilise des styles inline dynamiques → style‑src contient 'unsafe‑inline' pour compatibilité.
- Pour activer Google Analytics (GA4), ajoutez
https://www.googletagmanager.comàscript-srcdans la CSP. - Pour activer Microsoft Clarity, ajoutez
https://www.clarity.msàscript-srcdans la CSP. - Cache‑Control (immutable) sur /assets/* et /images/*
- Navigation clavier: skip link “Aller au contenu”
- Landmarks: sections et aria‑label (carte des zones)
- Contrastes: palette lisible (teal/navy/white), hover/focus visibles
- Images: alt descriptifs, lazy + dimensions
- Images: lazy, width/height, decoding="async"
- Preconnect/dns‑prefetch: Unsplash & OSM tiles
- Recommandé pour aller plus loin:
- WebP/AVIF + srcset/sizes pour hero/overlay
- Fonts locales si CSP très stricte (font‑src)
- Canonical / OG / Twitter alignés sur domaine prod
- JSON‑LD (WebSite, Service, Breadcrumb, FAQ)
- robots.txt & sitemap.xml générés
- AggregateRating retiré tant qu’il n’y a pas d’avis authentiques
- Front:
VITE_GBP_URL— URL publique Google Business (affiche badge “Avis Google”)VITE_REVIEWS_ENDPOINT— URL endpoint avis (par défaut/api/google-reviews)
- Netlify Functions:
GOOGLE_MAPS_API_KEY— clé API Maps (Places)GOOGLE_PLACE_ID— Place ID établissement
Voir .env.example et config Netlify (Site settings → Environment variables).
- SIRET: à compléter (footer + Mentions légales)
- RC Pro: assureur + n° de police (footer + Mentions légales)
- Adresse: à compléter (Contact + JSON‑LD)
- Réseaux sociaux (sameAs dans JSON‑LD): LinkedIn, X/Twitter, Instagram, Facebook
- og:image par défaut: ajouter
public/og-default.webpet référencer dans Helmet - Images de hero: à personnaliser plus tard (laisser en l’état pour le moment). Pages et fichiers concernés:
- Accueil:
src/routes/AppRoutes.tsx - Services:
src/pages/ServicesPage.tsx - Contact:
src/pages/ContactPage.tsx - Zones (index):
src/pages/ZonesIndex.tsx - Région:
src/pages/RegionPage.tsx - Ville:
src/pages/CityPage.tsx
- Accueil:
- Micro‑animations étendues (optionnel): à appliquer plus tard sur cartes témoignages et listes de départements/zones (stagger, hover, fade), en conservant
prefers-reduced-motion.
Voir CONTRIBUTING.md pour les conventions de commits (Conventional Commits), branchement (feature/*, fix/*, chore/*), exécution des scripts, CI et guidelines de code (TypeScript strict, accessibilité, SEO).
Éléments à renseigner et où les placer:
- SIRET: afficher en footer et dans la page Mentions légales (
src/pages/LegalPage.tsx). - RC Pro: assureur + n° de police en footer et Mentions légales.
- Adresse postale: Contact (
src/pages/ContactPage.tsx) et JSON‑LD LocalBusiness. - Téléphone et email: harmonisés (NAP), présents dans le footer, Contact et JSON‑LD.
- Horaires: TopInfoBar et footer (affichage), JSON‑LD LocalBusiness (structure).
- Confidentialité: compléter
src/pages/PrivacyPage.tsx(politique cookies/analytique) et ajouter un lien “Gérer les cookies” (bannière de consentement déjà incluse).
JSON‑LD LocalBusiness — champs recommandés:
"@type": "LocalBusiness","name","url","telephone","email""address"(streetAddress, postalCode, addressLocality, addressRegion, addressCountry)"openingHours"(ex:"Mo-Fr 08:00-20:00", "Sa 09:00-18:00")"priceRange"(ex:"€€") si pertinent"sameAs"(liens officiels: Google Business, LinkedIn, X/Twitter, Instagram, Facebook)- (option)
"areaServed"(Île‑de‑France, Normandie)
Si vous activez GA4 et/ou Microsoft Clarity, adaptez la directive CSP dans netlify.toml:
[[headers]]
for = "/*"
[headers.values]
Content-Security-Policy = """
default-src 'self';
script-src 'self' https://www.googletagmanager.com https://www.clarity.ms;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https://images.unsplash.com https://*.tile.openstreetmap.org;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://www.google-analytics.com https://www.clarity.ms;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
upgrade-insecure-requests;
"""Notes:
- Leaflet exige
style-src 'unsafe-inline'. - Ajoutez/retirez des hôtes selon vos sources réelles (CDN images, APIs).
- Vérifiez les en‑têtes effectifs avec l’audit (SecurityHeaders / DevTools).
- Tests: fallback de MapZones en mode test (jsdom) pour éviter les erreurs Leaflet.
- ScrollTop: ignore
window.scrollTonon implémenté en jsdom. - Pages Services: contenu enrichi (prestations, méthode, conseils) + CTA mis en avant.
- Consentement cookies: bannière et initialisation conditionnelle GA4/Clarity.
- Couverture tests: ajout de tests (analytics, clarity, consent, openingHours, zones) → ≥ 80%.
- Documentation: README et VISUELS.md mis à jour (CSP, légal, visuels et captures).
- Accessibilité & SEO: breadcrumb, aria‑label de la carte, og:image par défaut, robots/sitemap.
Ce projet est publié sous licence MIT. Voir LICENSE.