From Classic WordPress to a Headless Production Site
Production-ready migration for a local lutherie workshop
Esprit Guitare is a lutherie and electronics repair workshop based in Schœlcher, Martinique. The public website originally ran as a classic WordPress install (OceanWP theme, multiple plugins for booking, opening hours, reviews, forms, and SEO).
In July–August 2026, the site was migrated to a headless architecture: WordPress remains the editorial CMS, while a Next.js application serves the public frontend, APIs, and workshop admin tools. The visual identity stays close to the original site, with custom replacements for the heaviest plugins — especially appointment booking.
Live site: https://www.espritguitare.fr/
Context & Goals
- Keep WordPress for content editing (pages, posts, media)
- Remove front-end dependency on heavy WordPress plugins
- Rebuild booking, opening hours, contact/quote forms, and reviews display in the Next.js app
- Preserve SEO (canonical URLs, redirects, sitemaps, cutover without downtime)
- Deploy on a self-hosted VPS with Coolify (same pattern as other axialdata projects)
Technical Stack
Frontend:
- Next.js 16 (App Router) + React 19
- TypeScript 5.9
- Tailwind CSS 4
- Local SVG icons (no Font Awesome)
- Zod 4 for validation
- Cloudflare Turnstile on public forms and workshop login
CMS & content:
- Headless WordPress on
cms.espritguitare.fr - WPGraphQL with a custom endpoint slug (not the default
/graphql) - HTML rewrite layer for media URLs, shortcodes, and image optimization via
/_next/image(AVIF/WebP)
Business data & APIs:
- MongoDB + Mongoose 9 (opening hours, appointments, blacklist, admin sessions)
- Custom booking module (30-minute slots, blocks, blacklist by email / phone / name)
- Twilio SMS + SMTP (Proton) for confirmations and J−1 reminders
- iCal feed for calendar subscription
- Optional Nextcloud CardDAV sync (upsert client contacts on booking)
- Reviews: Facebook + Google listed via WordPress REST (mu-plugin); Pages Jaunes / Trustpilot as outbound links
Deployment & ops:
- Docker standalone image (
node:22-alpine) on Coolify - pnpm 11.20
- GitLab self-hosted (
gitlab.axialdata.app) - Rybbits analytics (
analytics.axialdata.app) without visitor tracking cookies
Architecture
WordPress CMS (Hostinger)
• pages / posts / media
• WPGraphQL
• review sync plugins (data source)
Next.js app (Coolify VPS)
www + apex espritguitare.fr
• public site + API routes
• workshop admin (/eg-coulisses)
• staging: preprod (noindex)
MongoDB Twilio + SMTP
(RDV, hours, (SMS + e-mail)
blacklist)
Menus and site config live in the Next.js codebase (not WordPress menus), to keep the CMS thin and reduce plugin surface.
Security & Hardening
- Strict Content Security Policy with nonces
- Security headers (HSTS, frame denial, referrer policy, etc.)
- Turnstile on contact, quote, booking, and workshop login
- Workshop admin: password auth, HTTP-only session cookie, Mongo-backed rate limit (5 failures / 15 min / IP)
- Timing-safe token checks for the iCal feed
- Preprod blocked from search indexing (
robots,X-Robots-Tag, empty sitemap when not production) - WordPress front disabled after cutover — CMS only
Main Features
Public site:
- Marketing pages and blog/realisations listings from WordPress
- Pixel-close layout vs the legacy OceanWP design
- Contact and quote forms (file upload on quote) with e-mail delivery
- Search over published content (
/recherche) - Opening hours status on the homepage (Mongo-driven, replaces We’re Open shortcodes)
- Reviews page (
/avis) with Facebook + Google entries - Article lightbox, TOC, reading time, and SEO metadata (Open Graph / Twitter)
Booking (replaces Appointment Hour Booking):
- Calendar wizard with available days and time slots
- Blacklist enforcement server-side
- Client + admin e-mail confirmations
- SMS confirmation and reminder (~24h before)
- iCal subscription for the workshop agenda
- Nextcloud contact upsert by phone number (best-effort)
Workshop back-office:
- Manage appointments (create, reschedule, cancel)
- Manage opening hours and slot blocks
- Optional client notification on admin changes
SEO cutover:
- DNS: apex +
www→ Next.js - Permanent redirects for legacy WordPress URLs (categories, author archives, comment pages, shortlinks
?p=, orphaned paths) - Trailing-slash convention aligned with historical WordPress URLs / Google preference
- Sitemap and canonical URLs generated by Next.js
Migration Approach
Work was delivered in phases:
- Foundation — Next.js scaffold, WPGraphQL content, design parity, forms, mail, SEO basics, Coolify deploy
- Opening hours — Mongo module + homepage integration
- Booking — full RDV stack (API, UI, SMS, iCal, admin, blacklist)
- Reviews — display layer on top of existing WordPress review tables
- Cutover — DNS, headless CMS, redirects, preprod noindex, production hardening
The portfolio’s own headless WordPress + Next.js pattern was reused as a baseline, then extended with workshop-specific booking and ops features.
Outcome
- Public site served by Next.js in production since 7–8 August 2026
- WordPress reduced to a content/media CMS
- Booking and hours no longer depend on third-party WordPress plugins on the public front
- Staging environment available for safe iteration without SEO duplication
Resources:
- Production website: https://www.espritguitare.fr/
- Private project (GitLab self-hosted)



