Blog
Χωρίς κατηγορία11 Απριλίου 20269 min read

Headless WordPress σε Next.js: Πώς Μετέφερα το dosmart.gr σε 3 Ημέρες

Ένα site που τρέχει 15 χρόνια δεν αλλάζει εύκολα. Αλλά όταν ανακαλύψεις ότι η Google δεν μπορεί καν να δει τις σελίδες σου, η αλλαγή γίνεται επείγουσα.

Αυτή είναι η ιστορία του πώς μεταφέραμε το dosmart.gr από WordPress + Avada σε headless Next.js, χωρίς να χάσουμε ούτε ένα URL, ούτε ένα backlink, ούτε ένα subscriber — σε 3 ημέρες.

Το Πρόβλημα: 177 Σελίδες, 0 Indexed

Κατά τον audit του παλιού site ανακαλύψαμε κάτι σοκαριστικό. Το WordPress plugin WPGuard (ένα security/firewall plugin) είχε ρυθμιστεί να μπλοκάρει τον Googlebot. Αποτέλεσμα: 177 σελίδες υποβλημένες στο Google Search Console, 0 indexed.

Αυτό σήμαινε ότι χρόνια δουλειάς σε content, SEO, και blog posts ήταν κυριολεκτικά αόρατα στη Google. Κανένας δεν μας έβρισκε μέσω αναζήτησης.

Ταυτόχρονα, το παλιό site είχε:

  • 32 active plugins (κάθε ένα potential security risk + performance drain)
  • Avada theme (ένα από τα πιο “βαριά” themes — Lighthouse mobile score: 60)
  • SeedProd landing pages (11 city pages με complex builder content)
  • FluentCRM (703 email subscribers που δεν επιτρεπόταν να χαθούν)
  • AIOSEO Pro (21 existing redirects + custom meta σε κάθε σελίδα)
  • Η ερώτηση δεν ήταν “πρέπει να αλλάξουμε;”. Ήταν “πώς αλλάζουμε χωρίς να σπάσουμε τίποτα;”.

    Η Στρατηγική: Headless WordPress + Next.js

    Αντί να κάνουμε ένα ακόμα WordPress rebuild (που θα κουβαλούσε τα ίδια προβλήματα), επιλέξαμε headless architecture:

    Frontend: Next.js 16 — pure custom, χωρίς MakerKit, χωρίς template. Κάθε component χτισμένο εξαρχής με shadcn/ui + Tailwind v4.

    Backend: Ίδιο WordPress installation μετακινημένο στο wp.dosmart.gr — noindex, κρυφό από τη Google, αλλά ακόμα functional. Το FluentCRM συνεχίζει να στέλνει emails. Το WP admin είναι ακόμα accessible. Απλά τώρα δεν servει HTML στους visitors — δίνει data μέσω REST API.

    ISR (Incremental Static Regeneration): Κάθε σελίδα γίνεται static HTML στο build time. Όταν αλλάζει κάτι στο WordPress, ένα webhook ειδοποιεί το Next.js και μόνο εκείνη η σελίδα ξαναγράφεται. Αποτέλεσμα: ταχύτητα static site + ευελιξία dynamic CMS.

    Infrastructure: Self-hosted σε Hetzner dedicated server, Docker orchestration με Coolify, Traefik reverse proxy, Cloudflare CDN. Zero vendor lock-in.

    Η Μεθοδολογία: 8 Phases σε 3 Ημέρες

    Phase 0: Audit (30 λεπτά)

    Πριν αγγίξουμε τίποτα, inventory:

  • 37 blog posts
  • 48 portfolio items (Avada custom post type με Fusion Builder shortcodes)
  • 11 city landing pages (SeedProd, κάθε μία ~128KB HTML)
  • 5 service pages
  • 21 existing 301 redirects
  • Εξήγαμε ΟΛΑ τα AIOSEO meta data (titles, descriptions) μέσω custom REST endpoint. Κανένα SEO signal δεν θα χανόταν.

    Phase 1: WordPress Backend (45 λεπτά)

    Δημιουργήσαμε το wp.dosmart.gr ως alias του ίδιου WordPress installation. Triple-layer noindex (robots.txt + X-Robots-Tag header + Cloudflare proxy). CORS headers για το Next.js frontend. Application Passwords για authenticated REST API access.

    Κρίσιμο: Αφαιρέσαμε το WPGuard plugin. Αμέσως, η Google μπορούσε ξανά να δει τα sitemaps.

    Phase 2-3: Next.js + WP Integration (2 ώρες)

    Pure custom Next.js setup. 16 typed API functions για posts, pages, portfolio, categories, tags, media, menus, AIOSEO meta. ISR webhook mu-plugin sto WordPress — κάθε save τρέχει POST στο /api/revalidate.

    Ένα gotcha που ανακαλύψαμε: στο Next.js 16, το `revalidateTag()` πήρε breaking change (χρειάζεται δεύτερο argument). Αντικαταστήσαμε με `revalidatePath()`. Λύσαμε το πρόβλημα σε 10 λεπτά χάρη στο γνωστό pattern.

    Phase 4: Design System (90 λεπτά, 3 iterations)

    Χρειάστηκαν 3 design iterations για να φτάσουμε σε premium level:

  • v1: Logo πολύ μικρό, centered nav, generic trust badges
  • v2: Real logo 40px, left-aligned nav (Linear/Vercel style), editorial stats row
  • v3: Fine-tuned spacing, accent lines, proper focus rings
  • Κάθε iteration reviewed με screenshots σε 1440px desktop + 375px mobile.

    Phase 5: Pages Build (~4 ώρες, σε tiers)

    120 σελίδες χτισμένες σε 4 tiers:
    1. Homepage (7 sections), Services, Contact, About
    2. Portfolio (48 items από WP API), Process, 6 Service details
    3. Blog (37 posts από WP API)
    4. 11 City landing pages (local SEO, reusable template)

    Κάθε σελίδα: unique meta tags, JSON-LD schema, OG images, breadcrumbs, mobile-responsive.

    Phase 6: SEO Migration (1 ώρα)

  • Auto-generated sitemap.xml με 109 URLs
  • robots.txt
  • 21 AIOSEO redirects migrated σε next.config.ts
  • JSON-LD: Organization, WebSite, LocalBusiness (per city), Service, Article
  • URL preservation: ΟΛΑ τα slugs identical
  • Phase 7-8: Deploy + Go Live (2 ώρες)

    Coolify project setup, Nixpacks build (Node 22), environment variables, DNS swap μέσω Cloudflare API.

    Αντιμετωπίσαμε 3 Coolify v4 bugs. Τα καταγράφω αναλυτικά γιατί δεν υπάρχουν πουθενά αλλού documented.

    Bug #1: FQDN δεν ενημερώνει τα Traefik labels

    Στη Coolify database, το FQDN λέει `dosmart.gr`. Αλλά κάθε φορά που γίνεται deploy, τα Docker container labels παίρνουν `sslip.io` — τον default hostname. Αποτέλεσμα: 503 errors στο production domain.

    Η λύση: παρακάμψαμε εντελώς τα Coolify-generated labels με static Traefik dynamic configuration:

    # /data/coolify/proxy/dynamic/dosmart.yaml
    http:
      routers:
        dosmart:
          rule: "Host(`dosmart.gr`)"
          service: dosmart-service
          tls:
            certResolver: letsencrypt
          priority: 100
      services:
        dosmart-service:
          loadBalancer:
            servers:
              - url: "http://container-name:3000"
    

    Αυτό το αρχείο φορτώνεται αυτόματα από τον Traefik και έχει priority 100 — υπερισχύει των Coolify labels.

    Bug #2: Environment variables σπάνε το build

    Κάθε φορά που προσθέταμε env vars μέσω Coolify API ή απευθείας στη DB, το build αποτύγχανε με “The payload is invalid”. Μετά από αρκετή διάγνωση, ανακαλύψαμε ότι ο Coolify serializer δεν μπορεί να χειριστεί σωστά τα env vars σε ορισμένες περιπτώσεις.

    Η λύση: persistent .env file εκτός Coolify, με auto-restore script μετά από κάθε deploy:

    #!/bin/bash
    # /usr/local/bin/dosmart-post-deploy.sh
    CONTAINER=$(docker ps --format '{{.Names}}' | grep dosmart | head -1)
    cat /etc/dosmart-next/.env >> /data/coolify/applications/$APP/.env
    cd /data/coolify/applications/$APP && docker compose up -d --force-recreate
    

    Bug #3: NIXPACKS_NODE_VERSION encrypted/corrupted

    Το Next.js 16 απαιτεί Node >= 20.9. Το Nixpacks χρησιμοποιεί Node 18 by default. Η μεταβλητή NIXPACKS_NODE_VERSION=22 που είχε οριστεί μέσω Coolify ήταν encrypted στη DB με corrupted value — ο builder δεν μπορούσε να τη διαβάσει.

    Η λύση: `nixpacks.toml` στο repo — in-code, χωρίς DB dependency:

    [variables]
    NIXPACKS_NODE_VERSION = "22"
    
    [phases.build]
    cmds = ["npm run build"]
    
    [start]
    cmd = "npm start"
    

    Αυτοματοποίηση: Zero-Touch Deploys

    Για να μην χρειάζεται manual SSH μετά από κάθε deploy, φτιάξαμε cron watcher. Κάθε 1 λεπτό ελέγχει αν υπάρχει νέο container και αυτόματα: (1) ενημερώνει το Traefik config, (2) προσθέτει τα env vars, (3) κάνει restart. Αποτέλεσμα: 3 λεπτά από git push σε live update, zero manual intervention.

    ISR Architecture: Πώς Δουλεύει στην Πράξη

    Η ISR (Incremental Static Regeneration) είναι η καρδιά του headless workflow. Ιδού πώς λειτουργεί βήμα-βήμα:

    1. Build time: Το Next.js κάνει fetch ΟΛΑ τα posts/pages από το wp.dosmart.gr REST API. Generates static HTML για κάθε σελίδα. Αποτέλεσμα: 120 pre-rendered HTML files, ταχύτατα στο CDN.

    2. Visitor request: Ο browser ζητάει μια σελίδα. Το Cloudflare CDN ή ο Next.js server servei το cached HTML. Χρόνος: < 100ms. 3. Content update: Ο editor αλλάζει ένα post στο wp.dosmart.gr/wp-admin. Μόλις πατήσει “Save”, ένα custom mu-plugin στέλνει POST webhook στο `https://dosmart.gr/api/revalidate` με το slug του post.

    4. Revalidation: Το Next.js λαμβάνει το webhook, validates το secret token, και καλεί `revalidatePath(‘/blog/post-slug’)`. Μόνο εκείνη η σελίδα ξαναχτίζεται — όχι ολόκληρο το site.

    5. Next visitor: Βλέπει αμέσως το updated content. Χρόνος από edit σε live: 5-10 δευτερόλεπτα.

    Fallback: αν το webhook αποτύχει (π.χ. network issue), κάθε σελίδα έχει `revalidate: 3600` — ανανεώνεται αυτόματα κάθε 1 ώρα.

    Τα Αποτελέσματα

    | Μετρική | Πριν (WordPress) | Μετά (Next.js) |
    |—|—|—|
    | Lighthouse Performance (mobile) | 60 | 85-87 (stable, 3-run avg) |
    | Lighthouse Best Practices | ~70 | 100 |
    | Lighthouse SEO | ~85 | 100 |
    | Plugins | 32 | 0 (frontend) |
    | Deploy time | Manual (ώρες) | 3 λεπτά (automated) |
    | Google indexed | 0 / 177 | 109 / 109 |
    | Static pages | 0 | 120 |
    | Blog rewrites | 0 | 7 premium posts (~9.000 λέξεις) |
    | FluentCRM subscribers | 703 | 703 (intact) |
    | SEO redirects | 21 | 21 (migrated) |
    | Content loss | – | Zero |
    | Downtime | – | Zero |

    Τι Σημαίνουν Αυτά τα Νούμερα

    Lighthouse 87.6 mobile μπορεί να μην ακούγεται “τέλειο” — αλλά σε context: ο μέσος όρος ελληνικών business sites είναι 45-55. Τα sites κατασκευασμένα με Avada, Divi, ή Elementor τυπικά κυμαίνονται στο 30-60. Εμείς είμαστε 87.6 χωρίς ακόμα image optimization (που θα μας πάει στο 92-95).

    Τα 3 λεπτά deploy time αντικαθιστούν μια διαδικασία που τυπικά παίρνει 30-60 λεπτά manual SSH, plugin updates, cache clearing. Σε 10 deploys/μήνα = 4.5-9.5 ώρες εξοικονόμηση.

    Τα 0 frontend plugins σημαίνουν zero attack surface, zero compatibility conflicts, zero “plugin X broke plugin Y” debugging sessions. Τα 32 plugins του παλιού site ήταν 32 πιθανά σημεία αποτυχίας.

    Τι Θα Έκανα Διαφορετικά

    Κανένα project δεν είναι τέλειο. Αν ξεκινούσα από την αρχή:

    1. Image optimization πριν launch — Θα έτρεχα Imagify bulk optimization στα WP uploads πριν τη μετάβαση. Το LCP 3.9s θα ήταν <2s, και το Lighthouse Performance θα ξεκινούσε στο 92+ αντί 87. 2. GSC indexing requests από Day 0 — Αφαιρέσαμε το WPGuard και η Google μπορούσε να δει ξανά τα sitemaps, αλλά δεν κάναμε proactive request indexing. Αν το είχαμε κάνει αμέσως, θα είχαμε κερδίσει 3-5 μέρες indexing momentum.

    3. Coolify staging test — Αν είχαμε δοκιμάσει τα env vars σε staging πρώτα, θα αποφεύγαμε 2-3 ώρες debugging σε production. Αλλά δεν είχαμε staging — πηγαίναμε live από Day 1 (χαμηλό traffic = χαμηλό risk).

    4. Content rewrites παράλληλα — Ξεκινήσαμε τα content rewrites μετά το launch. Θα μπορούσαμε να τα γράψουμε παράλληλα με τα Phases 2-5, γλιτώνοντας 2-3 ώρες.

    5 Πράγματα που Μάθαμε

    1. Τα security plugins μπορεί να σκοτώνουν το SEO σου

    Το WPGuard έκανε block τον Googlebot εδώ και μήνες (πιθανώς χρόνια). 177 σελίδες content, αόρατες. Μάθημα: check το robots.txt και τα sitemaps σου με Googlebot User-Agent, όχι μόνο κανονικό browser.

    2. Headless WordPress δεν χρειάζεται να αλλάξεις domain

    Το WordPress μένει στο ίδιο server, στο ίδιο database. Αλλάζεις μόνο ποιος servει το frontend. Zero data migration risk.

    3. ISR > SSR για agency sites

    Static generation + on-demand revalidation = best of both worlds. Lighthouse 87+ χωρίς runtime cost. Content updates σε δευτερόλεπτα.

    4. Coolify v4 beta έχει bugs — αλλά λύνονται

    3 bugs documented + workarounds. Static Traefik configs, persistent .env files, nixpacks.toml. Δεν χρειάστηκε να αλλάξουμε orchestrator.

    5. 15 λεπτά design review σώζουν 15 ώρες rebuild

    3 design iterations με screenshots + honest review κάθε φορά. Αν είχαμε χτίσει 12 pages πάνω στο v1 design, θα τα ξαναχτίζαμε.

    Τεχνολογίες

  • Framework: Next.js 16 (App Router, TypeScript strict)
  • UI: Tailwind CSS v4 + shadcn/ui
  • CMS: WordPress (headless, REST API)
  • Deploy: Coolify + Nixpacks (Node 22) + Traefik
  • CDN: Cloudflare (proxied, Brotli, HTTP/3)
  • Email: Mailgun (contact form, shared με WP)
  • Analytics: Microsoft Clarity
  • Server: Hetzner dedicated (self-hosted)
  • Τι Ακολουθεί

    Αυτό που ξεκίνησε ως migration project κατέληξε σε κάτι μεγαλύτερο: ένα reusable template (wide-agency-starter) που μπορούμε να χρησιμοποιήσουμε για κάθε νέο client project. Clone, configure, deploy — σε 2-3 μέρες αντί για 2-3 εβδομάδες.

    Η αλήθεια είναι ότι τα περισσότερα WordPress sites δεν χρειάζονται headless architecture. Αλλά αν θέλεις Lighthouse 90+, αν θέλεις 3-λεπτά deployments, αν θέλεις zero-plugin frontend — τότε headless WordPress + Next.js είναι η σωστή επιλογή.

    *Ενδιαφέρεσαι για παρόμοιο migration; Μίλησέ μας — δωρεάν αρχική αξιολόγηση.*

    DS

    DoSmart Team

    15+ χρόνια στο web development. Γράφουμε για πρακτικές λύσεις, τεχνολογίες και στρατηγικές που δουλεύουν πραγματικά.