WordPress nu merită. Livrează cu Next.js.
- Next.js
- WordPress
- Performance
- Web Dev
Fiecare proiect WordPress pe care l-am atins se transformă într-o bandă rulantă de plugin-uri și într-un dezastru pe Lighthouse. După ce am migrat două site-uri de clienți pe Next.js, nu mă mai întorc.
WordPress alimentează 43 la sută din web și generează o parte disproporționată din apelurile de suport ale clienților. Știu asta pentru că am petrecut doi ani construind și întrețineând site-uri WordPress înainte să trec fiecare proiect nou pe Next.js. Schimbarea nu este o chestiune de ideologie. Este o chestiune de timp, securitate și ce scor obține un site cu adevărat pe Core Web Vitals.
Banda rulantă a plugin-urilor și a patch-urilor de securitate
Un proiect WordPress tipic ajunge să aibă 15 până la 25 de plugin-uri. Fiecare plugin este o dependență separată cu propriul ciclu de lansare, propriul autor și propria istorie de CVE-uri. WordPress core în sine livrează patch-uri de securitate cu preaviz scurt. Când cade o vulnerabilitate critică, fereastra este îngustă: patchează rapid sau ești compromis.
Site-ul Wegweiser Leben a fost prima mea țintă serioasă de migrare. Avea un page builder, trei plugin-uri SEO care se suprapuneau parțial, un plugin de caching în conflict cu CDN-ul găzduirii și un plugin pentru formulare semnalat de două ori pentru XSS. În fiecare lună simțeam că joc un joc numit "care actualizare va strica layout-ul azi". Clientul plătea pentru mentenanță, nu pentru un site fiabil.
- Plugin-ul A se actualizează și strică injecția CSS a plugin-ului B.
- Hostul ridică versiunea PHP, două plugin-uri aruncă erori fatale.
- Patch de securitate pentru WordPress core, page builder-ul nu este încă compatibil.
- Scanerul de malware semnalează un plugin care nu a fost actualizat de 18 luni.
- Se repetă la infinit.
Cu un proiect Next.js suprafața de atac se prăbușește. Niciun runtime PHP expus pe internet. Niciun panou de administrare la /wp-admin. Nicio credențială de bază de date într-un fișier de configurare plat pe care un server configurat greșit l-ar putea servi. Aplicația este HTML static, CSS și JavaScript implementate pe un CDN edge. Nu există nimic de patchat într-o după-amiază de duminică pentru că un autor de plugin a livrat o actualizare proastă.

Markup-ul page builder-elor și Core Web Vitals
Deschide sursa oricărei pagini Elementor sau Divi. Vei găsi supă de div-uri adânc imbricate, stiluri inline pe fiecare element, scripturi care blochează randarea și fișiere de fonturi încărcate din trei origini diferite. Acel markup este rezultatul unui instrument drag-and-drop optimizat pentru editare vizuală, nu pentru motorul de layout al browserului sau pentru crawler.
Largest Contentful Paint suferă pentru că imaginea hero este încărcată printr-un container injectat de JavaScript care nu este vizibil în timpul randării inițiale. Cumulative Layout Shift crește pentru că page builder-ul rezervă spațiu dinamic după încărcarea fonturilor. Total Blocking Time urcă pentru că fiecare widget livrează propriul bundle de scripturi indiferent dacă widget-ul este vizibil pe această pagină.
Site-ul Jumpino View a obținut 41 la Performance pe mobil când era pe WordPress. După migrarea la Next.js obține 96. Conținutul este identic. Diferența constă în totalitate în ceea ce generează framework-ul și în modul în care încarcă resursele.
Deții output-ul, deci viteza este a ta
Cu Next.js scrii componenta, decizi markup-ul, controlezi <head>-ul. Componenta next/image gestionează automat srcset responsive, lazy loading și conversia în formate moderne. Nu ai nevoie de un plugin pentru asta. Nu plătești un autor de plugin să rămână treaz.
import Image from 'next/image';
import type {FC} from 'react';
type HeroProps = {
src: string;
alt: string;
headline: string;
};
// Replaces a WordPress "Hero Section" plugin block.
// next/image handles srcset, WebP conversion, and LCP prioritization.
const HeroSection: FC<HeroProps> = ({src, alt, headline}) => {
return (
<section className="relative isolate overflow-hidden">
<Image
src={src}
alt={alt}
fill
priority // marks this as LCP candidate
sizes="100vw"
className="object-cover -z-10"
/>
<div className="mx-auto max-w-3xl px-6 py-24">
<h1 className="text-4xl font-bold tracking-tight text-white sm:text-6xl">
{headline}
</h1>
</div>
</section>
);
};
export default HeroSection;Acea componentă este înlocuirea completă a unui plugin care adăuga 40 kB de JavaScript, un endpoint backend PHP și trei interogări la baza de date per încărcare de pagină. Prop-ul priority spune lui Next.js să preia imaginea în avans și să o marcheze ca element LCP. Browserul primește un indiciu înainte chiar de a analiza body-ul. Niciun panou de configurare, nicio cheie de licență, niciun email de reînnoire.
Formulare, contact și ultimele plugin-uri rezistente
Cele două plugin-uri care îi țin pe clienți pe WordPress cel mai mult timp sunt formularul de contact și înscrierea la newsletter. Ambele au soluții curate în Next.js. O componentă React Hook Form combinată cu un Route Handler face tot ce face Contact Form 7, cu zero PHP, zero scrieri în baza de date pe serverul frontend și tipuri TypeScript complete pe payload-ul trimiterii.
// app/api/contact/route.ts
// Replaces Contact Form 7 + a mail plugin entirely.
import {NextRequest, NextResponse} from 'next/server';
import {Resend} from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
export async function POST(req: NextRequest) {
const body = await req.json();
const {name, email, message} = body as {
name: string;
email: string;
message: string;
};
if (!name || !email || !message) {
return NextResponse.json({error: 'Missing fields'}, {status: 400});
}
const {error} = await resend.emails.send({
from: 'contact@jumpinotech.com',
to: 'gabriel@jumpinotech.com',
subject: `Contact from ${name}`,
text: `${message}\n\nReply to: ${email}`,
});
if (error) {
return NextResponse.json({error: 'Send failed'}, {status: 500});
}
return NextResponse.json({ok: true});
}Acesta este întregul backend. Resend se ocupă de livrare. Componenta frontend apelează fetch("/api/contact", ...). Niciun plugin, nicio interfață de configurare SMTP, niciun câmp honeypot pe care trebuie să-ți amintești să-l adaugi, niciun job WP cron care să gestioneze coada.

Cum un agent AI de programare păstrează memoria pe termen lung a unui proiect Next.js
Odată ce codebase-ul WordPress a dispărut, proiectul este suficient de curat pentru ca un agent AI de programare să îl opereze fiabil între sesiuni. Cheia este contextul markdown persistent. Un agent care citește un fișier AGENTS.md bine întreținut la rădăcina proiectului cunoaște convențiile, comenzile, variabilele de mediu și capcanele fără să fie informat din nou de fiecare dată.
Pentru migrarea Wegweiser Leben întrețin un fișier AGENTS.md pe care agentul îl citește la începutul fiecărei sesiuni. Acoperă structura folderelor, formatul de authoring al conținutului (module TypeScript pentru postări, exact cum folosesc aici), ținta de deployment și lucrurile care m-au surprins în timpul migrării. Agentul nu ghicește. Citește fișierul și acționează conform lui.
Memoria markdown nu este un workaround. Este arhitectura corectă pentru a menține un agent fiabil pe un proiect pe care îl vizitează necontinu.
Iată un extras reprezentativ din fișierul de context al agentului proiectului:
# AGENTS.md — Wegweiser Leben Next.js Project
## Stack
- Next.js 15 (App Router), TypeScript strict, Tailwind CSS v4
- Content: TypeScript modules in src/content/posts/ typed against Post in src/content/types.ts
- Images: next/image only, no raw <img>; WebP assets in public/blog/[slug]/
- Deployment: Vercel, auto-deploy on push to main
## Commands
- dev: npm run dev (localhost:3000)
- build: npm run build — must pass before any PR
- lint: npm run lint — ESLint + Prettier, no warnings allowed
## Content authoring
- Each post is a .ts file exported as default Post
- body array uses Block types (p, h2, h3, ul, ol, quote, code, callout, image)
- readingMinutes must match actual word count (approx 200 wpm)
- date field is ISO string, do not change after publish
## Gotchas
- Tailwind v4 uses @import "tailwindcss" not @tailwind directives
- next/font must be imported in layout.tsx only, not in individual components
- Route Handlers in app/api/ use NextRequest/NextResponse from 'next/server'
- RESEND_API_KEY must be set in Vercel env vars and in .env.local for local dev
- Do not add wordpress, elementor, or divi class names anywhere
## Known issues
- Large hero images above 1 MB will fail Vercel's 4.5 MB limit; compress first
Când deschid o sesiune nouă și îi cer agentului să adauge un formular de contact sau să remedieze o eroare de build, citește mai întâi acest fișier. Știe să nu folosească tag-uri <img> brute. Cunoaște formatul conținutului. Știe unde se află variabilele de mediu. Aceasta este continuitate operațională fără un document de predare sau un briefing verbal lung.
Lista de verificare a migrării
Atât Wegweiser Leben, cât și Jumpino View au urmat aceeași secvență. Durează un weekend concentrat pentru un site cu mai puțin de 20 de pagini.
- 01Exportă tot conținutul din WordPress (export XML sau interogare directă în DB).
- 02Convertește postările și paginile în module de conținut TypeScript.
- 03Reconstruiește navigarea și layout-ul ca și componente React.
- 04Înlocuiește plugin-ul de formular de contact cu un Route Handler și Resend.
- 05Înlocuiește plugin-ul SEO cu Metadata API din Next.js și
next-sitemap. - 06Auditează fiecare imagine: comprimă, convertește în WebP, mută în
public/. - 07Rulează Lighthouse pe fiecare pagină și remediază regresiile LCP sau CLS.
- 08Scrie AGENTS.md cu contextul complet al proiectului.
- 09Deployează pe Vercel, direcționează DNS-ul, retrage vechiul hosting.
Atât. Niciun abonament continuu la plugin-uri. Nicio scanare de securitate lunară. Nicio licență pentru page builder. Clientul plătește planul hobby Vercel sau nimic dacă folosește un export static. Site-ul este mai rapid, mai sigur și mai ieftin de operat. Singurul lucru pierdut este editorul drag-and-drop care cauza jumătate din probleme.
WordPress avea sens când alternativa era să scrii PHP de mână. Alternativa de azi este un framework tipizat, bazat pe componente, cu un CDN global, optimizare automată a imaginilor și o pipeline de deployment care durează 90 de secunde. Calculul s-a schimbat. Oprește-te din a întreține ceea ce poți pur și simplu înlocui.