Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

API routes: +server.js

Not every address should return an HTML page. A mobile app or a script on another site needs data as JSON. Such addresses — API routes — are described in SvelteKit in a +server.js file: it exports functions named after HTTP methods.

Answering GET

Create the folder src/routes/api/posts and the file +server.js in it:

// src/routes/api/posts/+server.js
import { json } from '@sveltejs/kit';
import { getPosts } from '$lib/server/posts.js';
 
export function GET() {
  return json(getPosts());
}

Open http://localhost:5173/api/posts — the browser shows the array of posts as JSON. The json function creates a Response object with the right Content-Type header. You can also return a plain new Response('text') — it is the standard object from the Fetch API.

Query parameters

The function receives an event object with the fields url, params, request. Let us add search by the ?q= string:

// src/routes/api/posts/+server.js
import { json } from '@sveltejs/kit';
import { getPosts } from '$lib/server/posts.js';
 
export function GET({ url }) {
  const q = url.searchParams.get('q') ?? '';
  const posts = getPosts().filter((post) => post.title.toLowerCase().includes(q.toLowerCase()));
  return json(posts);
}

The address /api/posts?q=runes returns only the post "What runes are".

Receiving data: POST

A POST function in the same file accepts JSON and creates a post:

// src/routes/api/posts/+server.js (add next to GET)
import { error } from '@sveltejs/kit';
import { addPost } from '$lib/server/posts.js';
 
export async function POST({ request }) {
  const { title, body } = await request.json();
 
  if (!title) {
    error(400, 'A title is required');
  }
 
  const post = { slug: title.toLowerCase().replaceAll(' ', '-'), title, body };
  addPost(post);
 
  return json(post, { status: 201 });
}

You can check it from the browser console on a page of the site:

// browser console at http://localhost:5173
const response = await fetch('/api/posts', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ title: 'Third post', body: 'Text' })
});
console.log(response.status, await response.json());

The console shows code 201 and the created post, and after a reload /blog has a new item in the list.

Page or API

+server.js and +page.svelte can live in the same folder: for a browser GET request with the Accept: text/html header SvelteKit serves the page, other requests go to +server.js. For clarity, APIs are usually kept in a separate src/routes/api folder.

Common mistake

Naming the functions in lowercase: export function get(). SvelteKit looks for an export named exactly after the method in capital letters — GET, POST, PUT, PATCH, DELETE. Otherwise the request gets a 405 error.

Thanks for reading!

Donate to the site — we work hard for you.