# Što ćeš izgraditi#
Ovaj vodič ti daje praktičnu, namjerno “opinionated” Next.js + Supabase Edge Functions arhitekturu za moderni SaaS: gdje živi koji kod, kako teku podaci i kako deployati bez spoticanja o runtime limite.
Naučit ćeš kada koristiti Supabase Edge Functions u odnosu na Next.js API rute i Server Actions, uz konkretne primjere za auth hookove, webhookove i background zadatke. Ako još odlučuješ koji auth pattern koristiti, kreni s našim vodičem Next.js authentication guide pa se vrati ovdje za arhitekturu i blueprint za deployment.
# Zašto ova arhitektura radi za SaaS#
SaaS aplikacije tipično imaju tri klase prometa:
- 1Promet aplikacije od ulogiranih korisnika, često zahtijeva sesije, upite zaštićene RLS-om i UI-driven workflowe.
- 2Promet providera od trećih strana poput Stripea, Postmarka, Sentryja, GitHuba ili custom enterprise sustava putem webhookova.
- 3Automatizacijski promet iz zakazanih zadataka, retrya i back-office workflowa.
Čista podjela smanjuje kompleksnost i incidente u produkciji. U praksi:
- Next.js briljira u UI-ju, Server Actions i zahtjevima svjesnima sesije.
- Supabase briljira u Postgresu, RLS-u, realtimeu, storageu i globalno dostupnim Edge Functions.
- Supabase Edge Functions su odlične za endpointove prema van koji ne smiju ovisiti o deployu tvoje Next.js aplikacije, i za tokove koji profitiraju od blizine bazi.
🎯 Ključna poruka: Logiku vezanu uz UI stavi u Next.js, endpointove prema providerima u Supabase Edge Functions, a pristup podacima provodi kroz Postgres RLS kao zadanu zaštitnu ogradu.
# Okvir odluke: Edge Functions vs API rute vs Server Actions#
Najbrži način da srušiš ovu arhitekturu je tretirati sav server kod kao međusobno zamjenjiv. Nije zamjenjiv, pogotovo kad ubaciš runtime ograničenja, modele sesija i topologiju deploymenta.
Brza usporedna tablica#
| Use case | Najbolji default | Zašto | Konkretan primjer |
|---|---|---|---|
| UI forma koja upisuje u DB | Server Actions | Uz UI, jednostavna validacija, koristi korisničku sesiju | Kreiranje projekta, poziv člana |
| UI treba custom JSON endpoint | API route ili Route Handler | Radi s fetchom, cachingom, middlewareom, može streamati | Search endpoint, file proxy |
| Webhookovi trećih strana | Supabase Edge Function | Stabilan URL, deploy ne ovisi o Next.js, service role se može sigurno koristiti | Stripe invoice.paid webhook |
| Hookovi auth providera | Supabase Edge Function | Radi blizu Supabase autha, minimalna latencija i coupling | Provisioning nakon signupa |
| Lagani javni API blizu korisnika | Supabase Edge Function | Globalna distribucija, Deno runtime, mali overhead | Javni status endpoint |
| Dugotrajni background jobovi | Dedicated worker ili automation alat | Timeouti i retry zahtijevaju queue semantiku | Usklađivanje naplate |
| Zakazano održavanje | Edge Function sa schedulerom ili automation | Jednostavni cron-like okidači | Dnevni usage rollup |
Za runtime trade-offove i kad je Edge stvarno koristan, pročitaj naš deep dive: Next.js Edge runtime vs Node.js runtime on Vercel and Cloudflare.
Koristi Supabase Edge Functions kada#
- 1
Pozivatelj nije tvoj Next.js frontend
Webhookovi i callbackovi providera ne bi smjeli ovisiti o životnom ciklusu Next.js deploymenta. - 2
Trebaš Supabase service role key
Edge Functions su sigurno mjesto za service role operacije poput privilegiranih upisa, cross-tenant administrativnih zadataka i po potrebi zaobilaženja RLS-a. - 3
Želiš stabilan, globalno dohvatljiv endpoint
Mnogi SaaS timovi deployaju Next.js na Vercel, a svejedno trebaju provider endpointove neovisne o Vercel build rolloutima.
Preferiraj Next.js Server Actions kada#
- 1Zahtjev dolazi iz UI-ja i prirodno pripada route treeju.
- 2Trebaš čvrstu povezanost s React component stateom i server-side validacijom.
- 3RLS je dovoljan i ne trebaš service role privilegije.
Preferiraj Next.js API Routes ili Route Handlers kada#
- 1Trebaš klasičan endpoint koji konzumira više klijenata, uključujući mobilne aplikacije.
- 2Treba ti streaming, file proxying ili posebni headeri.
- 3Integriraš Node-only biblioteke koje su nespretne u Edge runtimeovima.
⚠️ Upozorenje: Nemoj graditi cijeli backend iza Supabase Edge Functions samo zato što postoje. Ako je zahtjev UI-driven i zaštićen RLS-om, Next.js Server Actions su jednostavnije, jeftinije za održavanje i lakše za end-to-end testiranje.
# Pregled referentne arhitekture#
Na visokoj razini, tvoj SaaS bi trebao izgledati ovako:
- Next.js aplikacija rješava renderiranje, akcije svjesne sesije i UI workflowe.
- Supabase Postgres je source of truth s RLS policyjima koji provode granice tenant-a.
- Supabase Edge Functions implementiraju:
- Webhookove od providera
- Hookove životnog ciklusa autentikacije
- Zakazane rollupove i cleanup jobove
- Opcionalno: n8n automatizacije za orkestraciju workflowa, retrye, notifikacije i “integration glue”.
Ako želiš širi starter blueprint, usporedi s našim komplementarnim postom: Next.js + Supabase SaaS starter architecture.
# Namjerno “opinionated” struktura foldera i modula#
Cilj je da ownership bude očit: UI kod u Next.js, privilegirani kod u Edge Functions, shared logika u packageovima koji se čisto kompajliraju za oba runtimea.
Monorepo raspored#
| Path | Svrha | Runtime ograničenja |
|---|---|---|
apps/web | Next.js app | Node.js ili Edge ovisno o ruti |
supabase/functions | Supabase Edge Functions | Deno runtime |
packages/shared | Čiste util funkcije i tipovi | Mora biti runtime-agnostic |
packages/db | SQL migracije, tipizirani upiti | Nema runtimea, build-time tooling |
packages/security | Verifikacija potpisa, helperi za hashiranje | Ako je shared, mora izbjegavati Node-only API-je |
Struktura Next.js aplikacije#
Koristi App Router i drži sve server-only module unutar jasne granice.
| Path | Odgovornost | Napomene |
|---|---|---|
apps/web/app | Rute i layouti | Server actions na razini rute drži blizu stranica |
apps/web/app/(app)/actions | UI-driven Server Actions | DB zovi direktno, ili zovi Edge Functions kad treba |
apps/web/app/api | Route Handlers za client fetch | Preferiraj za mobilne klijente i JSON endpointove |
apps/web/lib/supabase | Browser i server klijenti | Razdvoji server-only od browser-safe modula |
apps/web/lib/auth | Helperi za sesiju | Ovisi o tvom auth pristupu |
apps/web/modules/* | Domenski moduli | Svaki modul posjeduje UI, actions i upite |
Pattern domenskih modula#
Svaki domenski modul neka uključuje barem:
| Datoteka | Svrha |
|---|---|
modules/billing/service.ts | Čista domenska logika, bez framework importa |
modules/billing/actions.ts | Server Actions za UI workflowe |
modules/billing/queries.ts | Metode pristupa podacima (RLS po defaultu) |
modules/billing/validators.ts | Zod ili Valibot sheme |
modules/billing/events.ts | Nazivi eventova i tipovi payloadova |
Ovo se skalira bolje nego trpati sve u lib/ i kasnije pogađati ownership.
💡 Savjet: Ako funkciji treba Supabase service role key, ne bi smjela živjeti u
apps/web. Stavi je u Edge Function i pozivaj je potpisanim zahtjevom.
Struktura Supabase Edge Functions#
Supabase Edge Functions rade na Deno. Izbjegavaj Node-specifične dependencyje i drži svaku funkciju malom i “single-purpose”.
| Path | Svrha |
|---|---|
supabase/functions/_shared/env.ts | Parsiranje env varijabli i provjere |
supabase/functions/_shared/supabase.ts | Kreiranje service role klijenta |
supabase/functions/_shared/verify.ts | Utilityji za verifikaciju potpisa |
supabase/functions/stripe-webhook/index.ts | Stripe webhook handler |
supabase/functions/auth-post-signup/index.ts | Provisioning auth hook |
supabase/functions/daily-rollup/index.ts | Zakazana agregacija |
# Konkretni primjeri: što ide gdje#
Ovaj dio mapira česte SaaS zahtjeve na ispravno okruženje izvršavanja.
Primjer 1: Provisioning nakon signupa s Auth Hooks#
Problem: Na signup trebaš kreirati tenant workspace, seedati default podatke i dodati korisnika kao ownera.
Najbolje mjesto: Supabase Edge Function kao auth hook.
Zašto je bitno: provisioning treba privilegirane upise i mora biti konzistentan. Ako se osloniš na klijenta da kreira workspace, vidjet ćeš parcijalno stanje kad korisnici zatvore tab ili pukne mobilna mreža.
Što Edge Function radi:
- Validira payload auth eventa
- Kreira redak tenant workspacea
- Ubacuje default postavke
- Dodaje redak membershipa
// supabase/functions/auth-post-signup/index.ts
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
Deno.serve(async (req) => {
const payload = await req.json();
const userId = payload?.user?.id;
if (!userId) return new Response("Missing user id", { status: 400 });
const supabase = createClient(
Deno.env.get("SUPABASE_URL") ?? "",
Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? ""
);
const { data: workspace, error } = await supabase
.from("workspaces")
.insert({ owner_id: userId, name: "My Workspace" })
.select()
.single();
if (error) return new Response(error.message, { status: 500 });
await supabase.from("memberships").insert({
user_id: userId,
workspace_id: workspace.id,
role: "owner",
});
return new Response("ok", { status: 200 });
});Kada ovo ne raditi u Next.js: Ako se signup događa kroz Supabase Auth, a ne kroz tvoj Next.js code path, ne možeš pouzdano garantirati da će se Next.js hook izvršiti.
Primjer 2: Stripe webhookovi#
Problem: Stripe šalje evente poput invoice.paid i customer.subscription.updated. Moraš verificirati potpise i ažurirati billing stanje.
Najbolje mjesto: Supabase Edge Function.
Zašto je bitno: želiš stabilan endpoint neovisan o Next.js deploymentima i želiš ažurirati billing tablice s privilegiranim pristupom. Također želiš odgovoriti unutar provider timeouta, obično mjerljivih u sekundama, ne minutama.
Stripe verifikacija potpisa se oslanja na raw request body. U Edge Functions to kontroliraš konzistentno bez brige da će framework middleware izmijeniti payload.
// supabase/functions/stripe-webhook/index.ts
import Stripe from "https://esm.sh/stripe@15?target=deno";
Deno.serve(async (req) => {
const sig = req.headers.get("stripe-signature");
const secret = Deno.env.get("STRIPE_WEBHOOK_SECRET") ?? "";
if (!sig) return new Response("Missing signature", { status: 400 });
const raw = await req.text();
const stripe = new Stripe(Deno.env.get("STRIPE_SECRET_KEY") ?? "", {
apiVersion: "2024-06-20",
});
let event;
try {
event = stripe.webhooks.constructEvent(raw, sig, secret);
} catch (_e) {
return new Response("Invalid signature", { status: 400 });
}
// Update your DB using the service role client here.
return new Response("ok", { status: 200 });
});Primjer 3: UI-driven link za Billing Portal#
Problem: Ulogirani korisnici kliknu “Manage billing” kako bi dobili Stripe portal URL.
Najbolje mjesto: Next.js Server Action, opcionalno s pozivom Edge Functiona.
Zašto je bitno: ovo je UI-driven zahtjev vezan uz sesiju. Ako već imaš server pristup Stripeu u Next.js Node runtimeu, drži to blizu UI-ja.
Minimalni Server Action pattern:
// apps/web/app/(app)/settings/billing/actions.ts
"use server";
import { redirect } from "next/navigation";
export async function createBillingPortalAction() {
// 1) Get the user and workspace from session
// 2) Create Stripe portal session
// 3) Redirect
redirect("/settings/billing");
}Ako želiš da svi Stripe credentialsi budu izolirani iz Next.js-a, pozovi Edge Function iz Server Actiona. Potpiši zahtjev shared secretnom i validiraj ga u funkciji.
ℹ️ Napomena: Dobar default je: Stripe webhookovi u Edge Functions, UI billing akcije u Next.js. UI billing akcije prebaci u Edge samo ako želiš jedinstven “blast radius” za Stripe tajne.
Primjer 4: Background zadaci i zakazani rollupovi#
Problem: Trebaš dnevni usage rollup po workspaceu, plus cleanup istečenih pozivnica.
Najbolje mjesto: Edge Function sa schedulerom za jednostavne jobove ili automation tooling za workflowe kojima trebaju retry, grananje i notifikacije.
Tipični rollup radi:
- Agregira jučerašnje evente u tablicu
usage_daily - Označava duplikate preko unique constrainta
- Drži funkciju idempotentnom
Ako tvoj posao treba:
- retry policyje po koraku
- pozivanje više providera
- slanje Slack alerta
- human-in-the-loop odobravanja
tada je workflow alat bolji fit nego trpati sve u jednu funkciju.
# Pristup podacima: prvo RLS, service role samo kad treba#
U SaaS-u RLS nije opcionalan. To je primarna obrana od curenja tenant podataka.
Praktična pravila:
- UI čitanja i upisi trebaju ići kroz korisničku sesiju i RLS.
- Provider webhookovi često trebaju privilegirane upise jer nema korisničke sesije.
- Cross-tenant administracija pripada u Edge Functions uz service role.
Jednostavan tenant pattern#
Većina B2B SaaS aplikacija koristi tablice poput:
workspacesmembershipssrole- domenske tablice s
workspace_id
Zatim RLS osigurava da korisnici mogu pristupati samo redovima za workspaces kojima pripadaju.
Ako želiš više patterna i čestih zamki, naš starter vodič to pokriva detaljno: Next.js + Supabase SaaS starter architecture.
# Kako Next.js sigurno komunicira sa Supabase Edge Functions#
Nemoj tretirati Edge Functions kao “internal-only” samo zato što su tvoje. Pretpostavi da će svaki javni URL biti pogođen skenerima i botovima.
Preporučeni patterni:
Pattern A: Provider-signed zahtjevi#
Za webhookove provider potpisuje payload. Ti ga verificiraš pa nastavljaš. Ovo je najbolji scenarij.
Pattern B: Shared-secret HMAC za interne pozive#
Kad Next.js zove Edge Function, uključi:
- timestamp header
- signature header
- body
Zatim validiraj u funkciji i odbaci stare timestampe kako bi spriječio replay napade.
// apps/web/modules/security/sign.ts
import crypto from "crypto";
export function signPayload(secret: string, payload: string) {
return crypto.createHmac("sha256", secret).update(payload).digest("hex");
}Shared secret drži isključivo server-side. Nikad ga ne izlaži u client kodu.
⚠️ Upozorenje: Nikad ne pozivaj Edge Function koja koristi service role direktno iz browsera, čak i ako djeluje praktično. Proksiraj kroz Server Action ili API rutu i dodaj validaciju potpisa.
# Deployment razmatranja: Vercel vs Cloudflare#
Izbor deploymenta mijenja runtime defaultove i ograničenja. Najčešći produkcijski setup je:
- Next.js na Vercelu
- Supabase Edge Functions pod Supabaseom
Ali neki timovi deployaju Next.js na Cloudflare Pages ili Workers radi edge renderiranja. Evo što trebaš planirati.
Runtime i kompatibilnost#
| Tema | Vercel Node.js runtime | Vercel Edge runtime | Cloudflare Workers | Supabase Edge Functions |
|---|---|---|---|---|
| Node API-ji | Puni | Ograničeno | Ograničeno | Deno, ograničena Node kompatibilnost |
| Cold startovi | Obično niski | Vrlo niski | Vrlo niski | Niski, globalno distribuirano |
| Najbolje za | Stripe SDK, PDF-ovi, teške libove | Personalizacija, lagani API-ji | Edge-first aplikacije | Webhookovi, hookovi, privilegirani DB ops |
| Česta zamka | Veliki serverless bundleovi | Korištenje Node-only libova | Neusklađenosti Node modula | Pretpostavka o dugotrajnom radu |
Za detaljne trade-offove i migration “gotcha” situacije, vidi: Next.js Edge runtime vs Node.js runtime on Vercel and Cloudflare.
Environment varijable i tajne#
Praktične smjernice:
SUPABASE_SERVICE_ROLE_KEYstavi samo u environment za Supabase Edge Functions, ne u Next.js osim ako je apsolutno nužno.- U Next.js javne env varijable stavi samo:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY
- Tajne webhookova drži tamo gdje webhook živi. Stripe webhook secret pripada Edge Functionu koji ga prima.
Deployment workflow#
Pouzdan workflow za timove:
- 1Migracije baze deployaj prve
- 2Edge Functions deployaj druge
- 3Next.js aplikaciju deployaj treću
Time sprječavaš da Next.js zove endpointove ili tablice koje još ne postoje, i sprječavaš da webhookovi upisuju u tablice kojima nedostaju nove kolone.
Verzije i backward kompatibilnost#
Webhookovi mogu stići bilo kada, uključujući tijekom deploymenta. Tvoj webhook handler mora tolerirati stare oblike payloada u kratkom prozoru.
Dvije taktike koje smanjuju incidente:
- DB promjene radi backward kompatibilnima barem kroz jedan deploy ciklus.
- Novo ponašanje “gateaj” feature flagom spremljenim u DB, ne samo environment varijablama.
# Praktičan request flow: end-to-end primjer#
Razmotri tipičnu funkcionalnost “invite teammate”.
- Korisnik klikne Invite u UI-ju.
- Next.js Server Action validira email i ulogu.
- Server Action ubacuje invite red pod RLS-om.
- DB trigger ili zakazani job odrađuje cleanup isteka.
- Automatizacija ili Edge Function šalje email preko providera.
Gdje slati email:
- Ako email provider vraća webhooks, drži taj webhook u Edge Functions.
- Ako ti trebaju retry i grananje, guraj u automatizaciju.
- Ako je jednostavan “one-off”, možeš poslati direktno u Server Actionu s provider SDK-om, ali pazi na latenciju.
Čest kompromis:
- Server Action upiše
outbox_messagesred. - Zakazana Edge Function obrađuje outbox i označi redove kao poslane. To ti daje retry i idempotenciju bez uvođenja punog queue sustava.
# Observability i obrada grešaka#
SaaS pouzdanost se najčešće gubi u pukotinama između sustava.
Minimalni observability checklist:
- Logiraj ID-jeve webhook eventova i spremaj ih u tablicu s unique constraintom kako bi spriječio duplu obradu.
- Prati retrye i zadnju poruku greške za background zadatke.
- Emitiraj strukturirane logove iz Edge Functions s konzistentnim poljima poput
event_type,workspace_idirequest_id.
Konkretan pattern za idempotenciju:
stripe_eventstablica sevent_idunique- Handler radi: prvo insert event reda, ako je conflict onda vrati 200
Ovo sprječava double-charging i duplirani provisioning, posebno jer provideri rade retry na non-200 odgovore.
# Česte zamke u Next.js + Supabase Edge Functions arhitekturi#
- 1
Korištenje service role ključa u Next.js route handlerima
Radi dok se ne dogodi misconfig i ne izloži se. Privilegirane ključeve drži u Edge Functions. - 2
Preskakanje RLS-a jer Edge Functions mogu zaobići RLS
RLS smanjuje količinu koda koju moraš auditirati. Bypass koristi samo kad je nužno. - 3
Dugotrajni posao u Edge Functions
Edge Functions su odlične za kratkotrajni compute. Za teške jobove koristi worker ili automatizaciju. - 4
Tretiranje webhookova kao “samo još jedan API”
Webhookovi trebaju verifikaciju potpisa nad raw bodyjem, idempotenciju i sigurne failure modove. - 5
Miješanje Node-only biblioteka u Edge runtimeove
Odluku donosi po endpointu. Ako je biblioteka Node-only, stavi je u Node runtime rutu.
# Ključne poruke#
- Koristi Supabase Edge Functions za endpointove prema providerima poput webhookova i auth hookova, te za privilegirane operacije koje traže service role key.
- Koristi Next.js Server Actions za UI-driven upise i workflowe gdje RLS može provoditi autorizaciju i gdje ti koristi da je logika blizu React ruta.
- Drži “opinionated” strukturu: domenski moduli u Next.js, shared čiste util funkcije u packageovima i male single-purpose Edge Functions s
_sharedhelperima. - Deployaj redoslijedom: prvo migracije, zatim Edge Functions, pa Next.js, i drži webhook handlere idempotentnima kako bi preživjeli provider retrye.
- Biraj runtime namjerno: Node runtime za teške SDK-ove, Edge runtime za lagane low-latency endpointove, a tajne drži u okruženju gdje se koriste.
# Zaključak#
Modernom SaaS backendu ne treba ogroman bespoke API sloj. Uz ispravnu Next.js + Supabase Edge Functions arhitekturu možeš zadržati UI workflowe jednostavnima kroz Server Actions, provider integracije robusnima kroz Edge Functions i prepustiti Postgres RLS-u da po defaultu provodi tenant granice.
Ako želiš da pregledamo tvoju trenutnu arhitekturu ili da ti pomognemo implementirati produkcijski spreman Next.js i Supabase SaaS temelj, kontaktiraj Samioda i mapirat ćemo tvoje domene, runtimeove i deployment pipeline u plan koji možeš pouzdano isporučiti.
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 →Rukovanje greškama u Reactu u 2026.: Error Boundaries, ponovni pokušaji i UX obrasci koji skaliraju
Praktičan, slojeviti vodič za obrasce rukovanja greškama u Reactu u 2026.: granice grešaka na razini komponente i rute, ponovni pokušaji u TanStack Query i SWR-u te UX poruke koje skaliraju kroz timove.
Testiranje ugovora za React komponente: MSW + Storybook kao živi API mockovi
Praktičan vodič za testiranje ugovora React komponenti pomoću zajedničkih MSW handlera u Storybooku i automatiziranim testovima kako biste spriječili razilaženje mockova, nestabilan UI i regresije u CI-u.
React obrasci za tablice podataka u velikom opsegu: virtualizacija, pinanje stupaca, filteri i izvoz (TanStack Table + Virtual)
Produkcijski spremni obrasci za React tablice podataka uz TanStack Table i TanStack Virtual: arhitektura stanja, paginacija i sortiranje na strani servera, debounce filteri, pinanje stupaca, izvozi i zamke performansi.
Trebate pomoć s projektom?
Gradimo prilagođena rješenja koristeći tehnologije iz ovog članka. Senior tim, fiksne cijene.
Povezani članci
Next.js višeregionalne implementacije: obrasci za nižu latenciju na Vercelu i Cloudflareu
Praktičan vodič za Next.js višeregionalnu implementaciju u 2026.: edge rendering, regionalni SSR i obrasci lokalnosti podataka na Vercelu i Cloudflareu, uključujući upozorenja za baze podataka i kontrolnu listu za provjeru latencije.
Next.js Edge Runtime vs Node.js Runtime (Vercel i Cloudflare): Što pokretati gdje
Praktičan okvir za odlučivanje između Next.js Edge Runtime i Node.js Runtime u 2026., s konkretnim primjerima, ograničenjima i završnom matricom use-caseova.
Next.js + Supabase SaaS početna arhitektura (App Router): Auth, RLS, naplata i multi-tenancy
Production-ready nacrt za Next.js App Router + Supabase SaaS početnu arhitekturu: autentikacija, Postgres podatkovni model, RLS politike, Stripe naplata i multi-tenant dizajn organizacija s konkretnim primjerima.