Episode ini membahas sisi server SvelteKit: mendefinisikan endpoint dengan +server.js, mengonsumsi dan mengekspos API internal, menyusun authentication middleware untuk protected endpoints, serta integrasi database dengan ORM. Kalian akan membangun back-end yang kohesif.

SvelteKit adalah framework full-stack: selain halaman, ia juga bisa menjadi back-end API. Episode 10 membahas file +server.js yang mendefinisikan endpoint HTTP, cara aplikasi mengonsumsi API internalnya sendiri, dan bagaimana melindungi endpoint yang sensitif.
Satu aplikasi, satu bahasa, satu deployment — inilah keunggulan utama menjadikan SvelteKit sebagai back-end. Kalian tidak perlu proyek terpisah untuk API; endpoint hidup di dalam struktur route yang sama dengan halaman.
Kita akan membangun endpoint yang bersih, mengamankannya dengan middleware, dan menghubungkannya ke database. Di akhir episode, kalian punya back-end fungsional yang terintegrasi erat dengan front-end.
File +server.js di dalam folder route mengekspor handler per method HTTP: GET, POST, PUT, PATCH, DELETE, dan OPTIONS. Tidak ada komponen yang dirender — hasilnya murni respons HTTP.
import { json } from "@sveltejs/kit";
export const GET = async ({ url }) => {
const limit = Number(url.searchParams.get("limit") ?? 10);
const daftar = await ambilData({ limit });
return json(daftar);
};
export const POST = async ({ request }) => {
const body = await request.json();
const baru = await simpanData(body);
return json(baru, { status: 201 });
};Helper json dari @sveltejs/kit membuat respons dengan Content-Type yang benar dan serialisasi otomatis. Handler menerima event yang sama seperti load function, sehingga params, url, request, cookies, dan locals semuanya tersedia.
Folder src/routes/api adalah konvensi tempat menaruh endpoint API, meski bukan keharusan — struktur sepenuhnya mengikuti routing. Endpoint bisa memakai dynamic segment, misalnya /api/artikel/[id] dengan file +server.js di folder [id], sehingga handler dapat membaca params.id.
SvelteKit mengoptimalkan request antar route: saat load function memanggil endpoint internal dengan event.fetch, request tidak melakukan perjalanan jaringan penuh — SvelteKit meneruskannya langsung dalam proses yang sama.
export const load = async ({ fetch }) => {
const res = await fetch("/api/artikel?limit=5");
const artikel = await res.json();
return { artikel };
};Karena berjalan di server, event.fetch mengikuti cookie dan header request asli. Ini berarti endpoint yang membaca session tetap bekerja saat dipanggil dari load function, tanpa perlu membangun header ulang secara manual.
Pola "load function memanggil +server.js" memberi pemisahan yang jelas antara data API dan tampilan. Namun jika keduanya berada di aplikasi yang sama, pertimbangkan untuk memanggil fungsi bersama langsung dari src/lib/server — lebih cepat karena menghindari lapisan HTTP sama sekali. Pilih +server.js ketika endpoint memang dikonsumsi pihak luar atau aplikasi lain.
Hook handle berjalan untuk setiap request sebelum route diproses. Ini adalah tempat untuk menaruh authentication middleware: baca cookie session, verifikasi, dan simpan hasilnya ke event.locals.
export const handle = async ({ event, resolve }) => {
const session = event.cookies.get("session");
if (session) {
event.locals.user = await verifikasiSession(session);
}
return await resolve(event);
};Dengan pola ini, setiap handler di aplikasi bisa mengakses event.locals.user tanpa mengulangi logika verifikasi. Inisialisasi event.locals yang aman dilakukan dengan mendeklarasikan tipe di src/app.d.ts.
Endpoint yang sensitif memeriksa locals di awal handler:
export const GET = async ({ locals }) => {
if (!locals.user) {
throw error(401, "Autentikasi diperlukan");
}
return json({ user: locals.user });
};Throw error(401, ...) menghentikan handler dan mengembalikan status yang sesuai. Untuk kontrol akses yang lebih detail, bandingkan peran pengguna dengan peran yang diizinkan, dan gunakan satu helper agar kebijakan tidak tersebar di banyak file.
Untuk aplikasi dengan data terstruktur dan relasi, ORM seperti Prisma atau Drizzle menyediakan tipe aman dan migrasi terkelola. Koneksi database disimpan di src/lib/server dan hanya diimpor dari kode server.
import prisma from "$lib/server/prisma";
export const load = async () => {
const artikel = await prisma.artikel.findMany({
orderBy: { createdAt: "desc" },
take: 10
});
return { artikel };
};Pastikan file skema Prisma dan migrasi di-versioning. Jalankan npx prisma migrate dev untuk development dan npx prisma migrate deploy saat deploy. Karena kode server berjalan sekali per request, hindari membuat koneksi baru tiap kali — pakai pola singleton sehingga satu instance Prisma dipakai bersama seluruh aplikasi.
Inti yang harus dibawa pulang:
+server.js mendefinisikan endpoint per method HTTP dan merespons lewat json atau Response.event.fetch untuk memanggil endpoint internal, dengan cookie dan header yang diteruskan.handle adalah tempat menaruh authentication middleware; hasilnya disimpan di event.locals.locals dan melempar error(401) saat tidak terautentikasi.src/lib/server agar tidak pernah bocor ke client.Di episode 11 selanjutnya kita memperdalam interaksi pengguna: forms, validation, & interaction. Kalian akan menyusun alur submit form dan validation, validasi di sisi server dengan umpan balik UI, progressive enhancement dengan no-JS fallback, serta file upload dan multipart form handling.