# Što ćete naučiti#
B2B administratorski panel nije samo CRUD ekrani. To je operativna površina na kojoj jedna pogrešna dozvola ili nesigurna masovna radnja može u nekoliko minuta izazvati incident na razini cijelog tenanta.
Ovaj vodič daje referentnu arhitekturu Next.js administratorskog panela za B2B SaaS, fokusiranu na četiri teška problema koja se pojavljuju u svakom ozbiljnom proizvodu: RBAC, revizijski zapisi, sigurna impersonacija i sigurne masovne radnje.
Dobit ćete obrasce na razini implementacije za App Router i API rute, praktične modele baze podataka i kontrolne liste koje možete kopirati u vlastite runbookove.
# Zašto admin paneli padaju u produkciji#
Admin paneli padaju iz predvidljivih razloga:
- Dozvole “odlutaju” kako se featurei isporučuju, što vodi u slučajnu eskalaciju privilegija.
- Revizijski zapisi su preplitki da bi bili korisni tijekom incidenta ili compliance pregleda.
- Impersonacija postoji, ali nije scopeana, nije logirana i nije očita operatoru.
- Masovne radnje su implementirane kao “petlja i update”, što uzrokuje timeoute, djelomične updateove ili slučajnu eksfiltraciju PII podataka.
Učinak u stvarnom svijetu je mjerljiv. IBM-ov Cost of a Data Breach Report 2024 navodi da je globalni prosječni trošak povrede podataka 4,88 milijuna USD, a kompromitirane vjerodajnice i zloupotreba privilegija se iznova nalaze među glavnim početnim vektorima napada. Admin paneli koncentriraju i vjerodajnice i privilegije, pa arhitektonske odluke ovdje izravno utječu na rizik i trošak.
🎯 Ključna poruka: Administratorski panel tretirajte kao sigurnosno kritičan proizvod, a ne kao interni alat. Prvo izgradite dozvole, logiranje i sigurnosne ograde, a zatim gradite featuree povrh toga.
# Referentna arhitektura: slojevi i odgovornosti#
Održiva arhitektura admin panela razdvaja četiri područja: identitet, autorizaciju, izvršavanje i observability. Ova podjela sprječava slučajne “bypass” situacije kada se UI promijeni ili se dodaju novi endpointi.
Komponente na visokoj razini#
| Sloj | Odgovornost | Primjer implementacije |
|---|---|---|
| UI | Admin ekrani i zaštitne ograde | Next.js App Router, server komponente za dohvat podataka, client komponente za tablice i forme |
| BFF API | Jedinstveni ulaz za admin mutacije | Route handleri u app/api/admin/.../route.ts |
| Domain servisi | Poslovna logika s policy provjerama | services/*.ts funkcije koje pozivaju API rute i background jobovi |
| Podaci | Persistencija scopeana po tenantu | Postgres s tenant ključevima na razini redaka, Prisma ili Drizzle |
| Jobovi | Masovne radnje, izvozi, dugotrajni zadaci | Queue poput BullMQ, Cloud Tasks ili managed worker |
| Observability | Logovi, traceovi, audit | Strukturirani logovi, Sentry, OpenTelemetry |
Životni ciklus zahtjeva za admin radnje#
- 1Autentificirajte korisnika i učitajte sesiju.
- 2Razriješite tenant kontekst.
- 3Procijenite autorizacijski policy.
- 4Izvršite radnju kroz servisnu funkciju.
- 5Zapišite audit event s prije-i-poslije podacima gdje je prikladno.
- 6Emitirajte operativne logove i metrike.
Ovaj životni ciklus mora se provoditi na serveru. Provjere samo u UI-ju pomažu UX-u, ali nisu sigurnost.
Za dublje čitanje o autorizacijskim obrascima u Next.js, pogledajte AuthZ obrasci u Next.js App Routeru: RBAC i ABAC. Za postavljanje logiranja i monitoringa, pogledajte Next.js logiranje i monitoring sa Sentryjem i OpenTelemetryjem. Za šire sigurnosno učvršćivanje, pogledajte našu kontrolnu listu sigurnosti web aplikacija.
# Modeliranje dozvola: RBAC s ulogama scopeanim po tenantu i policyjima po resursu#
Većini B2B SaaS admin panela trebaju dva paralelna sustava dozvola:
- Dozvole za platform staff admin, preko tenanata, ali strogo ograničene.
- Dozvole za tenant admin, scopeane na jedan tenant.
Preporučeni data model#
Najbrži put koji dobro skalira je: users, tenants, memberships, roles, permissions i opcionalna policy ograničenja.
| Entitet | Ključna polja | Napomene |
|---|---|---|
users | id, email, status | Globalni identitet |
tenants | id, name, plan | Granica organizacije |
memberships | id, tenant_id, user_id, role_id | Tenant scoping živi ovdje |
roles | id, tenant_id, name | tenant_id može biti null za platform uloge |
permissions | key, description | Stabilni ključevi poput billing.invoice.refund |
role_permissions | role_id, permission_key | Many-to-many |
role_constraints | role_id, json_constraints | Opcionalna ABAC-stil ograničenja |
U praksi želite stabilne permission ključeve koji mapiraju na radnje, a ne na ekrane. Ekrani se mijenjaju; radnje ostaju.
Konvencija imenovanja permission ključeva#
Koristite hijerarhijsku, pretraživu shemu:
user.readuser.updateuser.deletebilling.invoice.readbilling.invoice.refundaudit.readsupport.impersonateexport.customer_pii
Ovakvo imenovanje olakšava provođenje least privilege pristupa, pregled uloga i pretraživanje logova.
Pravila evaluacije policyja#
Autorizacija treba provoditi:
- 1Membership u tenantu je obavezan za tenant-scopeane radnje.
- 2Permission ključ mora postojati.
- 3Scoping resursa mora odgovarati tenant kontekstu.
- 4Opcionalna ograničenja mogu dodatno suziti pristup prema atributima.
Primjeri ograničenja koja se pojavljuju u B2B:
- Dopuštene regije ili podružnice
- Samo dodijeljeni accounti
- Vremenska ograničenja za radnje visokog rizika
- Feature flagovi po tenant planu
ℹ️ Napomena: Ako koristite Postgres, dodavanje tenant scopinga na razini upita je dobro, ali samo po sebi nije dovoljno. Autorizacija se mora događati i na servisnoj granici kako bi i radnje izvan baze—poput exporta, webhookova i poziva prema third-party API-jevima—bile zaštićene.
Mali, provediv authorization API#
Napravite jednu server-side funkciju koju zove svaka admin ruta. Neka bude jednostavna i eksplicitna.
// services/authz.ts
export type AuthContext = {
userId: string;
tenantId: string | null;
roleKeys: string[];
permissionKeys: string[];
isPlatformStaff: boolean;
};
export function requirePermission(
ctx: AuthContext,
permission: string,
opts?: { tenantRequired?: boolean }
) {
if (opts?.tenantRequired && !ctx.tenantId) {
throw new Error("TENANT_REQUIRED");
}
if (!ctx.permissionKeys.includes(permission)) {
throw new Error("FORBIDDEN");
}
}Ovo ne zamjenjuje vaš puni policy engine, ali stvara konzistentnu “usku točku”. Kasnije to možete razviti u ABAC bez prepisivanja svake rute.
# Struktura API-ja i servisa u Next.js App Routeru#
Koristite App Router route handlere za admin endpointove, ali poslovnu logiku držite u servisima. Servisni sloj je mjesto gdje dosljedno provodite tenant scoping, autorizaciju i audit logiranje.
Predloženi layout direktorija#
| Putanja | Svrha |
|---|---|
app/(admin)/admin/... | Admin UI rute |
app/api/admin/.../route.ts | Admin API rute |
services/admin/* | Domain servisi koje zovu rute i jobovi |
services/audit/* | Writer za audit evente i query helperi |
services/impersonation/* | Promjena sesije i kontrole |
lib/logger.ts | Strukturirano logiranje |
lib/queue.ts | Klijent za background jobove |
Primjer: API ruta koja koristi servis#
// app/api/admin/users/[id]/route.ts
import { NextResponse } from "next/server";
import { getAuthContext } from "@/services/session";
import { requirePermission } from "@/services/authz";
import { updateUser } from "@/services/admin/users";
export async function PATCH(req: Request, props: { params: Promise<{ id: string }> }) {
const { id } = await props.params;
const ctx = await getAuthContext(req);
requirePermission(ctx, "user.update", { tenantRequired: true });
const body = await req.json();
const result = await updateUser(ctx, { userId: id, patch: body });
return NextResponse.json(result);
}Važan dio nije route handler. Važno je da updateUser interno logira audit evente i provodi tenant scoping, čak i ako ga kasnije pozove neka druga ruta.
# Revizijski zapisi: što bilježiti, kako spremati i kako pretraživati#
Revizijski zapisi su product feature i alat za incident response. U B2B SaaS-u kupci često traže pristup auditu kao dio SOC 2 spremnosti.
Što logirati#
Minimalno, za svaku admin mutaciju logirajte ova polja:
| Polje | Primjer | Zašto je važno |
|---|---|---|
event_id | evt_... | Povezuje retryjeve i downstream sustave |
timestamp | ISO vrijeme | Rekonstrukcija vremenske linije |
tenant_id | tnt_123 | Multi-tenant izolacija |
actor_user_id | usr_456 | Odgovornost |
actor_type | tenant_user ili platform_staff | Policy i izvještavanje |
action | user.update | Pretraživo |
entity_type | user | Grupiranje |
entity_id | usr_789 | Drill-down |
ip i user_agent | zabilježeno | Forenzika |
request_id | req_... | Korelacija s app logovima |
before i after | JSON isječci | Istraga i povrat (revert) |
Za radnje visokog rizika logirajte i approval_id ako imate approvals, te reason ako tražite obrazloženje operatora.
Sigurno spremanje audit logova#
Audit logovi trebaju biti append-only. Nemojte ih spremati u istu tablicu koju mutirate za business state.
Preporučeni pristup:
- Tablica
audit_eventsu Postgresu s particioniranjem po mjesecu ako je volumen velik. - JSONB payload polja za
before,afterimetadata. - Indeksi na
tenant_id,actor_user_id,action,entity_typeicreated_at.
Retencija je poslovna odluka, ali u B2B-u je uobičajeno zadržavanje 90 do 365 dana ovisno o planu. Učinite je konfigurabilnom po tenant planu, ali nikad ne dopustite tenantu da spusti retenciju ispod vašeg compliance baselinea ako radite u reguliranim tržištima.
⚠️ Upozorenje: Izbjegavajte logiranje sirovih tajni i punog PII-ja u audit logove. Audit logovi se repliciraju, pretražuju i exportaju, pa često postanu nenamjerna sekundarna baza osjetljivih podataka.
Dosljedno pisanje audit događaja#
Napravite jednog audit writera kojeg koriste servisi i background jobovi.
// services/audit/writeAuditEvent.ts
export async function writeAuditEvent(input: {
tenantId: string | null;
actorUserId: string;
actorType: "tenant_user" | "platform_staff";
action: string;
entityType: string;
entityId: string;
before?: unknown;
after?: unknown;
metadata?: Record<string, string>;
requestId?: string;
}) {
// Persist to DB in an append-only way.
// Consider hashing payload fields for tamper evidence.
}Ako imate stroge compliance zahtjeve, dodajte dokaz neovlaštene izmjene (tamper evidence):
- Spremite
prev_event_hashievent_hash = SHA256(prev_event_hash + payload)po tenant streamu. - Nije blockchain, ali daje mogućnost detekcije ako se logovi mijenjaju.
Obrasci upita za admin UI#
Dizajnirajte audit UI oko pitanja koja dobivate tijekom incidenata:
- Što se promijenilo za ovog kupca u zadnja 24 sata
- Tko je danas izdao refundove
- Koji je operator nekoga impersonirao
- Koji je bulk job promijenio više od N zapisa
Filteri trebaju biti “first-class” i brzi. Ako je audit pretraga spora, neće se koristiti kad je najvažnije.
# Impersonacija: siguran dizajn za support i platform ops#
Impersonacija je jedan od najvrjednijih alata za support, ali i jedan od najlakših načina za tihu eskalaciju privilegija.
Sigurnosni zahtjevi za impersonaciju#
Vaša impersonacija treba provoditi:
| Kontrola | Implementacija | Svrha |
|---|---|---|
| Eksplicitna dozvola | support.impersonate | Least privilege |
| Tenant scoping | Samo unutar odabranog tenanta | Sprječava cross-tenant pogreške |
| Označavanje sesije | Spremite impersonator_user_id | Auditabilnost |
| Uvijek vidljiv banner | UI indikator + gumb za izlaz | Sprječava zabunu |
| Ograničenja radnji | Po defaultu blokirati refundove, exporte, izmjene uloga | Smanjuje blast radius |
| Re-auth za osjetljive radnje | Step-up auth | Štiti operacije visokog učinka |
Model s dvije sesije#
Izbjegavajte potpuno “zamjenjivanje” identiteta bez konteksta. Koristite model s dvije sesije:
- Effective user je tenant korisnik kao koji djelujete.
- Impersonator je stvarni operator koji je to pokrenuo.
Oboje spremite u sesiju tako da svaki zahtjev može logirati oba identiteta.
Primjer polja sesije:
| Polje | Primjer |
|---|---|
user_id | effective user |
tenant_id | effective tenant |
impersonator_user_id | operator |
impersonation_started_at | timestamp |
impersonation_reason | ID ticketa ili slobodni tekst |
Primjer: endpoint za pokretanje impersonacije#
// app/api/admin/impersonation/start/route.ts
import { NextResponse } from "next/server";
import { getAuthContext } from "@/services/session";
import { requirePermission } from "@/services/authz";
import { startImpersonation } from "@/services/impersonation/start";
export async function POST(req: Request) {
const ctx = await getAuthContext(req);
requirePermission(ctx, "support.impersonate");
const body = await req.json();
const session = await startImpersonation(ctx, {
tenantId: body.tenantId,
targetUserId: body.targetUserId,
reason: body.reason,
});
return NextResponse.json({ ok: true, session });
}Unutar startImpersonation trebate i:
- 1Provjeriti pripada li target user tom tenantu.
- 2Zapisati audit event poput
impersonation.start. - 3Postaviti vremensko ograničenje, npr. 30 minuta, pa automatski isteći.
💡 Savjet: Za “reason” zahtijevajte ID support ticketa. To pretvara neformalnu radnju u slijediv workflow i smanjuje ponašanje tipa “samo provjeravam”.
# Sigurne masovne radnje: arhitektura i operativne zaštitne ograde#
Masovne radnje su mjesto gdje admin panel postaje opasan. Masovna brisanja, refundovi, promjene uloga i migracije podataka ne bi se smjele izvoditi kao request-response petlje.
Arhitektura masovnih radnji: preview, job i reconciliation#
Dizajnirajte masovne radnje kao flow u tri koraka:
- 1Odabir i preview: prikažite broj i uzorak.
- 2Potvrda i enqueue joba: kreirajte bulk job zapis sa snapshotom upita.
- 3Async izvršavanje s napretkom: worker obrađuje u batchovima uz idempotenciju.
Ovakav pristup izbjegava timeoute, poboljšava pouzdanost i daje čist audit trail.
Data model za bulk job#
| Polje | Primjer | Napomene |
|---|---|---|
job_id | job_... | Primarna referenca za support |
tenant_id | tnt_... | Uvijek scopeano |
actor_user_id | usr_... | Tko je pokrenuo |
action | invoice.refund.bulk | Dozvole i audit |
query | JSON | Snapshot filtera i ID-jeva |
status | queued, running, completed, failed, cancelled | Životni ciklus |
total_count | 12043 | Za napredak |
processed_count | 8200 | Za napredak |
error_count | 3 | Za follow-up |
dry_run | true ili false | Sigurni defaulti |
Obrasci izvršavanja koji sprječavaju djelomične katastrofe#
U workeru implementirajte:
- Idempotency key po itemu, npr.
job_id + entity_id. - Batch size prilagođen vašoj bazi, često 100 do 1000.
- Retry s backoffom, ali stanite nakon ograničenog broja pokušaja.
- Dead-letter handling s listom neuspjelih ID-jeva.
Izbjegavajte “update where filter” upite za destruktivne radnje osim ako možete garantirati ispravnost i logirati točne zahvaćene ID-jeve. Za većinu admin panela eksplicitni ID-jevi su sigurniji, iako sporiji.
Kontrolna lista masovnih radnji za produkciju#
Koristite ovo kao release gate za svaki novi bulk feature.
| Provjera | Zašto | Minimalni zahtjev |
|---|---|---|
| Dozvola je jedinstvena | Sprječava slučajan pristup | Novi permission ključ poput user.disable.bulk |
| Postoji preview korak | Zaustavlja pogrešne filtere | Prikažite broj i uzorak redaka |
| Podržan dry-run | Smanjuje rizik | Default dry_run = true |
| Potvrda traži tipkanje | Sprječava pogrešan klik | Utipkati keyword poput DISABLE |
| Scopeano na tenant | Sprječava cross-tenant | Provesti tenant_id na jobu |
| Koristi se background job | Izbjegava timeoute | Queue + worker |
| Napredak i cancel | Operativna kontrola | Job status API |
| Idempotentno izvršavanje | Sigurni retryjevi | Idempotencija po itemu |
| Zabilježen audit log | Odgovornost | Logirati start i completion joba |
| Rate limiti | Štiti infrastrukturu | Per-tenant i per-actor limiti |
| Export limiti | Sprječava eksfiltraciju podataka | Max redaka ili async export s approvalom |
| PII handling | Compliance | Pravila maskiranja i redakcije |
# Izvozi i rukovanje PII: spriječite tihu eksfiltraciju podataka#
Izvozi su često najzloupotrebljivaniji admin feature jer izgledaju bezazleno. U praksi jedan export može sadržavati desetke tisuća zapisa, uključujući emailove, adrese, IP-ove ili payment metadata.
Klasificirajte podatke i provodite export dozvole#
Definirajte klase podataka i provodite ih na razini upita.
| Klasa podataka | Primjeri | Postupanje |
|---|---|---|
| Public | nazivi proizvoda | bez posebnog postupanja |
| Internal | feature flagovi | ograničiti na tenant admine |
| PII | ime, email, telefon | potrebna eksplicitna dozvola |
| Sensitive PII | državni identifikatori | izbjegavati export ili tražiti approval |
| Secrets | API ključevi | nikad exportati, nikad logirati |
Export treba imati svoje permission ključeve, ne “šlepati se” na read. Primjerice:
export.customers.basicexport.customers.piiexport.audit
Arhitektura exporta: async, scopeano i sljedivo#
Koristite isti bulk job sustav za exporte:
- Kreirajte export job sa snapshotom upita.
- Generirajte datoteku u workeru.
- Spremite u object storage s kratkim TTL-om, npr. 24 sata.
- Potpišite URL-ove i logirajte preuzimanja.
Razmislite i o watermarkingu CSV exporta ubacivanjem generated_by_user_id i generated_at stupaca u interne exporte. Kupci to možda ne žele, ali je vrlo vrijedno za interne operacije.
⚠️ Upozorenje: U produkciji nemojte vraćati velike CSV datoteke iz serverless requesta. Udarit ćete u execution limite, stvoriti memory pressure i smanjiti observability. Koristite async export jobove s linkovima za preuzimanje.
Praktična pravila redakcije#
Redakcija se treba događati pri serijalizaciji, ne u UI-ju, jer exporti i API consumeri zaobilaze UI.
Primjeri:
- Maskirajte emailove u
j***@domain.comosim ako je dodijeljenoexport.*.pii. - Skraćujte IP adrese za uloge s nižim privilegijama.
- Uklonite free-text polja koja mogu sadržavati tajne koje su unijeli korisnici.
# Observability: povežite audit evente, aplikacijske logove i traceove#
Audit logovi odgovaraju na “što se dogodilo”. Operativni logovi i traceovi odgovaraju na “zašto se dogodilo i je li nešto puklo”.
Minimalni observability za admin radnje#
| Signal | Uključite | Primjer |
|---|---|---|
| Strukturirani logovi | request_id, tenant_id, actor_user_id, action | JSON logovi |
| Greške | stack trace + kontekst | Sentry |
| Traceovi | od route handlera do DB poziva | OpenTelemetry |
| Metrike | trajanja jobova, failurei | Prometheus ili managed metrike |
Pobrinite se da svaki audit event sprema request_id. Tada možete od “izdan refund” doći do točnih request logova i trace spana.
Za setup spreman za produkciju u Next.js, pogledajte Next.js logiranje i monitoring sa Sentryjem i OpenTelemetryjem.
# Sve zajedno: konkretan flow admin panela#
Evo kako se cijela arhitektura ponaša u čestom B2B scenariju: onemogućavanje više korisnika nakon sumnjive aktivnosti.
Flow#
- 1Operator filtrira korisnike po vremenu zadnje prijave i statusu.
- 2UI traži preview endpoint koji vraća broj i uzorak.
- 3Operator potvrđuje upisivanjem keyworda.
- 4API enqueuea bulk job i vraća
job_id. - 5Worker obrađuje korisnike u batchovima, piše per-batch logove i finalni audit event.
- 6Audit UI prikazuje status joba, broj zahvaćenih zapisa i eventualne neuspjehe.
Primjer: enqueueanje bulk joba#
// services/admin/bulk/enqueueBulkAction.ts
export async function enqueueBulkAction(ctx: {
tenantId: string;
actorUserId: string;
}, input: {
action: string;
ids: string[];
dryRun: boolean;
}) {
if (input.ids.length > 50000) throw new Error("TOO_MANY_IDS");
const jobId = `job_${crypto.randomUUID()}`;
// Persist bulk job record and enqueue to your queue
// Write audit event: bulk.job.created with total_count
return { jobId };
}Action-specifično ponašanje držite u dedicated worker handlerima, ne u enqueue funkciji.
# Ključne poruke#
- Modelirajte dozvole kao stabilne ključeve radnji, scopeane kroz membership po tenantu, i provodite ih na servisnoj granici, ne samo u UI-ju.
- Izgradite revizijske zapise kao append-only evente koji hvataju aktera, tenant, entitet i prije-i-poslije podatke za promjene visokog rizika, uz redakciju tajni i osjetljivog PII-ja.
- Implementirajte impersonaciju s modelom dvije sesije koji uvijek bilježi impersonatora, prikazuje trajni banner i ograničava rizične radnje dok se ne odradi step-up autentifikacija.
- Isporujte masovne radnje kao async jobove s previewjem, dry-runom, potvrdom, idempotencijom, napretkom i otkazivanjem, uz eksplicitne export dozvole za PII.
- Povežite audit evente s request logovima i traceovima preko zajedničkog
request_idkako bi incident response bio brz i temeljen na dokazima.
# Zaključak#
Robusna arhitektura Next.js administratorskog panela je konkurentska prednost u B2B SaaS-u jer smanjuje incidente, ubrzava support i čini compliance audite manje bolnima.
Ako želite drugo mišljenje o vašem RBAC modelu, audit shemi, kontrolama impersonacije ili sigurnosnim ogradama za bulk jobove, Samioda vam može pomoći dizajnirati i implementirati admin panel spreman za produkciju u Next.js. Javite se putem naše web stranice i pregledat ćemo vaš trenutni pristup te predložiti konkretan plan migracije.
FAQ
Osnivač i senior developer u Samiodi. 8+ godina iskustva u izradi React, Next.js, Flutter i n8n rješenja za klijente diljem Europe.
Više iz kategorije Web razvoj
Sve →Izrada višekoračnog čarobnjaka u Next.js App Routeru uz Server Actions + Zod (bez dodatnog API sloja)
Implementirajte produkcijski spreman Next.js višekoračni obrazac koristeći App Router Server Actions i Zod — s tri strategije stanja (kolačići, DB nacrti, URL), pristupačnim UX‑om, optimističnim prijelazima i robusnim rukovanjem greškama bez dodavanja API sloja.
Next.js App Router obrasci u 2026.: React Hook Form + Zod + Server Actions (validacija, greške, UX)
Arhitektura spremna za produkciju za Next.js App Router obrasce uz React Hook Form, Zod i Server Actions — sa zajedničkim shemama, sigurnom validacijom na serveru, async provjerama, uploadom datoteka i dosljednim rukovanjem greškama.
React aplikacije prilagođene radu offline uz TanStack Query: perzistencija, ponovni pokušaji i optimistični UI (vodič za 2026.)
Izgradite otporan offline-first UX uz TanStack Query: offline perzistencija za React Query, strategije ponovnih pokušaja i backoffa, sigurni optimistični updateovi, obrasci djelomičnog offline rada i testiranje s MSW-om.
Trebate pomoć s projektom?
Gradimo prilagođena rješenja koristeći tehnologije iz ovog članka. Senior tim, fiksne cijene.
Povezani članci
Autorizacija u Next.js App Routeru: RBAC vs ABAC uz middleware, RLS i obrasce politika
Praktičan vodič za autorizaciju u Next.js App Routeru uz RBAC i ABAC — s provjerama u middlewareu, zaštitama u server komponentama, RLS-om koji se provodi u bazi, matricom odluke i gotovim obrascima politika za copy-paste.
Next.js multitenant SaaS arhitektura: modeli tenancije, rutiranje, autentikacija i izolacija podataka (Vodič za 2026.)
Praktičan vodič za Next.js multitenant SaaS arhitekturu: modeli tenancije, tenant-aware rutiranje uz App Router i middleware, obrasci autentikacije te učvršćivanje izolacije podataka kako bi se spriječila curenja.
Next.js App Router obrasci u 2026.: React Hook Form + Zod + Server Actions (validacija, greške, UX)
Arhitektura spremna za produkciju za Next.js App Router obrasce uz React Hook Form, Zod i Server Actions — sa zajedničkim shemama, sigurnom validacijom na serveru, async provjerama, uploadom datoteka i dosljednim rukovanjem greškama.