Features
File Uploads
S3-compatible file uploads with Better Upload — Backblaze B2 in prod, MinIO locally.
TheShipStack uses Better Upload with an S3-compatible backend.
Local setup
MinIO runs via Docker Compose and is used automatically in development. See Local Development for access details.
Production setup
In production, files go to Backblaze B2. Create a B2 bucket (set to public) and an App Key, then set the storage env vars. See Deployment for details.
Upload route
The upload handler lives in app/api/upload/route.ts. It validates the request and returns a pre-signed URL for direct browser-to-storage upload.
Uploading a file from the client
import { useUpload } from 'better-upload/client'
export function AvatarUpload() {
const { upload, isUploading } = useUpload()
async function handleFile(file: File) {
const { url } = await upload({ file, route: 'avatar' })
// url is the permanent public URL of the uploaded file
}
return <input type="file" onChange={(e) => handleFile(e.target.files![0])} />
}Adding a new upload route
In app/api/upload/route.ts, add a new route config alongside the existing ones:
documents: {
maxFileSize: '10mb',
allowedFileTypes: ['application/pdf'],
},