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 filesUpload Response
Upload response structure:
| Property | Type | Description |
|---|---|---|
id | string | Unique file identifier |
filename | string | Original filename |
path | string | Storage path |
contentType | string | MIME type |
size | number | File size in bytes |
url | string | Public URL (if public) |
signedUrl | string? | Signed URL (if private) |
metadata | object? | Custom metadata |
createdAt | Date | Upload 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:
| Property | Type | Description |
|---|---|---|
path | string | Folder path (e.g., "uploads/images") |
public | boolean | Whether file is publicly accessible |
filename | string | Override original filename |
contentType | string | Override MIME type |
metadata | object | Custom metadata |
maxSize | number | Maximum 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.