# How to Integrate the Fastio API with SvelteKit

SvelteKit's server-side form actions and API routes make it a strong fit for integrating with the Fastio API. This guide walks through authentication, file uploads, workspace management, and Intelligence Mode queries, all while keeping API keys off the client.

Source: https://fast.io/resources/fastio-api-sveltekit-integration/
Last reviewed: 2026-03-23

## Why SvelteKit Works Well for Fastio Integrations

SvelteKit gives you server-side code execution out of the box. Every `+page.server.ts` file and `+server.ts` endpoint runs exclusively on the server, which means your Fastio API key never reaches the browser. That alone solves the biggest security concern with client-side file upload integrations.

Beyond security, SvelteKit's form actions provide a clean pattern for file uploads. A standard HTML `<form>` with `enctype="multipart/form-data"` submits directly to a server action that can parse the file, forward it to the Fastio API, and return results to the page. Progressive enhancement via `use:enhance` makes this feel instant without requiring you to build a separate API layer.

SvelteKit's adoption has grown . GitHub stars for the Svelte ecosystem crossed 80,000 by mid-2025, and developer usage reached roughly 20% in recent State of JS surveys. The framework's compile-time approach produces smaller bundles and faster hydration than most alternatives, which matters when you're building file-heavy applications that need to stay responsive.

If you've built file upload flows with Next.js or Remix, the SvelteKit equivalent is simpler. There's no need for a separate API route for most operations. Form actions handle the round trip natively, and SvelteKit 2.49 introduced streaming file uploads in form actions, letting you process files while they're still uploading.

## What to check before scaling Fastio API SvelteKit integration

Fastio uses Bearer token authentication. You'll need an API key from your Fastio developer dashboard, stored in an environment variable that SvelteKit's server-side code can access.

Create a `.env` file at your project root:

```
FASTIO_API_KEY=your_api_key_here
FASTIO_BASE_URL=https://api.fast.io/current
```

Then create a reusable API client in `src/lib/server/fastio.ts`:

```typescript
import { FASTIO_API_KEY, FASTIO_BASE_URL } from '$env/static/private';

export async function fastioFetch(
  path: string,
  options: RequestInit = {}
) {
  const url = `${FASTIO_BASE_URL}${path}`;
  const response = await fetch(url, {
    ...options,
    headers: {
      Authorization: `Bearer ${FASTIO_API_KEY}`,
      ...options.headers,
    },
  });

if (!response.ok) {
    const error = await response.json();
    throw new Error(error?.error?.text || 'Fastio API error');
  }

return response.json();
}
```

The `$env/static/private` import is key. SvelteKit enforces that these values are only accessible in server-side modules (files under `src/lib/server/` or `+page.server.ts` / `+server.ts`). If you accidentally import a private env var in a client-side file, SvelteKit throws a build error. This is a real guardrail, not just a convention.

For applications where users authenticate with their own Fastio accounts, use OAuth 2.0 with PKCE instead of a shared API key. Fastio supports S256 code challenge for browser-based flows, which fits SvelteKit's server-side auth handling well.

## Uploading Files with Form Actions

SvelteKit form actions are the most natural way to handle file uploads. The browser sends multipart form data to your server action, which extracts the file and forwards it to the Fastio API.

Here's a complete upload flow. First, the page component at `src/routes/upload/+page.svelte`:

```svelte
<script>
  import { enhance } from '$app/forms';

let { form } = $props();
  let uploading = $state(false);
</script>

<form
  method="POST"
  enctype="multipart/form-data"
  use:enhance={() => {
    uploading = true;
    return async ({ update }) => {
      uploading = false;
      await update();
    };
  }}
>
  <label>
    Choose a file
    <input type="file" name="file" required />
  </label>

<input
    type="hidden"
    name="workspaceId"
    value="your_workspace_id"
  />

<button disabled={uploading}>
    {uploading ? 'Uploading...' : 'Upload'}
  </button>
</form>

{#if form?.success}
  <p>Uploaded: {form.fileName}</p>
{/if}

{#if form?.error}
  <p class="error">{form.error}</p>
{/if}
```

Then the server action at `src/routes/upload/+page.server.ts`:

```typescript
import { fail } from '@sveltejs/kit';
import { fastioFetch } from '$lib/server/fastio';

export const actions = {
  default: async ({ request }) => {
    const formData = await request.formData();
    const file = formData.get('file') as File;
    const workspaceId = formData.get('workspaceId') as string;

if (!file || file.size === 0) {
      return fail(400, { error: 'No file selected' });
    }

const uploadBody = new FormData();
    uploadBody.append('file', file);

try {
      const result = await fastioFetch(
        `/workspace/${workspaceId}/upload/`,
        {
          method: 'POST',
          body: uploadBody,
        }
      );

return {
        success: true,
        fileName: file.name,
        fileId: result.file_id,
      };
    } catch (err) {
      return fail(500, {
        error: err instanceof Error
          ? err.message
          : 'Upload failed',
      });
    }
  },
};
```

A few things to note about this pattern. The `use:enhance` directive prevents a full page reload on submit, but the form still works without JavaScript. SvelteKit's `fail()` function returns the error data along with the appropriate HTTP status. The server action runs entirely on the server, so the API key never appears in the browser's network tab.

For files larger than 4 MB, Fastio supports chunked uploads. You would split the file into chunks on the server side and upload each chunk in a separate request. The API returns a session ID with the first chunk that you include in subsequent requests.

## Managing Workspaces from SvelteKit

Most file operations in Fastio happen within a workspace. You can create and manage workspaces through dedicated API endpoints, exposed via SvelteKit server routes.

Create a workspace management endpoint at `src/routes/api/workspaces/+server.ts`:

```typescript
import { json } from '@sveltejs/kit';
import { fastioFetch } from '$lib/server/fastio';

export async function GET() {
  const data = await fastioFetch('/workspace/');
  return json(data);
}

export async function POST({ request }) {
  const { name, folderName, enableIntelligence } =
    await request.json();

const data = await fastioFetch('/workspace/', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      name,
      folder_name: folderName,
      intelligence: enableIntelligence ?? true,
    }),
  });

return json(data);
}
```

Note that `folder_name` must be 4 to 80 characters, alphanumeric with hyphens. The `name` field allows 2 to 100 characters. Agent-created workspaces default to Intelligence enabled, which means files are automatically indexed for semantic search and AI chat as soon as they're uploaded.

On the frontend, call these endpoints from a SvelteKit page using the built-in `fetch`:

```svelte
<script>
  let workspaceName = $state('');
  let folderName = $state('');
  let workspaces = $state([]);

async function loadWorkspaces() {
    const res = await fetch('/api/workspaces');
    workspaces = await res.json();
  }

async function createWorkspace() {
    await fetch('/api/workspaces', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        name: workspaceName,
        folderName: folderName,
        enableIntelligence: true,
      }),
    });
    await loadWorkspaces();
  }
</script>
```

The `+server.ts` approach works well for workspace management because these operations are typically triggered by button clicks rather than form submissions. You get clean REST-style endpoints without needing a separate backend.

Storage and seats come with the plan, so workspace creation is not metered. Starter is $29 per month ($24 billed annually) with 5 seats, 1 TB of storage, and 300,000 monthly credits, and credits are spent on AI work rather than on the workspaces themselves.

## Querying Files with Intelligence Mode

One of the more useful patterns for a SvelteKit application is connecting to Fastio's Intelligence Mode. When Intelligence is enabled on a workspace, every uploaded file is automatically indexed for semantic search and RAG-powered chat. You don't need to set up a separate vector database or ingestion pipeline.

Create a search endpoint at `src/routes/api/search/+server.ts`:

```typescript
import { json } from '@sveltejs/kit';
import { fastioFetch } from '$lib/server/fastio';

export async function POST({ request }) {
  const { workspaceId, query } = await request.json();

const results = await fastioFetch(
    `/workspace/${workspaceId}/storage/search/`,
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ query }),
    }
  );

return json(results);
}
```

And an AI chat endpoint for asking questions about your files:

```typescript
// src/routes/api/chat/+server.ts
import { json } from '@sveltejs/kit';
import { fastioFetch } from '$lib/server/fastio';

export async function POST({ request }) {
  const { workspaceId, question } = await request.json();

const answer = await fastioFetch(
    `/workspace/${workspaceId}/ai/chat/`,
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ message: question }),
    }
  );

return json(answer);
}
```

The chat responses include citations pointing to specific files, pages, and text snippets. This is useful for building document Q&A interfaces where users need to verify the source of an answer.

Compare this to building a similar feature with S3 plus Pinecone or Weaviate. With those, you'd need to set up document parsing, chunking, embedding generation, vector storage, and retrieval before you can run a single query. Fastio collapses that entire stack into enabling Intelligence on a workspace and uploading files. The tradeoff is less control over embedding models and chunking strategies, but for most applications, the built-in defaults work well enough.

You can also use semantic search without the chat layer. This is faster and doesn't consume AI token credits. It's a good fit for autocomplete-style file search or building a knowledge base browser.

## Error Handling and Production Concerns

Production integrations need to handle several scenarios that simple examples skip over.

**Rate limiting and retries.** Wrap your `fastioFetch` helper with retry logic for transient failures:

```typescript
export async function fastioFetchWithRetry(
  path: string,
  options: RequestInit = {},
  maxRetries = 3
) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fastioFetch(path, options);
    } catch (err) {
      if (attempt === maxRetries - 1) throw err;
      await new Promise((r) =>
        setTimeout(r, 1000 * Math.pow(2, attempt))
      );
    }
  }
}
```

**File size validation.** Check file size before forwarding to the API. Set a ceiling that matches your app's needs and reject oversized files early, which saves bandwidth on both ends:

```typescript
const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100 MB

if (file.size > MAX_FILE_SIZE) {
  return fail(413, {
    error: 'File exceeds the 100 MB upload limit',
  });
}
```

**Concurrent uploads.** If your application handles simultaneous uploads, leverage Fastio's file version history and granular permissions to manage revisions safely. Version history preserves previous states so changes can be audited or restored without conflicting overwrites.

**Activity tracking.** Rather than aggressive polling loops, monitor Fastio's realtime activity feed or WebSocket events feed from your server route:

```typescript
// src/routes/api/activity/+server.ts
import { json } from '@sveltejs/kit';

export async function GET({ url }) {
  const entityId = url.searchParams.get('entityId');
  const res = await fetch(`https://api.fast.io/current/activity/poll/${entityId}?wait=95`, {
    headers: { Authorization: `Bearer ${process.env.FASTIO_API_KEY}` }
  });
  const data = await res.json();
  return json(data);
}
```

This long-poll pattern works cleanly with SvelteKit's server routes for pushing updates to clients.

**Environment-specific configuration.** SvelteKit supports `.env.development` and `.env.production` files. Use different Fastio API keys per environment so your development workspace stays separate from production data.

## Putting It Together

A practical SvelteKit plus Fastio application might combine all these patterns. Consider a client portal where freelancers share deliverables with clients. The architecture looks like this:

1. **Authentication**: OAuth PKCE flow so each user connects their own Fastio account
2. **Workspace per project**: Create a workspace when a new project starts, with Intelligence enabled for file search
3. **File uploads via form actions**: Clients and freelancers upload through the same interface, with files landing in the shared workspace
4. **AI-powered search**: Clients search across all project files using natural language
5. **Branded shares**: Generate Send or Receive shares for external stakeholders who don't need full workspace access

The SvelteKit project structure for this would look like:

```
src/routes/
├── +layout.server.ts      # Auth check
├── projects/
│   ├── +page.svelte       # List workspaces
│   ├── +page.server.ts    # Load workspaces
│   └── [id]/
│       ├── +page.svelte   # Project detail
│       ├── +page.server.ts # Load files
│       └── upload/
│           └── +page.server.ts # Upload action
├── search/
│   └── +server.ts         # AI search endpoint
└── api/
    └── activity/
        └── +server.ts     # Activity poll handler
```

When an agent needs to work on this project alongside humans, it can access the same workspace through the [Fastio MCP server](/storage-for-agents/) or the REST API directly. The agent and human see the same files, the same Intelligence index, and the same activity history. When the agent's work is done, ownership can be transferred to the human client.

To get started, visit [fast.io/pricing](/pricing/). You can start with a 14-day Business Trial requiring a credit card, or choose a Starter ($29/mo), Business ($99/mo), or Growth ($299/mo) plan. Pair that with `npm create svelte@latest` and you can have a working integration in an afternoon.

## Frequently asked questions

### How do I handle file uploads in SvelteKit with Fastio?

Use SvelteKit form actions in a +page.server.ts file. The form submits multipart data to your server action, which extracts the file from FormData and forwards it to the Fastio upload endpoint using Bearer token authentication. The API key stays server-side, and the form works with or without JavaScript enabled.

### Is the Fastio API compatible with SvelteKit server endpoints?

Yes. Fastio exposes a standard REST API at api.fast.io/current/ with JSON responses. SvelteKit's +server.ts endpoints can call it directly using fetch with Bearer token auth. You can create GET, POST, PUT, and DELETE handlers that proxy Fastio operations while keeping credentials on the server.

### Do I need a separate backend to use Fastio with SvelteKit?

No. SvelteKit's built-in server routes and form actions run on the server, so they can securely call the Fastio API without exposing your API key. You don't need Express, Fastify, or any additional backend framework.

### How does Intelligence Mode work with uploaded files?

When Intelligence is enabled on a Fastio workspace, every file you upload is automatically indexed for semantic search and AI chat. You can query the workspace through the API to search files by meaning or ask questions that return cited answers from your documents. No separate vector database setup is needed.

### What are the rate limits for the Fastio API?

Fastio uses a credit-based system rather than strict rate limits. Credits meter AI work such as chat (roughly 1 credit per 100 tokens), document ingestion, and agent runs, while storage and seats come with the plan. Starter includes 300,000 credits per month, and overage is billed at $10 per 100,000 credits. Check the Fastio pricing page for current allocations per plan.

## About Fast.io

Fast.io provides shared workspaces where people and AI agents work on the same files, with built-in semantic search and citation-backed chat over what they hold. Agents reach it through a remote MCP server at https://mcp.fast.io/mcp, a REST API at https://api.fast.io/current/, and a command line client published on npm as @vividengine/fastio-cli.
