DEV Community

Cover image for How to Integrate Filestack with SvelteKit Using the JavaScript SDK
IderaDevTools
IderaDevTools

Posted on • Originally published at blog.filestack.com

How to Integrate Filestack with SvelteKit Using the JavaScript SDK

Adding uploads to a SvelteKit app comes down to a single decision about how much of the upload layer you want to own. Filestack’s JavaScript SDK covers uploads, storage, a global CDN, and image processing, so a single page component and one server route get you a working, secured upload. This guide ships exactly that, and you can grab a free API key and build it in your own project as you read.

The browser sends the file straight to Filestack, and a small +server.js route signs the short-lived credentials that keep your app secret on the server. You write the upload once, point your components at it, and spend the rest of your time on the parts of your product that need you.

Every snippet runs against the real filestack-js SDK. Copy them in order and you will have a working upload, signed credentials, and a resized image by the end.

Key takeaways

  • The SDK works in the browser with just your public API key, so a basic upload is one init call and one client.upload(file) call

  • A SvelteKit +server.js route signs a short-lived policy with your app secret, which lives in $env/static/private and stays server-side

  • The signing logic is a handful of node:crypto lines, so the server route needs no extra packages

  • client.upload accepts the File object from an directly, so the bytes travel straight from the browser to Filestack

  • Transformations are delivery-time CDN URLs, so resizing an image is a string you build from the returned handle

Before you start

You need:

  • Node 18 or higher

  • A SvelteKit project (npm create svelte@latest)

  • A Filestack account for your API key and app secret

  • Familiarity with Svelte components and SvelteKit routing

Pull your API key and app secret from the Filestack developer portal. The API key is fine in client code. The app secret stays on the server and signs every policy.

Step 1: Install and set environment variables

Install the SDK:

npm install filestack-js

Add your keys to .env:

PUBLIC_FILESTACK_API_KEY=Axxxxxxxxxxxxxxxxxxxxx

FILESTACK_APP_SECRET=your-app-secret-here

SvelteKit exposes anything prefixed with PUBLIC_ to the browser through $env/static/public. Everything else stays server-only in $env/static/private. That split is the whole security story in one naming convention.

Step 2: Get a working upload with the public key

Filestack apps start with security off, so an API key is enough for your first upload. Create src/routes/+page.svelte:

<script>
import { onMount } from 'svelte';
  import { PUBLIC_FILESTACK_API_KEY } from '$env/static/public';

  let client;
  let result = $state(null);
  let uploading = $state(false);

  onMount(async () => {
    const filestack = await import('filestack-js');
    client = filestack.init(PUBLIC_FILESTACK_API_KEY);
  });

  async function handleFile(event) {
    const file = event.currentTarget.files?.[0];
    if (!file) return;
    uploading = true;
    result = await client.upload(file);
    uploading = false;
  }
</script>

<input type="file" onchange={handleFile} />

{#if uploading}<p>Uploading...</p>{/if}

{#if result}
  <p>Uploaded {result.filename}</p>
  <img src={result.url} alt={result.filename} width="320" />
{/if}
Enter fullscreen mode Exit fullscreen mode

Run npm run dev, pick a file, and you have a working upload. The result object carries everything you need next: result.handle, result.url, result.filename, result.mimetype, and result.size. Save the handle in your database, since it is the durable identifier you reuse for signed reads, transformations, and deletes. The URL is convenience metadata.

Press enter or click to view image in full size

Step 3: Sign a policy on the server

Once you turn on security in the developer portal, every upload needs a policy and a signature. Both come from a short-lived security policy signed with your app secret. Create src/routes/api/filestack-creds/+server.js:

import { json } from '@sveltejs/kit';
import { createHmac } from 'node:crypto';
import { FILESTACK_APP_SECRET } from '$env/static/private';

function signPolicy(policy, secret) {
  const encoded = Buffer.from(JSON.stringify(policy))
    .toString('base64')
    .replace(/\+/g, '-')
    .replace(/\//g, '_');
  const signature = createHmac('sha256', secret).update(encoded).digest('hex');
  return { policy: encoded, signature };
}

export function GET() {
  const policy = {
    expiry: Math.floor(Date.now() / 1000) + 300, // valid for 5 minutes
    call: ['pick', 'store', 'read', 'convert']
  };
  return json(signPolicy(policy, FILESTACK_APP_SECRET));
}
Enter fullscreen mode Exit fullscreen mode

This route returns a five-minute credential scoped to the calls you allow. Keep it behind your own auth so only signed-in users can request one. The app secret never leaves the server, and the browser only ever sees the encoded policy and its signature.

Step 4: Upload with the signed credentials

Update the handler to fetch credentials first, then initialize the client with that security object:

async function handleFile(event) {
const file = event.currentTarget.files?.[0];
  if (!file) return;
  uploading = true;
  const filestack = await import('filestack-js');
  const security = await fetch('/api/filestack-creds').then((r) => r.json());
  const secured = filestack.init(PUBLIC_FILESTACK_API_KEY, { security });
  result = await secured.upload(file);
  uploading = false;
}
Enter fullscreen mode Exit fullscreen mode

The flow stays the same from the user’s side. The only change is that the client now carries a signed, expiring policy, so Filestack accepts the upload on a secured app.

Step 5: Resize on delivery

Filestack transformations happen at delivery time. Build a CDN URL from the returned handle:

{#if result}
<img
    src={`https://cdn.filestackcontent.com/resize=width:600/${result.handle}`}
    alt={result.filename}
  />
{/if}
Enter fullscreen mode Exit fullscreen mode

The resize runs on the Filestack Processing Engine and the result is cached on the CDN, so your SvelteKit app never touches the bytes. The same URL pattern handles cropping, format conversion, and compression. With security on, append the read credentials as query parameters:

const src =
`https://cdn.filestackcontent.com/resize=width:600/${result.handle}` +
  `?policy=${security.policy}&signature=${security.signature}`;
Enter fullscreen mode Exit fullscreen mode

Putting it all together

One page component, one +server.js route, and the real SDK. The browser handles the transfer, the route signs short-lived policies with node:crypto, the app secret stays server-side, and a resize is a URL built from the handle. That covers the upload pipeline most apps need, and you wrote about forty lines to get it.

Create your free Filestack API key, wire up the page component and the policy route above, and you have secured uploads and transformations in your SvelteKit app the same afternoon. When you size it for production traffic, Filestack pricing scales with uploads, transformations, and bandwidth.

Originally published on the Filestack blog.

Top comments (0)