---
title: SvelteKit
description: Mount the Files gateway in a SvelteKit +server.ts endpoint. createRouteHandler returns { GET, POST, PUT } over the Web Request, on Node and edge alike.
related:
  - /guides/sveltekit-file-upload
---

`files-sdk/sveltekit` mounts a [`createFilesRouter`](/docs/ui/server/gateway) in a SvelteKit `+server.ts` endpoint. SvelteKit hands each route a Web `Request` on `event.request` and wants named per-method exports, so — like [`files-sdk/next`](/docs/ui/server/next) — `createRouteHandler` returns `{ GET, POST, PUT }`: `GET` serves downloads, `POST` the JSON verbs, and `PUT` the upload byte path. The handlers are Web-native, so the route runs on the **Node and edge adapters alike**.

```ts title="src/routes/api/files/+server.ts" lineNumbers
import { createFiles } from "files-sdk";
import { r2 } from "files-sdk/r2";
import { createFilesRouter } from "files-sdk/api";
import { createRouteHandler } from "files-sdk/sveltekit";

const router = createFilesRouter({
  files: createFiles({ adapter: r2({ bucket: "uploads" }) }),
  allowedOrigins: ["https://app.example.com"],
  authorize: async ({ req }) => {
    /* throw to deny, or return a per-user constraint — see /ui/server/authorization */
  },
});

export const { GET, POST, PUT } = createRouteHandler(router);
```

:::note
This is the **server** binding — distinct from the [`files-sdk/svelte`](/docs/ui/client/svelte) client store that drives the upload UI. One `+server.ts` backs every client binding; the gateway dispatches on the method internally (GET = download, POST = the JSON verbs, PUT = upload).
:::

## SvelteKit settings that reach the gateway

SvelteKit runs a few checks of its own before a request gets to the gateway. They apply to SvelteKit 2 and 3 alike.

- **CSRF.** SvelteKit returns 403 for a cross-origin `POST` or `PUT` whose `Content-Type` looks like a form submission (`text/plain`, `multipart/form-data`, or `application/x-www-form-urlencoded`). SvelteKit 3 also rejects one with no `Content-Type`. Explicit-key uploads send the file's own type, so a cross-origin upload of a `.txt` file is rejected before `authorize` ever runs. If the gateway serves other origins, list them in `csrf.trustedOrigins` as well as in `allowedOrigins`. That goes in `svelte.config.js` on SvelteKit 2, and in the `sveltekit()` plugin options in `vite.config.js` on SvelteKit 3.
- **Request body size.** `@sveltejs/adapter-node` caps request bodies at 512 KB unless you raise `BODY_SIZE_LIMIT`. Explicit-key `PUT` uploads stream through this route, so raise the limit to cover your largest file. Keyless uploads go straight to the provider through a signed URL and never hit the limit.
- **Disconnects.** On `@sveltejs/adapter-node` 6 (SvelteKit 3), `request.signal` aborts when the client disconnects. The gateway passes that signal to every `Files` call, so an abandoned upload or proxied download stops instead of running to completion.

See the [gateway options](/docs/ui/server/gateway) for the full configuration and the [`authorize`](/docs/ui/server/authorization) model for locking it down.
