SonusLab StorageSonusLab Storage

Quickstart

From zero to a working upload in under five minutes.

1

Create an app

Head to /apps and click New App. Pick a name, region, visibility, and a max file size.

2

Create an API key

Open the app's Keys tab and click Create. Copy the sl_... token shown — it's displayed exactly once.

Store it securely

The key is hashed at rest. If you lose it, rotate and re-deploy — there's no recovery.
3

Install the package

bun add sonuslab-storage

Vue is an optional peer dependency — only required if you import from sonuslab-storage/vue.

4

First upload (server)

For small files (think reports, avatars, attachments), upload the bytes straight from your server.

server/upload-report.ts
import { StorageClient } from 'sonuslab-storage/server'
import { readFile } from 'node:fs/promises'

const storage = new StorageClient({
  apiKey: process.env.SONUSLAB_STORAGE_API_KEY!,
})

const data = await readFile('./report.pdf')

const file = await storage.upload({
  name: 'report.pdf',
  contentType: 'application/pdf',
  data,
  metadata: { userId: 'abc' },
})

console.log(file.id, file.key, file.url)
5

First browser upload

For user-driven uploads, the browser uploads bytes via a short-lived upload URL. Wire up two server routes (presign + complete), then call uploadFile from your component.

server/api/upload/presign.post.ts
import { StorageClient } from 'sonuslab-storage/server'

const storage = new StorageClient({
  apiKey: process.env.SONUSLAB_STORAGE_API_KEY!,
})

export default defineEventHandler(async (event) => {
  const body = await readBody(event)
  return storage.presign(body)
})
server/api/upload/complete.post.ts
export default defineEventHandler(async (event) => {
  const { fileId } = await readBody(event)
  return storage.completeUpload({ fileId })
})
components/Uploader.vue (browser)
<script setup lang='ts'>
import { uploadFile } from 'sonuslab-storage/client'

async function onChange(e: Event) {
  const file = (e.target as HTMLInputElement).files?.[0]
  if (!file) return
  const result = await uploadFile({
    file,
    presignEndpoint: '/api/upload/presign',
    completeEndpoint: '/api/upload/complete',
    onProgress: (p) => console.log(`${p.percent}%`),
  })
  console.log('uploaded', result.fileId, result.key)
}
</script>

<template>
  <input type='file' @change='onChange' />
</template>

Next steps

  • Vue integration — useUpload composable and headless StorageUpload component.
  • Webhooks — react to upload.completed events server-side.
  • Multipart uploads — for files larger than your single-PUT limit.