SvelteKit tidak hanya dipakai untuk membuat antarmuka web, tetapi juga bisa menangani kebutuhan backend sederhana melalui endpoint API. Dengan file +server.js, Anda dapat membuat route yang merespons request HTTP seperti GET, POST, PUT, atau DELETE tanpa perlu framework backend terpisah untuk kasus dasar.

Pada artikel ini, kita akan langsung membuat endpoint API /api/todos yang mendukung GET dan POST. Anda juga akan melihat cara mengirim response JSON, membaca body request, serta memanggil endpoint tersebut dari halaman SvelteKit. Contoh yang digunakan sengaja sederhana supaya bisa langsung dicoba, tetapi strukturnya tetap relevan untuk proyek nyata.

Struktur endpoint API di SvelteKit

Di SvelteKit, endpoint API dibuat berdasarkan struktur folder di dalam direktori src/routes. Jika Anda ingin membuat endpoint /api/todos, maka file yang dibutuhkan adalah:

src/routes/api/todos/+server.js

Nama file +server.js menandakan bahwa route tersebut menangani request di sisi server. Anda bisa mengekspor fungsi sesuai HTTP method yang ingin didukung, misalnya GET dan POST.

Contoh paling dasar:

export async function GET() {
  return new Response('Hello from API');
}

Namun, untuk API modern, biasanya Anda ingin mengembalikan JSON. SvelteKit menyediakan helper json dari @sveltejs/kit agar response lebih rapi dan header Content-Type otomatis diset ke application/json.

Membuat endpoint /api/todos dengan GET dan POST

Kita mulai dari contoh endpoint sederhana yang menyimpan data todo di array dalam memori. Pendekatan ini cocok untuk belajar dan eksperimen lokal. Untuk produksi, tentu data sebaiknya disimpan ke database karena array di memori akan hilang saat server restart.

File: src/routes/api/todos/+server.js

import { json } from '@sveltejs/kit';

const todos = [
  { id: 1, text: 'Belajar SvelteKit API', done: false },
  { id: 2, text: 'Membuat endpoint +server.js', done: true }
];

export async function GET() {
  return json({
    success: true,
    data: todos
  });
}

export async function POST({ request }) {
  const body = await request.json();
  const text = body.text?.trim();

  if (!text) {
    return json(
      {
        success: false,
        message: 'Field text wajib diisi'
      },
      { status: 400 }
    );
  }

  const newTodo = {
    id: todos.length + 1,
    text,
    done: false
  };

  todos.push(newTodo);

  return json(
    {
      success: true,
      message: 'Todo berhasil ditambahkan',
      data: newTodo
    },
    { status: 201 }
  );
}

Ada beberapa hal penting pada kode di atas:

  • GET mengembalikan daftar todo dalam format JSON.
  • POST membaca body request dengan await request.json().
  • Validasi sederhana dilakukan agar field text tidak kosong.
  • Status code 400 dipakai untuk request tidak valid, dan 201 untuk data baru yang berhasil dibuat.

Pola ini penting karena API yang baik tidak hanya mengembalikan data, tetapi juga memberikan status HTTP yang sesuai. Ini memudahkan debugging dan integrasi dari sisi frontend.

Menjalankan dan menguji endpoint

Setelah file endpoint dibuat, jalankan aplikasi SvelteKit seperti biasa:

npm run dev

Jika server berjalan di alamat default, endpoint Anda bisa diakses di:

http://localhost:5173/api/todos

Uji GET dari browser atau curl

Untuk request GET, Anda bisa membuka URL langsung di browser atau memakai curl:

curl http://localhost:5173/api/todos

Response yang diharapkan kira-kira seperti ini:

{
  "success": true,
  "data": [
    { "id": 1, "text": "Belajar SvelteKit API", "done": false },
    { "id": 2, "text": "Membuat endpoint +server.js", "done": true }
  ]
}

Uji POST dengan curl

Untuk mengirim data baru:

curl -X POST http://localhost:5173/api/todos \
  -H "Content-Type: application/json" \
  -d '{"text":"Menulis dokumentasi endpoint"}'

Jika berhasil, response akan berisi todo yang baru dibuat:

{
  "success": true,
  "message": "Todo berhasil ditambahkan",
  "data": {
    "id": 3,
    "text": "Menulis dokumentasi endpoint",
    "done": false
  }
}

Jika Anda mendapat error saat memanggil request.json(), periksa apakah header Content-Type: application/json sudah dikirim dan body request memang valid JSON.

Memanggil endpoint dari halaman SvelteKit

Setelah endpoint tersedia, langkah berikutnya adalah menggunakannya dari halaman SvelteKit. Di sini kita akan membuat halaman sederhana yang menampilkan daftar todo dan form untuk menambah todo baru.

File: src/routes/todos/+page.svelte

<script>
  import { onMount } from 'svelte';

  let todos = [];
  let text = '';
  let loading = false;
  let error = '';

  async function loadTodos() {
    error = '';

    try {
      const res = await fetch('/api/todos');
      const result = await res.json();

      if (!res.ok) {
        throw new Error(result.message || 'Gagal memuat todos');
      }

      todos = result.data;
    } catch (err) {
      error = err.message;
    }
  }

  async function addTodo() {
    error = '';

    if (!text.trim()) {
      error = 'Input todo tidak boleh kosong';
      return;
    }

    loading = true;

    try {
      const res = await fetch('/api/todos', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ text })
      });

      const result = await res.json();

      if (!res.ok) {
        throw new Error(result.message || 'Gagal menambahkan todo');
      }

      todos = [...todos, result.data];
      text = '';
    } catch (err) {
      error = err.message;
    } finally {
      loading = false;
    }
  }

  onMount(loadTodos);
</script>

<h1>Daftar Todo</h1>

<div>
  <input bind:value={text} placeholder="Tulis todo baru" />
  <button on:click={addTodo} disabled={loading}>
    {#if loading}
      Menyimpan...
    {:else}
      Tambah
    {/if}
  </button>
</div>

{#if error}
  <p style="color: red;">{error}</p>
{/if}

<ul>
  {#each todos as todo}
    <li>{todo.text} - {todo.done ? 'Selesai' : 'Belum'}</li>
  {/each}
</ul>

Pada contoh ini:

  • loadTodos() mengambil data dari endpoint GET /api/todos.
  • addTodo() mengirim data baru ke endpoint POST /api/todos.
  • Kita selalu memeriksa res.ok agar error dari server tidak dianggap sukses.
  • UI diperbarui langsung setelah data berhasil ditambahkan.

Ini adalah pola yang umum dipakai dalam aplikasi SvelteKit: frontend memanggil endpoint internal menggunakan fetch('/api/...'), lalu server mengembalikan JSON untuk dirender di halaman.

Kenapa pendekatan ini bekerja dengan baik

Keuntungan utama memakai +server.js adalah backend dan frontend berada dalam satu proyek dengan sistem routing yang konsisten. Anda tidak perlu menyiapkan server Express terpisah hanya untuk endpoint dasar seperti CRUD sederhana, validasi ringan, atau integrasi dengan layanan lain.

Selain itu, pendekatan ini memudahkan beberapa hal:

  • Struktur route jelas: path URL langsung mengikuti struktur folder.
  • Lebih sedikit boilerplate: cukup ekspor fungsi GET, POST, dan seterusnya.
  • Mudah dipanggil dari halaman internal: gunakan path relatif seperti /api/todos.
  • Cocok untuk full-stack sederhana: satu codebase untuk UI dan API.

Namun, penting juga memahami batasannya. Jika data Anda disimpan dalam variabel array seperti contoh di atas, data tersebut tidak persisten. Pada mode development mungkin terlihat normal, tetapi saat aplikasi restart atau dijalankan di lingkungan serverless, isi array bisa hilang atau tidak konsisten antar instance.

Kesalahan umum dan tips debugging

1. Salah menaruh file +server.js

Endpoint /api/todos harus berada di:

src/routes/api/todos/+server.js

Jika folder atau nama file salah, route tidak akan ditemukan dan biasanya menghasilkan 404.

2. Lupa memakai request.json()

Pada handler POST, body request tidak otomatis tersedia sebagai object JavaScript. Anda harus membacanya secara eksplisit:

const body = await request.json();

Kalau body bukan JSON valid, pemanggilan ini bisa melempar error.

3. Tidak mengirim Content-Type yang sesuai

Saat mengirim POST dari frontend atau curl, pastikan header berikut ada:

Content-Type: application/json

Tanpa header ini, parsing body sering bermasalah atau perilakunya tidak sesuai harapan.

4. Tidak mengembalikan status code yang benar

Jangan selalu mengembalikan status 200. Untuk input tidak valid, gunakan 400. Untuk data baru, gunakan 201. Ini membantu frontend mengambil keputusan dengan lebih akurat.

5. Mengandalkan data in-memory untuk produksi

Contoh artikel ini memakai array supaya sederhana. Untuk aplikasi nyata, pindahkan penyimpanan ke database seperti PostgreSQL, MySQL, SQLite, atau layanan backend lain. Endpoint +server.js tetap bisa dipakai, hanya sumber datanya yang berubah.

Versi yang lebih rapi untuk pengembangan lanjutan

Setelah endpoint dasar berjalan, Anda bisa mengembangkan pola ini menjadi lebih stabil dengan beberapa peningkatan berikut:

  • Memindahkan logika data ke file terpisah, misalnya src/lib/server/todos.js.
  • Menambahkan validasi yang lebih ketat untuk body request.
  • Menambahkan handler PUT atau DELETE untuk melengkapi operasi CRUD.
  • Menambahkan autentikasi jika endpoint tidak boleh diakses publik.
  • Menghubungkan endpoint ke database agar data persisten.

Contoh artikel ini sengaja fokus pada dasar yang paling sering dibutuhkan: menerima request, membaca body, dan mengembalikan JSON dengan benar. Jika fondasi ini sudah paham, pengembangan ke level berikutnya biasanya jauh lebih mudah.

Penutup

Membuat API endpoint di SvelteKit dengan +server.js cukup langsung: buat file pada route yang sesuai, ekspor handler HTTP seperti GET dan POST, lalu kembalikan response JSON menggunakan helper json(). Untuk request yang membawa data, baca body melalui request.json() dan validasi isinya sebelum diproses.

Dengan endpoint /api/todos yang sudah kita buat, Anda sekarang punya pola dasar yang bisa dipakai untuk banyak kasus lain seperti formulir, pencarian, integrasi database, atau endpoint internal aplikasi. Jika ingin melangkah lebih jauh, tahap berikutnya yang paling masuk akal adalah menambahkan penyimpanan database dan operasi update/hapus agar API menjadi CRUD yang lengkap.