import { headers } from "next/headers";
import { NextResponse } from "next/server";
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
// Webhook-urile cer acces la raw body: Route Handlers sunt obligatorii aici
export async function POST(req: Request) {
const body = await req.text();
const signature = (await headers()).get("stripe-signature");
if (!signature) {
return new NextResponse("Missing signature", { status: 400 });
}
try {
const event = stripe.webhooks.constructEvent(
body,
signature,
process.env.STRIPE_WEBHOOK_SECRET!
);
if (event.type === "payment_intent.succeeded") {
// procesează plata
}
return NextResponse.json({ received: true });
} catch (err) {
return new NextResponse("Webhook error", { status: 400 });
}
}De când a băgat Vercel Server Actions în prim-plan, văd tot mai mulți colegi care încearcă să șteargă complet folderul de app/api. E o greșeală clasică de tipul „avem un ciocan nou, totul e un cui”.
La un magazin online pe care l-am migrat pe Next.js 14 acum câteva luni (în jur de 12k comenzi pe lună), am făcut experimentul ăsta. Am vrut să vedem cât putem împinge Server Actions înainte să ne dăm cu capul de pragul de sus. Concluzia scurtă: pentru formularistica internă sunt aur curat, dar pentru restul arhitecturii devin rapid o frână.
Form Submit: Server Actions câștigă detașat
Dacă ai o mutare de date declanșată direct de UI-ul tău — un formular de profil, adăugare în coș, schimbat o parolă — Server Actions n-au rival. Scapi de boilerplate-ul clasic: definește rută POST, fă fetch din client, gestionează starea de loading manual, invalidează cache-ul.
Cu useActionState (sau vechiul useFormState) și revalidatePath, rezolvi totul dintr-o singură funcție async. Ai type-safety direct din server până în componentă fără să expui un contract HTTP public pe care să-l documentezi sau să-l securizezi separat cu CORS. La formularele de checkout am redus codul de client cu vreo 25% doar scăpând de handlerele clasice de fetch.
Webhook-uri third-party: doar Route Handlers
Aici nu există negociere. Dacă integrezi Stripe, Twilio sau un procesator local de plăți precum Netopia, Server Actions ies complet din discuție. Serviciile externe au nevoie de un endpoint REST clasic, predictibil, cu URL fix și acces la raw request body.
Server Actions funcționează ca un apel RPC intern prin POST, cu headere specifice Next.js și răspunsuri serializate intern. Stripe n-are habar să trimită payload-ul într-un format pe care Server Actions să-l înțeleagă, plus că verificarea semnăturii criptografice (stripe.webhooks.constructEvent) cere acces brut la buffer-ul request-ului. În Server Actions primești direct date parsate sau FormData, deci verificarea semnăturii crapă instant.
File Upload: depinde cât de mare e fișierul
Am pățit-o pe pielea noastră aici. Pentru un avatar de 500KB, merge brici să arunci un file într-un FormData și să-l procesezi direct într-o Server Action. Problema apare la fișiere de zeci de mega.
Next.js are o limită default de 1MB pentru payload-ul unei Server Action (o poți crește din next.config.js via serverActions.bodySizeLimit), dar dacă treci tot traficul de upload prin serverless functions pe Vercel, te lovești de două ziduri: execuție blocată și costuri de compute degeaba.
Pentru documente mari, cel mai curat pattern rămâne un Route Handler dedicat care generează un presigned URL de S3/R2, urmat de un upload direct din browser către storage. Server Actions nu sunt gândite să facă streaming de fișiere gigant.
Cum le împarți, pe scurt
Trade-off-ul e simplu: Server Actions sunt cuplate strâns cu React și frontend-ul tău. Nu au URL-uri publice curate și nu le poți refolosi dacă mâine vrei să construiești o aplicație de mobil pe același backend.
Folosește Server Actions dacă acțiunea e inițiată de un user în browser și vrei revalidare automată de pagină. Păstrează Route Handlers (app/api/.../route.ts) pentru webhook-uri, API-uri publice consumate de alții și fluxuri custom de streaming sau auth extern.
Voi mai țineți rute de API pentru formulare normale sau ați trecut exclusiv pe Actions?