Bird
Raised Fist0
Svelteframework~15 mins

Server routes (+server.js) in Svelte - Deep Dive

Choose your learning style10 modes available
Overview - Server routes (+server.js)
What is it?
Server routes in SvelteKit are special files that handle requests from the browser or other clients. They let you write code that runs on the server to respond with data, perform actions, or control navigation. The +server.js file is where you define these routes using functions for different HTTP methods like GET or POST. This helps separate server logic from the user interface.
Why it matters
Without server routes, your app would only run in the browser and could not securely fetch or send data to a database or external services. Server routes let you build dynamic, interactive apps that can handle user input, save data, or protect sensitive operations. They make your app more powerful and real-world ready by bridging the client and server safely.
Where it fits
Before learning server routes, you should understand basic Svelte components and how client-side routing works. After mastering server routes, you can explore advanced topics like server actions, API integration, and authentication in SvelteKit.
Mental Model
Core Idea
Server routes are like waiters in a restaurant who listen to your order (request), prepare the food (process data), and bring it back to you (response).
Think of it like...
Imagine a restaurant kitchen where customers place orders through waiters. The waiter takes the order, the kitchen cooks the meal, and the waiter delivers it back. Server routes act as the waiter, handling requests and responses between the client and server.
┌───────────────┐       Request       ┌───────────────┐
│   Client      │ ──────────────────▶ │  +server.js   │
└───────────────┘                    │  (Server)     │
                                    └───────────────┘
                                          │
                                          │ Process request
                                          ▼
                                    ┌───────────────┐
                                    │  Response     │
                                    └───────────────┘
                                          │
                                          ▼
                                    ┌───────────────┐
                                    │   Client      │
                                    └───────────────┘
Build-Up - 7 Steps
1
FoundationWhat Are Server Routes in SvelteKit
🤔
Concept: Introduce the idea of server routes as files that handle HTTP requests on the server side.
In SvelteKit, server routes are special files named +server.js placed inside folders that match URL paths. Each file can export functions like GET, POST, PUT, DELETE to handle requests. When a client visits a URL or sends data, SvelteKit runs the matching function in +server.js to respond.
Result
You understand that +server.js files are the server's way to listen and respond to client requests.
Understanding that server routes are just files with functions helps you see how SvelteKit connects URLs to server logic simply and clearly.
2
FoundationBasic GET Handler in +server.js
🤔
Concept: Learn how to write a simple GET function to respond with data.
Create a +server.js file with an exported GET function. This function receives a request and returns a response object with status and body. For example: export function GET() { return new Response(JSON.stringify({ message: 'Hello from server!' }), { headers: { 'Content-Type': 'application/json' } }); } This sends JSON data back to the client.
Result
Visiting the route URL returns the JSON message from the server.
Knowing how to send a response with status and headers is the foundation for all server route interactions.
3
IntermediateHandling POST Requests with +server.js
🤔Before reading on: do you think POST handlers receive data the same way as GET handlers? Commit to your answer.
Concept: Learn how to accept and process data sent by the client using POST method.
In +server.js, export a POST function that reads the request body. For example: export async function POST({ request }) { const data = await request.json(); // Process data here return new Response(JSON.stringify({ received: data }), { headers: { 'Content-Type': 'application/json' } }); } This lets the server receive JSON data from the client and respond accordingly.
Result
The server echoes back the data sent by the client in the POST request.
Understanding how to read request bodies unlocks the ability to build forms, APIs, and interactive features.
4
IntermediateUsing Request Parameters and URL Matching
🤔Before reading on: do you think server routes can access parts of the URL like IDs or names? Commit to your answer.
Concept: Learn how to capture dynamic parts of the URL in server routes using folder and file naming conventions.
SvelteKit lets you create dynamic routes by naming folders or files with square brackets. For example, a folder named [id] matches any value in that part of the URL. Inside +server.js, you can access this parameter: export function GET({ params }) { return new Response(`ID is ${params.id}`); } Visiting /123 will respond with 'ID is 123'.
Result
Server routes can respond differently based on URL parameters.
Knowing how to use URL parameters makes your server routes flexible and able to handle many similar requests with one file.
5
IntermediateOrganizing Multiple HTTP Methods in +server.js
🤔
Concept: Learn how to handle different HTTP methods like GET, POST, PUT, DELETE in one +server.js file.
You can export multiple functions in +server.js, each named after an HTTP method. For example: export function GET() { return new Response('GET response'); } export function POST() { return new Response('POST response'); } SvelteKit calls the right function based on the request method, letting you handle many actions in one place.
Result
Your server route can respond differently to GET and POST requests at the same URL.
Understanding this pattern helps you build RESTful APIs and organize server logic cleanly.
6
AdvancedUsing Request Event for Advanced Control
🤔Before reading on: do you think the server route functions can access cookies, headers, and locals? Commit to your answer.
Concept: Learn about the request event object that gives access to request details, cookies, headers, and server-side locals.
Server route functions receive a single argument called event. It contains useful info: - event.request: the full request object - event.params: URL parameters - event.cookies: read and set cookies - event.locals: data shared during the request lifecycle Example: export function GET(event) { const user = event.locals.user; return new Response(`Hello ${user}`); } This lets you build personalized and secure responses.
Result
You can access and manipulate request details beyond just the body and URL.
Knowing about the event object unlocks powerful server-side features like authentication and session handling.
7
ExpertServer Routes and Edge vs Node Environments
🤔Before reading on: do you think server routes run the same way everywhere? Commit to your answer.
Concept: Understand how server routes behave differently depending on the deployment environment, like edge functions or Node.js servers.
SvelteKit can deploy server routes to different environments: - Node.js servers support full Node APIs and long-running processes. - Edge functions run closer to users with limited APIs and faster cold starts. This affects what you can do inside +server.js. For example, some Node modules may not work on the edge. You must write routes compatible with your target environment.
Result
You write server routes that work efficiently and correctly depending on where they run.
Understanding environment differences prevents bugs and performance issues in production.
Under the Hood
When a client sends a request to a SvelteKit app, the framework matches the URL to a folder with a +server.js file. It then calls the exported function matching the HTTP method (GET, POST, etc.) inside that file. This function receives an event object with request details. The function returns a Response object, which SvelteKit sends back to the client. This process happens on the server, separate from the client-side code, enabling secure and efficient data handling.
Why designed this way?
SvelteKit uses file-based routing to keep server logic simple and intuitive, matching URLs to files like pages. Exporting functions for HTTP methods follows web standards, making it easy for developers to write familiar code. This design avoids complex configuration and keeps server and client code organized. Alternatives like centralized routing tables were rejected for their complexity and less clear structure.
Client Request
    │
    ▼
┌───────────────┐
│ URL matches   │
│ folder with   │
│ +server.js    │
└───────────────┘
    │
    ▼
┌───────────────┐
│ Call exported │
│ function for  │
│ HTTP method   │
└───────────────┘
    │
    ▼
┌───────────────┐
│ Function      │
│ processes     │
│ request       │
└───────────────┘
    │
    ▼
┌───────────────┐
│ Returns       │
│ Response      │
└───────────────┘
    │
    ▼
Client receives response
Myth Busters - 4 Common Misconceptions
Quick: Do server routes run in the browser or on the server? Commit to your answer.
Common Belief:Server routes run in the browser just like Svelte components.
Tap to reveal reality
Reality:Server routes run only on the server, never in the browser.
Why it matters:Thinking server routes run in the browser leads to confusion about security and data handling, causing bugs and unsafe code.
Quick: Can you use client-only APIs like localStorage inside +server.js? Commit to yes or no.
Common Belief:You can use browser APIs like localStorage inside server routes.
Tap to reveal reality
Reality:Server routes run on the server where browser APIs do not exist.
Why it matters:Using browser-only APIs in server routes causes runtime errors and breaks your app.
Quick: Do you think you must write separate files for each HTTP method? Commit to yes or no.
Common Belief:Each HTTP method requires a separate +server.js file.
Tap to reveal reality
Reality:You can export multiple HTTP method functions in the same +server.js file.
Why it matters:Misunderstanding this leads to unnecessary file clutter and harder maintenance.
Quick: Do you think server routes always have access to full Node.js APIs? Commit to your answer.
Common Belief:Server routes always have full Node.js capabilities regardless of deployment.
Tap to reveal reality
Reality:Server routes running on edge environments have limited APIs compared to Node.js servers.
Why it matters:Ignoring environment limits causes deployment failures and unexpected bugs.
Expert Zone
1
Server routes can share data during a request lifecycle using event.locals, enabling complex workflows like authentication without global state.
2
The Response object returned by server routes supports streaming, allowing efficient handling of large data or progressive responses.
3
You can set cookies and headers directly in server routes to control client behavior, caching, and security policies.
When NOT to use
Avoid using server routes for purely client-side UI updates or animations; use Svelte components instead. For heavy data processing or long-running tasks, consider background jobs or external APIs rather than blocking server routes.
Production Patterns
In production, server routes often serve as API endpoints for frontend components, handle form submissions securely, and implement authentication flows. Developers use middleware-like hooks to add logging, error handling, and security checks around server routes.
Connections
REST API Design
Server routes implement RESTful endpoints by mapping HTTP methods to actions.
Understanding server routes helps grasp how REST APIs work, enabling you to build scalable web services.
HTTP Protocol
Server routes respond to HTTP requests using standard methods and status codes.
Knowing HTTP basics clarifies how server routes communicate and handle errors effectively.
Restaurant Order System
Both involve receiving requests, processing them, and delivering responses.
This cross-domain connection shows how asynchronous request handling is a common pattern in many systems.
Common Pitfalls
#1Trying to use browser-only APIs like localStorage inside +server.js.
Wrong approach:export function GET() { const token = localStorage.getItem('token'); return new Response(token); }
Correct approach:export function GET() { // localStorage not available on server return new Response('No localStorage on server'); }
Root cause:Confusing client-side environment with server-side environment.
#2Not returning a Response object from server route functions.
Wrong approach:export function GET() { return { message: 'Hello' }; }
Correct approach:export function GET() { return new Response(JSON.stringify({ message: 'Hello' }), { headers: { 'Content-Type': 'application/json' } }); }
Root cause:Misunderstanding that server routes must return a Response instance, not plain objects.
#3Creating separate +server.js files for each HTTP method unnecessarily.
Wrong approach:Folder structure: /myroute/GET/+server.js /myroute/POST/+server.js
Correct approach:Folder structure: /myroute/+server.js Inside +server.js: export function GET() { ... } export function POST() { ... }
Root cause:Not knowing that multiple HTTP methods can be handled in one file.
Key Takeaways
Server routes in SvelteKit let you handle HTTP requests on the server by exporting functions named after HTTP methods inside +server.js files.
These routes run only on the server, separate from client-side code, enabling secure data handling and dynamic responses.
You can access request details like URL parameters, headers, cookies, and body through the event object passed to route functions.
Server routes can handle multiple HTTP methods in one file, making it easy to organize RESTful APIs.
Understanding deployment environments like Node.js and edge functions is crucial to writing compatible and efficient server routes.

Practice

(1/5)
1. What is the main purpose of a +server.js file in a SvelteKit project?
easy
A. To style the application using CSS
B. To define client-side UI components
C. To manage database connections directly in the browser
D. To handle server-side HTTP requests like GET or POST

Solution

  1. Step 1: Understand the role of +server.js

    This file is used to write server-side code that responds to HTTP requests.
  2. Step 2: Differentiate client and server roles

    Client-side UI components and styling are handled elsewhere, not in +server.js.
  3. Final Answer:

    To handle server-side HTTP requests like GET or POST -> Option D
  4. Quick Check:

    Server routes = handle HTTP requests [OK]
Hint: Remember: +server.js is for server code only [OK]
Common Mistakes:
  • Confusing +server.js with client components
  • Thinking CSS or styling goes in +server.js
  • Assuming database code runs in the browser
2. Which of the following is the correct way to export a GET handler in a +server.js file?
easy
A. export async function get() { return { body: { message: 'Hello' } }; }
B. export function get() { return { body: { message: 'Hello' } }; }
C. export async function GET() { return { body: { message: 'Hello' } }; }
D. export async get() { return { body: { message: 'Hello' } }; }

Solution

  1. Step 1: Recall SvelteKit server route syntax

    Handlers must be exported as async functions named in uppercase HTTP methods, e.g., GET.
  2. Step 2: Check syntax correctness

    Only export async function GET() { return { body: { message: 'Hello' } }; } uses export async function GET() which is correct syntax.
  3. Final Answer:

    export async function GET() { return { body: { message: 'Hello' } }; } -> Option C
  4. Quick Check:

    Use uppercase HTTP method names for exports [OK]
Hint: Export async functions named uppercase HTTP methods [OK]
Common Mistakes:
  • Using lowercase method names like 'get' instead of 'GET'
  • Omitting async keyword for async handlers
  • Incorrect export syntax without 'function'
3. Given this +server.js code, what will be the JSON response body when a GET request is made?
export async function GET() {
  return {
    status: 200,
    body: { success: true, data: [1, 2, 3] }
  };
}
medium
A. {"success":true,"data":[1,2,3]}
B. {"status":200,"body":{"success":true,"data":[1,2,3]}}
C. [1, 2, 3]
D. An error because body must be a string

Solution

  1. Step 1: Understand the returned object structure

    The handler returns an object with status and body. The body is the JSON data sent to the client.
  2. Step 2: Identify the actual response body content

    The client receives the body content serialized as JSON: {"success":true,"data":[1,2,3]}.
  3. Final Answer:

    {"success":true,"data":[1,2,3]} -> Option A
  4. Quick Check:

    Response body = JSON data object [OK]
Hint: Response body is the JSON object inside returned body [OK]
Common Mistakes:
  • Confusing the whole return object with the response body
  • Expecting raw arrays or strings instead of JSON objects
  • Thinking status code is part of JSON body
4. What is wrong with this +server.js POST handler?
export async function POST(request) {
  const data = await request.json();
  return { status: 201, body: { received: data } };
}
medium
A. Nothing is wrong; this is correct syntax
B. The request parameter is missing the 'event' wrapper
C. The handler must return a Response object, not a plain object
D. The function should be named post in lowercase

Solution

  1. Step 1: Check handler parameter

    The POST handler receives an event object containing request. The code names it request but calls request.json(), which fails because the event object has no json() method; use event.request.json() or destructure { request }.
  2. Step 2: Identify the correct fix

    The parameter needs destructuring like POST({ request }) or renaming to event with event.request. The request parameter is missing the 'event' wrapper correctly identifies the missing 'event' wrapper.
  3. Final Answer:

    The request parameter is missing the 'event' wrapper -> Option B
  4. Quick Check:

    Destructure { request } from event [OK]
Hint: Destructure { request } from event parameter [OK]
Common Mistakes:
  • Using lowercase method names instead of uppercase
  • Expecting a Response object instead of plain object
  • Misunderstanding request parameter structure
5. You want to create a +server.js route that accepts a POST request with JSON data, validates that the JSON has a non-empty name string, and returns a 400 error if invalid. Which code snippet correctly implements this?
hard
A. export async function POST({ request }) { const data = await request.json(); if (!data.name || typeof data.name !== 'string' || data.name.trim() === '') { return { status: 400, body: { error: 'Name is required' } }; } return { status: 200, body: { message: `Hello, ${data.name}` } }; }
B. export async function POST(request) { const data = await request.json(); if (!data.name) { throw new Error('Name missing'); } return new Response(JSON.stringify({ message: `Hello, ${data.name}` }), { status: 200 }); }
C. export async function POST({ request }) { const data = await request.json(); if (data.name === '') { return { status: 500, body: { error: 'Empty name' } }; } return { status: 200, body: { message: `Hi ${data.name}` } }; }
D. export async function POST({ request }) { const data = await request.json(); if (!data.name) { return { status: 404, body: { error: 'Name not found' } }; } return { status: 200, body: { message: `Welcome, ${data.name}` } }; }

Solution

  1. Step 1: Validate the 'name' field properly

    The correct snippet destructures { request }, checks if name exists, is a string, and non-empty after trim(), returning 400 if invalid.
  2. Step 2: Confirm status codes and completeness

    It uses 400 for validation errors and 200 for success; others use wrong parameters, incomplete checks, wrong statuses (500/404), or throw errors.
  3. Final Answer:

    The snippet with full validation (exists, string, trimmed non-empty) and 400 status -> Option A
  4. Quick Check:

    Validate input and return 400 if invalid [OK]
Hint: Check for empty or missing fields, return 400 for bad input [OK]
Common Mistakes:
  • Returning wrong status codes like 404 or 500 for validation errors
  • Throwing errors instead of returning HTTP responses
  • Not trimming strings before checking emptiness
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard