File Uploads

S3/R2

Upload, store, and manage files using the Sylphx Storage service.

Cloud Storage

S3/R2 compatible backend

CDN Delivery

Fast global distribution

Private Files

Signed URLs for access

Auto Resize

Image processing built-in

Upload Files

Upload files from client or server:

Client-side (React)
'use client'

import { useStorage } from '@sylphx/platform-sdk/react'
import { useState } from 'react'

export function FileUploader() {
  const { upload } = useStorage()
  const [uploading, setUploading] = useState(false)
  const [uploadedUrl, setUploadedUrl] = useState<string | null>(null)

  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0]
    if (!file) return

    setUploading(true)
    try {
      const result = await upload(file, {
        path: 'uploads',    // Optional folder path
        public: true,       // Make publicly accessible
      })

      setUploadedUrl(result.url)
      console.log('Uploaded:', result)
    } catch (error) {
      console.error('Upload failed:', error)
    } finally {
      setUploading(false)
    }
  }

  return (
    <div>
      <input type="file" onChange={handleFileChange} disabled={uploading} />
      {uploading && <p>Uploading...</p>}
      {uploadedUrl && <p>Uploaded: <a href={uploadedUrl}>{uploadedUrl}</a></p>}
    </div>
  )
}
Server-side
import { platform } from '@/lib/platform'

// Upload from buffer or stream
const result = await platform.storage.upload({
  file: fileBuffer,
  filename: 'document.pdf',
  contentType: 'application/pdf',
  path: 'documents',
  public: false,
  metadata: {
    uploadedBy: user.id,
    category: 'invoices',
  },
})

console.log(result.id)       // Unique file ID
console.log(result.url)      // Public URL (if public)
console.log(result.signedUrl) // Signed URL for private files

Upload Response

Upload response structure:

PropertyTypeDescription
idstringUnique file identifier
filenamestringOriginal filename
pathstringStorage path
contentTypestringMIME type
sizenumberFile size in bytes
urlstringPublic URL (if public)
signedUrlstring?Signed URL (if private)
metadataobject?Custom metadata
createdAtDateUpload timestamp

Avatar Upload

Shortcut for uploading user avatars with automatic processing:

'use client'

import { useStorage, useUser } from '@sylphx/platform-sdk/react'

export function AvatarUpload() {
  const { uploadAvatar } = useStorage()
  const { user, refreshUser } = useUser()

  const handleChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0]
    if (!file) return

    // uploadAvatar automatically:
    // - Resizes to appropriate dimensions
    // - Crops to square
    // - Updates user profile
    await uploadAvatar(file)
    await refreshUser()
  }

  return (
    <div className="flex items-center gap-4">
      <img
        src={user?.avatar}
        alt="Avatar"
        className="w-20 h-20 rounded-full object-cover"
      />
      <label className="cursor-pointer px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90">
        Change Avatar
        <input type="file" accept="image/*" onChange={handleChange} className="hidden" />
      </label>
    </div>
  )
}

Upload Options

Available upload options:

PropertyTypeDescription
pathstringFolder path (e.g., "uploads/images")
publicbooleanWhether file is publicly accessible
filenamestringOverride original filename
contentTypestringOverride MIME type
metadataobjectCustom metadata
maxSizenumberMaximum file size in bytes

List Files

List uploaded files:

// List all files
const files = await platform.storage.list()

// List files in a folder
const images = await platform.storage.list({
  path: 'uploads/images',
})

// List user's files
const userFiles = await platform.storage.list({
  userId: user.id,
})

// Pagination
const page2 = await platform.storage.list({
  limit: 20,
  cursor: files.nextCursor,
})

Delete Files

Delete uploaded files:

// Delete by ID
await platform.storage.delete(fileId)

// Delete multiple files
await platform.storage.deleteMany([fileId1, fileId2, fileId3])

Storage Limits

Default file size limits by plan:

Free

Max file: 10 MB

Total: 100 MB

Pro

Max file: 100 MB

Total: 10 GB

Enterprise

Max file: 1 GB

Total: Unlimited

Custom Limits

Configure custom file size limits in your dashboard under App Settings → Storage.