Next.js 16 + AI agenti: Production-Grade Master Guide
Next.js 16 + AI agenti: Production-Grade Master Guide

Autor: Zoran Knežević
Tehnička verifikacija: Next.js 16.x Official Documentation & BFF Security Guidelines
Status: Active Living Reference • Ažurirano: 26. avgust 2026. (Next.js 16.3.3 Active LTS)

Veštačka inteligencija i savremeni coding agenti (Cursor, Claude Code, GitHub Copilot, Gemini CLI, Windsurf, Codex) uneli su revoluciju u brzinu razvoja softvera. Međutim, sa tom brzinom isplivao je i ogroman tehnički dug: aplikacije koje naizgled rade savršeno u lokalnom dev okruženju, ali u produkciji pate od katastrofalnih bezbednosnih propusta, memorijskih i keš anomalija, nekontrolisane "use client" eksplozije i rušenja pod serverless infrastrukturom.

Ovaj vodič predstavlja kompletan produkcioni master-vodič sa 80 preciznih pravila, arhitektonskim dijagramima, Data Access Layer (DAL) modelom, Next.js 16 Cache Components mehanizmima, najnovijim bezbednosnim zakrpama i 10-faznim AI eksekutivnim protokolom.


Zašto AI agenti greše na modernom Next.js-u?

Glavni razlog zašto AI modeli generišu problematičan kod leži u zastarelosti trening podataka i mešanju nepovezanih paradigmi:

  1. Konfuzija između Pages i App Router-a: Modeli često primenjuju stare koncepte na React Server Components (RSC).
  2. Pretvaranje celog stabla u klijentsku aplikaciju: Čim zatreba najmanje stanje ili animacija, AI stavlja 'use client' na vrh stranice ili layout-a.
  3. Iluzija bezbednosti u UI-ju i proxy sloju: AI često autorizaciju postavlja samo u dugme ili u proxy.ts, ostavljajući bazu otvorenom za direktne napade.
  4. Zablude o Caching mehanizmima: Neznanje o tome kako Next.js 16 kešira argumente funkcija, što dovodi ili do curenja privatnih podataka u shared cache ili do potpunog gašenja performansi.
  5. Nerealne pretpostavke o okruženju: Kod koji radi na lokalnom monolitnom next dev serveru puca na produkcionom serverless runtime-u zbog connection pooling-a, timeout-a ili nepostojećeg fajl sistema.

💡 INSIGHT: Empirijski dokaz iz Next.js AI Agent Evaluations
Zvanični Next.js AI Agent Evaluations pokazuju da version-matched dokumentacija i AGENTS.md kod mnogih agenata značajno povećavaju success rate - često do 90%+, iako veličina dobitka zavisi od konkretnog modela (npr. Claude Sonnet 4.6 skok sa 58% na 96%, Kimi K2.6 sa 67% na 96%, dok modeli poput GPT-5.6 ili Grok 4.6 već imaju visoku osnovnu stabilnost oko 92%). Ovaj vodič služi upravo kao ta stroga baza znanja.


Sekcija 0: Version-Aware AI Development

kod
┌─────────────────────────────────────────────────────────────┐
│                 VERIFIKACIJA OKRUŽENJA (Pravilo 0)          │
└─────────────────────────────────────────────────────────────┘
                               │
       1. Čitanje package.json -> next, react, react-dom, node
       2. Čitanje dokumentacije -> node_modules/next/dist/docs/
       3. Poštovanje pravila   -> AGENTS.md / CLAUDE.md

Pravilo 0: AI agent mora proveriti tačnu verziju pre generisanja koda

Pre implementacije, agent mora pročitati package.json i utvrditi tačne verzije: next, react, react-dom, typescript i node. Nikada se ne sme pretpostavljati ponašanje framework-a samo na osnovu opšteg naziva verzije.

Pravilo 1: Obavezno čitanje version-matched dokumentacije

Pre pisanja koda koji se oslanja na specifične API-je (posebno keširanje, Server Actions i Metadata), agent mora konsultovati lokalnu dokumentaciju koja dolazi uz instalirani paket u node_modules/next/dist/docs/.

Pravilo 2: Prioritet lokalnih pravila repozitorijuma

Ako u repozitorijumu postoje fajlovi AGENTS.md ili CLAUDE.md, njihova pravila i arhitektonska ograničenja imaju apsolutni prioritet nad generičkim asocijacijama modela.

Pravilo 3: Zabrana izmišljanja nepostojećih API-ja (No Hallucinated APIs)

Ako agent nije 100% siguran u postojanje funkcije (npr. NextResponse.magicRedirect() ili cacheSomething()), dužan je da proveri definicije tipova ili dokumentaciju umesto da nagađa API.

Pravilo 4: Poštovanje postojećeg Package Manager-a

Ako projekat koristi pnpm-lock.yaml, zabranjeno je pokretanje npm install (i obrnuto za yarn.lock / package-lock.json / bun.lockb).


Sekcija I: Arhitektura & Granice Komponenti

kod
[ BROWSER / CLIENT ]
       │
       ▼ (Interaktivna stanja: useState, dogadaji, DOM)
 ┌──────────────────────────────────────────────────────────┐
 │  Client Boundary (Što dublje i uže u stablu)             │
 └──────────────────────────────────────────────────────────┘
       │  (Kompozicija kroz children / Server Action pozivi)
       ▼
 ┌──────────────────────────────────────────────────────────┐
 │  React Server Components (RSC) - DEFAULT RENDERING       │
 └──────────────────────────────────────────────────────────┘
       │  (Direktan interni poziv - BEZ HTTP fetch na /api)
       ▼
 ┌──────────────────────────────────────────────────────────┐
 │  DATA ACCESS LAYER (DAL) + DTO Shaper (server-only)      │
 │  • verifySession()                                       │
 │  • Tenant Scoping (organizationId)                       │
 │  • Resource Ownership Check                              │
 └──────────────────────────────────────────────────────────┘
       │
       ▼
 ┌──────────────────────────────────────────────────────────┐
 │  DATABASE / ORM (Prisma, Drizzle, Kysely, SQL)           │
 └──────────────────────────────────────────────────────────┘

Pravilo 5: Server Component je podrazumevani izbor (Default)

U App Router arhitekturi svaka komponenta ostaje Server Component sve dok ne postoji konkretan razlog za klijentsku interakciju. Server Components ne dodaju sopstveni komponentni JavaScript u client bundle.

Pravilo 6: Klijentske granice držati što dublje i uže u stablu

Nemojte postavljati 'use client' na page.tsx ili layout.tsx kao podrazumevano rešenje. Ako čitava granica zaista zahteva klijentsko izvršavanje, takva odluka mora biti namerna i arhitektonski opravdana.

Pravilo 7: Podrška za Wrapping i Provider kompoziciju

Kada klijentska komponenta mora poslužiti kao provajder (npr. ThemeProvider ili TooltipProvider), ona treba da prihvata server-renderovani sadržaj kroz prop children, čime server komponente ostaju na serveru bez pretvaranja u klijentski JS bundle.

Pravilo 8: Server kod ne znači automatski Route Handler (/api)

Ako Server Component treba podatke iz baze, ona direktno poziva funkciju iz Data Access Layer-a (DAL). Pravljenje sopstvenog /api/data endpointa samo da bi ga server komponenta zvala preko fetch stvara nepotreban mrežni krug, kašnjenje i nepotrebnu javnu površinu za napad.

Pravilo 9: Precizna matrica izbora: Server Component vs Server Action vs Route Handler

Situacija / ZahtevPreporučeno rešenjeZašto?
Čitanje podataka za rendering straniceServer ComponentNema sopstvenog JS-a u bundle-u, direktan pristup DAL-u, optimalan streaming.
Mutation sa forme ili UI interakcijeServer ActionNativna React mutacija sa progressive enhancement podrškom; input i autorizacija se validiraju u runtime-u, a keš invalidacija definiše eksplicitno.
Spoljni Webhook (Stripe, Resend, Clerk)Route Handler (route.ts)Standardni HTTP endpoint, provera potpisa sirovog tela (raw body), status kodovi.
Javni API / Mobilna aplikacijaRoute HandlerStandardni REST/JSON interfejs sa javnim CORS i rate-limit pravilima.
Generisani fajlovi (PDF, CSV download)Route HandlerPotpuna kontrola nad HTTP stream-om i Content-Disposition zaglavljima.
Često pulsirajući podaci na klijentuRoute Handler + SWR/TanStackEfikasno dedupliciranje, pozadinsko osvežavanje i optimistički keš na klijentu.

Pravilo 10: Server Actions nisu zamena za GET API

Server Actions se izvršavaju isključivo kao POST zahtevi i nisu namenjene za standardni data fetching. Za čitanje podataka koristite Server Components ili DAL.

Pravilo 11: Zabrana mešanja klijentskih i serverskih modula bez barijere

Moduli koji barataju tajnama, bazom ili administratorskim funkcijama moraju sadržati import 'server-only' na samom vrhu.

Pravilo 12: Minimalni blast radius pri izmenama

Zadatak koji glasi "popravi dugme" ne sme proizvesti prepisivanje rutera, migraciju ORM-a ili uvođenje novog globalnog state menadžera.

Pravilo 13: Očuvanje usklađenosti i postojećih arhitektonskih obrazaca

Pre kreiranja novih pomoćnih biblioteka (npr. utils2.ts ili new-auth.ts), agent mora pretražiti postojeću bazu koda i iskoristiti već uspostavljene obrasce.


Sekcija II: Bezbednost, Autorizacija & DAL / DTO Arhitektura

kod
      Klijentski Zahtev (User ID: "user_99", Target Post: "post_123")
                          │
                          ▼
            ┌───────────────────────────┐
            │       proxy.ts            │ -> (Gruba provera sesije, routing)
            └───────────────────────────┘
                          │
                          ▼
            ┌───────────────────────────┐
            │       Server Action       │ -> (Zod validacija formata i tipova)
            └───────────────────────────┘
                          │
                          ▼
 ╔═══════════════════════════════════════════════════════════════════════╗
 ║                     DATA ACCESS LAYER (DAL)                           ║
 ║                                                                       ║
 ║  1. verifySession() -> Ko si ti? (AuthN)                              ║
 ║  2. checkPermission('posts:edit') -> Smeš li generalno? (AuthZ)       ║
 ║  3. verifyOwnership(session.userId, postId) -> Da li je tvoje?        ║
 ║  4. Tenant Isolation: WHERE id = ? AND orgId = ?                      ║
 ║  5. DTO Shaper: Izbaci passwordHash, stripeCustomerId, interne beleške ║
 ╚═══════════════════════════════════════════════════════════════════════╝
                          │
                          ▼
            ┌───────────────────────────┐
            │         Baza Podataka     │
            └───────────────────────────┘

Pravilo 14: UI nije bezbednosna granica

Sakrivanje komponente pod uslovom {user.role === 'admin'} ne štiti samu operaciju. Svako može poslati direktan POST zahtev. Autorizacija se uvek mora izvršiti na serveru pre pristupa podacima.

Pravilo 15: Autentifikacija (AuthN) nije Autorizacija (AuthZ)

Provera if (!session) throw new Error() dokazuje samo da je korisnik ulogovan, ali ne i da ima pravo da menja traženi resurs.

Pravilo 16: Svaki ulazni ID je pod kontrolom napadača (IDOR odbrana)

Nikada nemojte verovati ID-ju koji dolazi sa klijenta (postId, invoiceId, orgId). Upit uvek mora uključivati identifikator vlasnika ili organizacije iz verifikovane sesije.

typescript
// ❌ KATASTROFALNO: IDOR propust
export async function deletePost(postId: string) {
  const session = await verifySession();
  await db.post.delete({ where: { id: postId } }); // Svako može obrisati tuđ post!
}

// ✅ ISPRAVNO: Izolacija po vlasniku i tenantu
export async function deletePost(postId: string) {
  const session = await verifySession();
  const deleted = await db.post.deleteMany({
    where: {
      id: postId,
      authorId: session.userId,
      organizationId: session.organizationId,
    },
  });
  if (deleted.count === 0) {
    throw new Error('Resurs nije pronađen ili nemate ovlašćenje.');
  }
}

Pravilo 17: Obavezno scope-ovanje svih upita u Multi-Tenant sistemima

Svaki upit u višekorisničkim (SaaS) sistemima mora u where klauzuli sadržati organizationId ili tenantId izvučen iz proverene serverske sesije.

Pravilo 18: Ne prihvatajte identitet sa klijenta

Klijent nikada ne šalje svoj userId ili role u telu zahteva ako ti podaci već postoje u kriptografski potpisanoj sesiji.

Pravilo 19: Zod validacija nije autorizacioni sistem

Zod garantuje ispravnost tipa podatka (npr. da je string dužine do 100 karaktera), ali ne može znati da li korisnik sme da izvrši akciju.

Pravilo 20: Preporučeni Data Access Layer (DAL) i servisna granica

Za nove aplikacije i sisteme koji nemaju već uspostavljenu backend granicu, privilegovani pristup podacima treba centralizovati u server-only DAL/service sloju. Postojeći sistemi sa nezavisnim REST/GraphQL backendom mogu zadržati tu HTTP granicu uz Zero Trust model. Ovaj vodič standardizuje lib/dal/ kao preporučenu konvenciju.

typescript
// lib/dal/account.ts
import 'server-only';
import { db } from '@/lib/db';
import { verifySession } from '@/lib/auth';

export async function getAccountBillingDTO() {
  const session = await verifySession();
  
  const account = await db.account.findFirst({
    where: { id: session.accountId, organizationId: session.organizationId },
    select: {
      id: true,
      companyName: true,
      plan: true,
      // Osetljivi podaci (tokeni, interni ključevi) se NE selektuju
    }
  });

  if (!account) throw new Error('Nalog nije pronađen.');
  return account;
}

Pravilo 21: Klijentske komponente nikada ne dobijaju sirovi ORM entitet (DTO Shaper)

Objekti iz baze mogu sadržati passwordHash, stripeCustomerId ili secretFlags. Kroz DTO šablon klijentu se prosleđuju isključivo javno dozvoljena polja.

Pravilo 22: Sve što prelazi Server -> Client granicu je javno

Podaci poslati kroz props, Server Action odgovor ili Route Handler JSON dostupni su korisniku u DevTools-u. Smatrajte ih javnim za tog korisnika.

Pravilo 23: NEXT_PUBLIC_ je potpuno javan

Promenljive sa prefiksom NEXT_PUBLIC_ ulaze u JS bundle. Nikada nemojte ovde stavljati API tajne, privatne ključeve baze ili payment tajne.

Pravilo 24: proxy.ts nije zamena za autorizaciju u DAL-u

proxy.ts (ili middleware) je pogodan za grube provere, preusmeravanja i rano odbacivanje neulogovanih korisnika, ali konačna autorizacija se mora desiti u samoj operaciji.

Pravilo 25: Route Handler je javna HTTP površina (Attack Surface)

Svaki route.ts mora se tretirati kao javno dostupna HTTP površina i primeniti kontrole koje odgovaraju njegovom ugovoru: input validation, AuthN/AuthZ gde su potrebni, rate/abuse protection za skupe ili izložene operacije, body/content-type limite i bezbedno rukovanje greškama.


Sekcija III: Proširene Web Security Granice

Pravilo 26: Robusna zaštita od SSRF napada (Server-Side Request Forgery)

Ako server preuzima sadržaj sa proizvoljnog URL-a koji korisnik unosi:

  • Dozvoliti isključivo http: i https: protokole.
  • Izvršiti DNS rezoluciju i blokirati sve non-public / non-global IP adrese koristeći pouzdanu IP klasifikaciju (uključujući 0.0.0.0/8, 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, 100.64.0.0/10, 224.0.0.0/4, 240.0.0.0/4, ::1, fc00::/7, fe80::/10, link-local, multicast, reserved i IPv4-mapped IPv6).
  • DNS i IP validaciju obavezno ponoviti nakon svakog HTTP redirect koraka (sprečiti da eksterni host uradi 302 preusmeravanje na interni servis).
  • Postaviti striktan timeout (npr. 3 sekunde) i limit maksimalne veličine odgovora (npr. 5 MB).
kod
URL parse -> Protocol allowlist -> DNS resolve -> Classify every resolved IP -> Connect
                                                            │ (Ako je redirect)
                                                            └-> PONOVITI PUNU VALIDACIJU

Pravilo 27: Bezbedan upload fajlova preko Pre-Signed URL-ova

Nikada ne propuštajte velike fajlove direktno kroz Next.js serverless memoriju niti ih čuvajte na lokalni disk.

  • Browser traži potpisani URL od Server Action-a (gde se proverava kvota i autorizacija).
  • Upload se vrši direktno u Object Storage (S3 / Cloud Storage / R2).
  • Verifikujte tip fajla preko magic bytes zaglavlja, a ne samo na osnovu ekstenzije.

Pravilo 28: Zaštita od XSS i bezbedno rukovanje HTML-om

Izbegavajte dangerouslySetInnerHTML. Kada je renderovanje korisničkog HTML-a ili Markdown-a neophodno, obavezno koristite provereni sanitizer (poput DOMPurify ili sanitize-html) sa striktnom allowlist-om tagova i atributa.

Pravilo 29: Content Security Policy (CSP) i zasebna HTTP Security zaglavlja

  • Content Security Policy (CSP): Definišite striktne direktive: script-src, connect-src, img-src, style-src i frame-ancestors 'none'.
  • HTTP Security Headers: Zasebno konfigurišite Strict-Transport-Security (HSTS), X-Content-Type-Options: nosniff i Referrer-Policy: strict-origin-when-cross-origin.

Pravilo 30: Validacija Open Redirect URL-ova

Preusmeravanja nakon prijave (/login?returnTo=...) moraju prihvatati isključivo relativne interne putanje koje počinju sa / (ali ne i //) ili strogo allowlist-ovane eksterne domene.

Pravilo 31: Bezbednosne zastavice za kolačiće (Cookie Security Flags)

Autentifikacioni kolačići moraju po defaultu imati zastavice: HttpOnly, Secure (u produkciji) i SameSite=Lax ili SameSite=Strict. SameSite=None koristiti isključivo kada aplikacija dokazano zahteva cross-site semantiku i tada je Secure strogo obavezan.

Pravilo 32: CORS se nikada ne rešava sa * na autentifikovanim rutama

Zaglavlje Access-Control-Allow-Origin: * ne sme se postavljati na rutama koje barataju privatnim podacima ili koriste credentials.

Pravilo 33: Kriptografska verifikacija Webhook potpisa

Eksterni webhook pozivi (Stripe, GitHub, Clerk) moraju verifikovati sirovi potpis (raw body) pre bilo kakve obrade podataka.

Pravilo 34: Zaštita od Replay napada na Webhook rutama

Proverite timestamp prema toleranciji koju propisuje konkretni provider (npr. do 5 minuta tolerancije), i gde postoji event ID primenite deduplikaciju/idempotency.

Pravilo 35: Ograničenje veličine i dubine tela zahteva (Body Limits)

Sprečite Denial-of-Service napade slanjem ogromnih JSON payload-a ograničavanjem maksimalne veličine tela u Route Handler-ima.

Pravilo 36: Validacija i ograničenje parametara pretrage i filtriranja

Parametri poput ?limit=1000000 mogu oboriti bazu. Server mora nametnuti gornju granicu (npr. Math.min(limit, 50)).

Pravilo 37: Paginacija kontrolisana isključivo na serveru

Nikada ne prepuštajte browseru definisanje sirovog SQL OFFSET-a ili naziva kolone za sortiranje bez striktne allowlist provere.


Sekcija IV: Stanje, Mutacije & Pouzdanost Transakcija

Pravilo 38: Idempotency ključevi za kritične mutacije

Akcije koje vrše naplatu, kreiraju narudžbine ili šalju mejlove moraju koristiti Idempotency Key kako dupli klik korisnika ili mrežni retry ne bi proizveo duple troškove.

Pravilo 39: Višekoračne promene u bazi i Cross-System tokovi

  • Unutar baze: SQL transakcije (db.$transaction) štite atomarnost međusobno povezanih zapisa.
  • Preko eksternih servisa: Kada operacija prelazi granice baze (npr. Baza + Stripe + Email + Red poruka), primenite Outbox/Event pattern ili Saga/Compensation model, jer jedna SQL transakcija ne može obuhvatiti eksterne HTTP pozive.

Pravilo 40: Server Action kao nativna mutation primitive

Server Actions su primarno dizajnirane za mutacije. Zahtevaju runtime validaciju unosa i eksplicitno definisanu strategiju invalidacije keša.

Pravilo 41: Optimistički UI mora imati Rollback strategiju

Kada klijentska komponenta odmah prikaže novi rezultat pre potvrde servera (npr. preko useOptimistic), mora postojati definisan mehanizam za vraćanje na prethodno stanje ukoliko server odbije mutaciju.

Pravilo 42: Centralizovani Permission Gates

Poslovna pravila (npr. canEditArticle(user, article)) moraju biti izdvojena u čiste funkcije koje podjednako koriste Server Components, Server Actions i pozadinski job-ovi.

Pravilo 43: Timeouts za sve eksterne pozive

Svaki poziv ka eksternom API-ju mora imati definisan AbortSignal.timeout(ms) kako spora treća strana ne bi zablokirala serverske niti.

Pravilo 44: Bezbedni Retry mehanizmi sa Idempotency Budžetom

Automatski retry primenjivati na prirodno idempotentne operacije ili na mutacije koje imaju eksplicitnu idempotency/deduplication zaštitu, uz eksponencijalno odlaganje (exponential backoff sa jitter-om), limit maksimalnih pokušaja i ukupan timeout budžet.


Sekcija V: Next.js 16 Cache Components & Savremena Caching Semantika

Next.js 16 uvodi Cache Components kao objedinjeni model keširanja kroz direktivu 'use cache', podržanu u next.config.ts.

typescript
// next.config.ts (Next.js 16 Active LTS)
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  cacheComponents: true,
};

export default nextConfig;
kod
┌─────────────────────────────────────────────────────────────┐
│                 ZAHTEV ZA PODACIMA                          │
└─────────────────────────────────────────────────────────────┘
                               │
               Da li su podaci personalizovani?
             ┌─────────────────┴─────────────────┐
            DA                                  NE
             │                                   │
             ▼                                   ▼
 ┌───────────────────────────┐      ┌───────────────────────────┐
 │   PRIVATNI / KORISNIČKI   │      │     JAVNI / STATIČKI      │
 ├───────────────────────────┤      ├───────────────────────────┤
 │ • Argument funkcije:      │      │ • 'use cache' (in-memory) │
 │   getOrders(userId)       │      │ • 'use cache: remote'     │
 │ • Dinamički request       │      │ • cacheTag('catalog')     │
 │ • updateTag() na izmenu   │      │ • cacheLife('hours')      │
 └───────────────────────────┘      └───────────────────────────┘

Pravilo 45: Direktni uvoz cacheTag i cacheLife iz 'next/cache'

U Next.js 16, funkcije cacheTag i cacheLife su stabilni API-ji. Uvoze se direktno:

typescript
import { cacheTag, cacheLife } from 'next/cache';

Pravilo 46: Zabrana pristupa request-time API-jima unutar 'use cache'

Standardni 'use cache' blok ne sme direktno pozivati cookies(), headers() ili searchParams. Kontekstualni podaci (npr. userId) moraju se pročitati van keširane funkcije i proslediti kao argumenti, jer Next.js uključuje argumente funkcije u deterministički cache key.

typescript
// ✅ ISPRAVNO: Argument funkcije ulazi u deterministički cache key
import { cacheTag, cacheLife } from 'next/cache';
import { verifySession } from '@/lib/auth';
import { db } from '@/lib/db';

async function getCachedUserOrders(userId: string) {
  'use cache';
  cacheTag(`user-orders-${userId}`);
  cacheLife('minutes');

  return db.order.findMany({
    where: { userId },
  });
}

export async function UserOrders() {
  const session = await verifySession();
  const orders = await getCachedUserOrders(session.userId);
  return <OrdersList orders={orders} />;
}

Pravilo 47: Tri modela keširanja u Next.js 16: Local, Remote i Private

Next.js 16 podržava tri jasno razdvojena nivoa:

  1. 'use cache' (Default/Server): In-process keširanje unutar aktivne instance.
  2. 'use cache: remote' (Distributed/Shared): Deljeni keš između više server instanci podržan kroz cacheHandlers adaptere (Redis, Memcached, DynamoDB). Uvodi mrežni round-trip pa se koristi ciljano.
  3. 'use cache: private' (Browser Memory): Izvršava se na serveru, ali se rezultat nikada ne skladišti na server-side kešu već isključivo u efemernoj memoriji browsera (ne preživljava reload).

Pravilo 48: updateTag za Server Actions i Read-Your-Own-Writes konzistentnost

Kada korisnik izmeni sopstvene podatke, koristite updateTag za momentalno osvežavanje stanja:

typescript
// app/actions/profile.ts
'use server';

import { updateTag } from 'next/cache';
import { verifySession } from '@/lib/auth';
import { db } from '@/lib/db';

export async function updateProfile(formData: FormData) {
  const session = await verifySession();
  const displayName = String(formData.get('displayName'));

  await db.user.update({
    where: { id: session.userId },
    data: { displayName },
  });

  // Momentalna invalidacija za tog korisnika (Read-Your-Own-Writes)
  updateTag(`user-profile-${session.userId}`);
}

Pravilo 49: revalidateTag(tag, 'max') za pozadinsku revalidaciju

Za javne kataloge, blogove i CMS sadržaje koristite stale-while-revalidate model:

typescript
import { revalidateTag } from 'next/cache';

// Poziva se npr. unutar CMS webhook-a
export async function onCmsPublish() {
  revalidateTag('public-products', 'max');
}

(Napomena: Poziv sa jednim argumentom revalidateTag(tag) je zastareo u Next.js 16).

Pravilo 50: revalidatePath koristiti namenski

Koristite revalidatePath samo kada želite da osvežite čitavu stranicu ili ruter stablo, vodeći računa o tome da to ne izazove nepotrebno ponovno renderovanje nepromenjenih segmenata.

Pravilo 51: Razlikovanje stabilnog Next.js 16 Cache Components modela od Next.js 15 eksperimentalne semantike

Next.js 16 koristi stabilizovan Cache Components model. Next.js 15 je već imao eksperimentalni 'use cache', paralelno sa postojećim unstable_cache i fetch caching obrascima. Agent zato mora koristiti version-matched dokumentaciju i ne sme zaključivati caching semantiku samo iz major verzije.

Pravilo 52: Eksplicitno definisana strategija keširanja

Pre dodavanja keširanja odgovorite na pitanja: Šta se kešira? Koji je cache key? Ko ga invalidira? Šta se dešava nakon mutacije?


Sekcija VI: Performanse, Streaming & Hydration Integritet

Pravilo 53: Eliminacija vodopada (Waterfalls) uz Promise.all

Nezavisne upite pokrećite konkurentno:

typescript
// ✅ Paralelno dohvatanje nezavisnih izvora
const [user, stats, notifications] = await Promise.all([
  getUser(),
  getStats(),
  getNotifications(),
]);

Pravilo 54: Kombinujte route-level loading.tsx i granularne Suspense granice

loading.tsx je validna route-level Suspense granica koja omogućava instant loading UI i streaming dok deljeni layout ostaje interaktivan. Za finiju kontrolu postavite dodatne <Suspense> granice što bliže sporim ili dinamičkim podstablima, kako bi nezavisni delovi stranice mogli biti prikazani ranije.

Pravilo 55: Izbegavanje sirovog useEffect(fetch) na klijentu

Za podatke koji se učitavaju na klijentu preferirajte SWR ili TanStack Query radi automatske deduplikacije, keširanja i 'stale-while-revalidate' obrade.

Pravilo 56: Rešavanje pravog uzroka Hydration Mismatch-a

Nemojte maskirati greške stavljanjem suppressHydrationWarning. Proverite:

  • Korišćenje Date.now(), new Date() ili Math.random() pri inicijalnom renderu.
  • Razlike u lokalizaciji ili renderovanje zasnovano na window i localStorage.
  • Nevalidno HTML ugnježđavanje (npr. <p> unutar <p>, ili <div> unutar <p>).

Pravilo 57: Optimizacija slika kroz next/image i preload u Next.js 16

U Next.js 16 svojstvo priority je zastarelo (deprecated) u korist svojstva preload. Za poznati LCP/hero element razmotrite preload, odnosno loading="eager" ili fetchPriority="high" u zavisnosti od konkretnog loading modela. Obavezno definišite sizes i dimenzije radi sprečavanja Cumulative Layout Shift (CLS).

tsx
<Image
  src="/images/hero.webp"
  alt="Next.js 16 Architecture"
  width={1200}
  height={630}
  sizes="(max-width: 768px) 100vw, 1200px"
  preload
/>

⚠️ Security note - Image Optimization je server-side parser attack surface:
next/image nije samo vizuelna optimizacija. Kada Next.js server obrađuje spoljne ili korisnički kontrolisane slike, image decoder i njegovi native dependencies (poput libheif / sharp) postaju deo serverske površine za napad. Zvanični bezbednosni incident GHSA-2xp9-vwfh-vxw4 (avgust 2026) demonstrirao je rizik gde je AVIF obrada mogla dovesti do unauthenticated Remote Code Execution (RCE) u verzijama ispod 16.3.3. Uvek ograničite spoljne izvore slika striktnim remotePatterns pravilima u next.config.ts i redovno ažurirajte framework.

Pravilo 58: Optimizacija fontova kroz next/font

Koristite next/font/google ili next/font/local kada želite Next.js optimizaciju i automatsko self-hostovanje fontova bez eksternih mrežnih zahteva u runtime-u:

typescript
import { Inter } from 'next/font/google';
import localFont from 'next/font/local';

Pravilo 59: Oprezno korišćenje next/dynamic

Dynamic import koristite samo za masivne komponente koje nisu odmah vidljive (npr. teški grafikoni, bogati tekstualni editori, modali). Previše sitnih dinamičkih chunk-ova stvara mrežni overhead.

Pravilo 60: Kontrola eksternog JavaScript-a (Third-Party Scripts)

Za non-critical eksterni JavaScript (analitika, marketing, chat vidžeti) koristite strategije afterInteractive ili lazyOnload u skladu sa prioritetom integracije. Strategiju beforeInteractive rezervišite isključivo za retke kritične skripte neophodne pre hidratacije.

Pravilo 61: Kontinuirano merenje veličine Bundle-a

Koristite Next.js bundle analyzer (@next/bundle-analyzer) ili izveštaj produkcionog build-a kao primarni izvor istine. Alati poput Bundlephobia služe samo kao gruba pre-install procena.


Sekcija VII: Production Runtime, Deployment & Resursi

Pravilo 62: Serverless fajl sistem nije trajno skladište

U serverless okruženju lokalni disk (fs.writeFile) je efemeran i gubi se nakon gašenja instance. Koristite Object Storage ili bazu podataka.

Pravilo 63: Baza i Connection Pooling na Serverless platformama

Serverless funkcije mogu otvoriti stotine paralelnih konekcija i zagušiti bazu. Koristite connection pooler (npr. PgBouncer, Prisma Accelerate, Neon pooling, Supabase pooler).

Pravilo 64: Zahtevi koji dugo traju (Long-running jobs)

Serverless/lambda platforme nameću provider-specific maksimalno trajanje izvršavanja. Agent mora proveriti hosting i plan pre projektovanja operacija koje dugo traju i delegirati ih background queue/worker sistemima (npr. Inngest, Trigger.dev ili BullMQ).

Pravilo 65: WebSockets i Serverless ograničenja

Persistentni WebSockets nisu kompatibilni sa kratkoživećim serverless hosting modelom. Koristite namenske servise (Pusher, Ably, PartyKit) ili dugoživeći kontejnerski proces.

Pravilo 66: Distribuirani Rate Limiting

In-memory brojači (new Map()) funkcionišu isključivo kao lokalni limiter u okviru jednog Node.js procesa. U horizontalno skaliranim ili serverless okruženjima obavezan je centralizovani store (Redis / Upstash).

Pravilo 67: Validacija Environment promenljivih na Startup-u (Fail-Fast)

Definišite šemu (npr. preko @t3-oss/env-nextjs ili Zod) kako aplikacija ne bi startovala ako u produkciji nedostaje kritična promenljiva (DATABASE_URL, AUTH_SECRET). Nikada nemojte stavljati tihe fallback vrednosti u stilu process.env.SECRET || 'dev-secret'.


Sekcija VIII: Pouzdanost, Greške & Observability

Pravilo 68: Hijerarhija Error Boundaries

Ključni route segmenti treba da imaju error.tsx gde je potrebna lokalna recovery granica i not-found.tsx gde ruta ima semantiku "nije pronađeno". Fajl app/global-error.tsx je isključivo root-level fallback za greške koje zahvataju root layout.tsx/template.tsx i mora sam sadržati <html> i <body> tagove.

Pravilo 69: Razdvajanje korisničkih i internih grešaka

Korisniku se prikazuje generička, sigurna poruka ("Došlo je do greške pri obradi"), dok se detaljan stack trace i interni podaci beleže isključivo u serverskim logovima.

Pravilo 70: Strukturirani logovi sa Request ID korelacijom

Svaki serverski log mora sadržati jedinstveni requestId koji se propagira kroz sve slojeve obrade radi brze dijagnostike u APM alatima.

Pravilo 71: Automatska redakcija osetljivih podataka iz logova

Serverski logovi treba da sadrže sanitizovan dijagnostički kontekst (request ID, error code, stack, operaciju, trajanje). Lozinke, sesijski tokeni, Authorization zaglavlja i sirovi SQL upiti koji sadrže PII podatke moraju biti strogo redaktovani.

Pravilo 72: Praćenje i metrike ključnih operacija

Pratite stope grešaka i latenciju na kritičnim tokovima (autentifikacija, plaćanja, AI generisanje) uz pomoć alata kao što su Sentry ili OpenTelemetry.

Pravilo 73: Semantički HTML i pristupačnost (A11y)

AI generisani interfejsi moraju koristiti nativne semantičke elemente (<button>, <nav>, <main>, <header>), sa potpunom podrškom za navigaciju putem tastature i ispravnim ARIA atributima.


Sekcija IX: Testiranje, Verifikacija & Kvalitet Koda

Pravilo 74: Zabrana uklanjanja provera radi prolaska taska

Strogo je zabranjeno rešavati probleme stavljanjem any, // @ts-ignore, // @ts-expect-error ili gašenjem ESLint pravila samo radi prikrivanja grešaka. Izuzetak za @ts-expect-error je dozvoljen isključivo kada postoji usko lokalizovan, dokumentovan i proverljiv razlog (npr. type-level testovi ili privremeni workaround za neispravne eksterne tipove).

Pravilo 75: Production Build komanda je obavezna kapija (Gate)

Razvojni server (next dev) ne proverava sve greške statičke optimizacije. Pre proglašavanja zadatka završenim, obavezno je pokrenuti production build komandu odgovarajućeg package manager-a (npr. pnpm build, npm run build, yarn build ili bun run build).

Pravilo 76: E2E testiranje na produkcionom buildu

Kritične korisničke tokove (prijava, odjava, checkout) testirajte alatom Playwright pokrenutim nad okruženjem koje što vernije odgovara ciljnom deployment target-u (za standardni Node.js server to je next build + next start).

Pravilo 77: Obavezni negativni bezbednosni testovi

Pored testiranja uspešnih tokova, testirajte i nedozvoljene akcije: Korisnik B pokušava da izmeni post korisnika A; Neautorizovani korisnik poziva Server Action; Webhook sa lažnim potpisom se odbija.

Pravilo 78: SEO i konfigurabilni Metadata API

Javne stranice treba da imaju relevantne title, description, canonical, Open Graph i Twitter metapodatke. Koristite statički metadata export kada su vrednosti unapred poznate, a funkciju generateMetadata kada podaci zavise od dinamičkih parametara rute ili runtime upita.

Pravilo 79: Zaštita privatnih ruta od indeksiranja

Administratorske i korisničke kontrolne table moraju u metapodacima sadržati robots: { index: false, follow: false }.

Pravilo 80: Patch-level security verification je production gate (Next.js 16.3.3+)

Sama činjenica da je aplikacija na "Next.js 16" ne garantuje bezbednost. Pre svakog puštanja u produkciju neophodno je proveriti zvanične Next.js Security Advisories i tačnu instaliranu patch verziju.

🔒 Security Release Gate (Obavezna procedura):

  1. Proverite tačnu next verziju u package.json i package-lock.json/pnpm-lock.yaml.
  2. Proverite zvanične GitHub Security Advisories.
  3. Od 26. avgusta 2026. aktuelni produkcioni minimum za Next.js 16 je 16.3.3, koji rešava kritičnu CVSS 9.5 RCE ranjivost u AVIF obradi (GHSA-2xp9-vwfh-vxw4).
  4. Ako postoji Critical/High advisory koji pogađa instaliranu verziju - release je BLOCKED.
  5. Tek nakon primene patch-a pokrenite ponovni build i bezbednosne testove.

Sekcija X: AI Coding Agent 10-Phase Execution Protocol

Ovaj protokol predstavlja standardizovani radni okvir koji AI coding agenti mogu koristiti pre i tokom izvršavanja zadatka:

kod
┌─────────────────────────────────────────────────────────────┐
│                 10-FAZNI PROTOKOL ZA AGENTE                 │
└─────────────────────────────────────────────────────────────┘
  1. Reconnaissance -> package.json, TypeScript i runtime
  2. Doc Matching   -> node_modules/next/dist/docs/ & AGENTS.md
  3. Classification -> Server vs Client / Read vs Mutation
  4. Threat Model   -> AuthN, AuthZ, Tenant IDOR, Rate Limits
  5. Data Boundary  -> DAL (server-only) i DTO Shaper
  6. Implementation -> Minimalni klijentski JS, čista tipizacija
  7. Caching & Perf -> use cache, updateTag, Suspense, Promise.all
  8. Typecheck/Lint -> Provera tipova bez 'any' i lažnih supresija
  9. Security Tests -> Pokušaj zloupotrebe i IDOR manipulacije
 10. Production Gate-> Package-manager native build & Playwright
  • Faza 1 - Rekognosciranje: Provera verzija paketa, tipa rutera (App Router), ORM-a i hosting okruženja.
  • Faza 2 - Provera dokumentacije: Usklađivanje sa instaliranom verzijom Next.js-a (node_modules/next/dist/docs/).
  • Faza 3 - Klasifikacija zadatka: Određivanje arhitektonske uloge (Server Component za čitanje, Server Action za mutaciju, Route Handler za spoljni API).
  • Faza 4 - Model pretnji (Threat Modeling): Identifikacija potencijalnih IDOR, SSRF, XSS i tenant izolacionih propusta.
  • Faza 5 - Granica podataka: Formiranje server-only DAL funkcija i DTO filtera.
  • Faza 6 - Implementacija: Pisanje modularnog koda bez suvišnog 'use client' spama.
  • Faza 7 - Optimizacija i keširanje: Postavljanje cacheTag, cacheLife i updateTag logike, uz eliminaciju mrežnih vodopada.
  • Faza 8 - Statička verifikacija: Provera TypeScript pravila bez zaobilaznih trikova.
  • Faza 9 - Negativni testovi: Simulacija napada sa nevažećim sesijama i tuđim identifikatorima.
  • Faza 10 - Produkciona kapija: Potvrda da nativni package-manager build prolazi sa 100% uspeha i pokretanje E2E testova.

Sekcija XI: The Core Rule & Završna Kontrolna Lista

Zlatno pravilo modernog razvoja:

Kada AI generiše Next.js kod, ne pitajte samo: "Da li ovaj kod radi?"
Pitajte: "Gde se ovaj kod izvršava, ko sme da ga pozove, koje podatke vraća klijentu i šta se dešava ako zahtev stigne dva puta u produkciji?"

Kontrolna lista pre puštanja u produkciju:

  • Da li je instaliran najnoviji bezbednosni patch (Next.js 16.3.3+)?
  • Da li je autorizacija implementirana unutar DAL-a, a ne samo u UI-ju ili proxy.ts?
  • Da li svaki upit u bazi u multi-tenant aplikaciji ima organizationId filter?
  • Da li su klijentske komponente zadržane samo na interaktivnim granicama?
  • Da li moduli sa tajnama imaju import 'server-only'?
  • Da li se koristi updateTag za momentalno osvežavanje stanja korisnika?
  • Da li su privatni podaci zaštićeni od curenja u shared keš?
  • Da li spoljni webhook-ovi verifikuju kriptografski potpis?
  • Da li je SSRF endpoint obezbeđen potpunom DNS i IP klasifikacijom na svim redirect nivoima?
  • Da li production build prolazi sa 100% uspeha bez grešaka i upozorenja?

Reference i Zvanična Dokumentacija