Getting Started
1. Database Schema
Add the files table to your database schema:
import { createFilesTable } from '@repo/storage/database'
// Global database
export const filesTable = createFilesTable()
// Or tenant-scoped
import { tenantSchema } from '@repo/auth/database'
export const filesTable = createFilesTable(tenantSchema)
The table includes columns: name, key, bucket, storage, mimeType, size, and deletedAt.
2. Server File Manager
Create a server-side instance in your app:
// lib/files.server.ts
import { env } from '$env/dynamic/private'
import { getGlobalDb } from '$lib/db/managedDb.server'
import { S3Client } from '@aws-sdk/client-s3'
import { FilesRepository, ServerFileManager } from '@repo/storage/server'
export const serverFileManager = new ServerFileManager({
repository: new FilesRepository(getGlobalDb),
s3: {
client: new S3Client({
endpoint: env.PRIVATE_S3_ENDPOINT,
region: 'us-west-1',
forcePathStyle: true,
credentials: {
accessKeyId: env.S3_ACCESS_KEY_ID!,
secretAccessKey: env.S3_SECRET_ACCESS_KEY!,
},
}),
},
})
3. Basic Upload
Define a schema, create a form, and upload a file:
import { FileInput } from '@repo/storage'
import { zaf } from '@repo/form'
import { z } from 'zod'
export const myFormSchema = z.object({
name: z.string(),
file: zaf(z.file(), {
component: FileInput.Root
}),
})
export const createForm = form(myFormSchema, async ({ file, ...data }) => {
await serverFileManager.createBucket('my-bucket')
const { createdFile } = await serverFileManager.sync('my-bucket', { file })
await db.insert(myTable).values({ ...data, fileId: createdFile.id })
})
Next Steps
- Single File -- create, update, and edit flows
- Multiple Files -- multi-file uploads with delete tracking
- Serving Files -- private streaming and public URLs