Documentation
Documentation
Introduction

Getting Started

Getting StartedInstallationQuick StartProject Structure

Architecture

Architecture OverviewTech StacktRPC MiddlewareDesign Principles

Patterns

Code Patterns & ConventionsFeature ModulesError HandlingType Safety

Database

DatabaseSchema DefinitionDatabase OperationsMigrationsCaching

API

tRPCProceduresRouterstRPC Proxy Setup
APIsOpenAPIREST Endpoints

Auth & Access

AuthenticationConfigurationOAuth ProvidersRolesSession Management
AuthorizationUser RolesPermissions

Routing & i18n

RoutingDeclarative RoutingNavigation
InternationalizationTranslationsLocale Routing

Components & UI

ComponentsButtonsFormsNavigationDialogs
StylesTailwind CSSThemingTypography

Storage

StorageConfigurationUsageBuckets

Configuration

ConfigurationEnvironment VariablesFeature Flags

Templates

Template GuidesCreate New FeatureCreate New PageCreate Database TableCreate tRPC RouterAdd Translations

Development

DevelopmentCommandsAI AgentsBest Practices

Usage

Upload and manage files in your application

FileUpload Component

The FileUpload component provides a complete upload experience with drag-and-drop support.

import { FileUpload } from "@/forms/file/file-upload";

<FileUpload
  bucket="avatars"
  accept="image/*"
  maxSize={5 * 1024 * 1024} // 5MB
  onUpload={(path) => {
    console.log("Uploaded to:", path);
  }}
/>;

Props

PropTypeDescription
bucketUploadBucketsTarget storage bucket
acceptstringAccepted MIME types
maxSizenumberMax file size in bytes
onUpload(path: string) => voidCallback after successful upload
disabledbooleanDisable the upload

useFileUpload Hook

For custom upload UI, use the useFileUpload hook:

import { useFileUpload } from "@/forms/file/use-file-upload";

function CustomUploader() {
  const { upload, isUploading, progress } = useFileUpload({
    bucket: "documents",
  });

  const handleFile = async (file: File) => {
    const path = await upload(file);
    console.log("File uploaded to:", path);
  };

  return (
    <div>
      <input type="file" onChange={(e) => handleFile(e.target.files[0])} />
      {isUploading && <p>Uploading... {progress}%</p>}
    </div>
  );
}

Server-Side Operations

Upload a File

import { storage } from "@/lib/storage/server";

const buffer = Buffer.from(fileContent);
await storage.upload("path/to/file.pdf", buffer, "application/pdf");

Get a Signed URL

// For reading (download link)
const downloadUrl = await storage.getSignedUrl("path/to/file.pdf", "read");

// For writing (upload link)
const uploadUrl = await storage.getSignedUrl("path/to/file.pdf", "write");

Delete a File

await storage.delete("path/to/file.pdf");

Check if File Exists

const exists = await storage.exists("path/to/file.pdf");

API Routes

The storage system includes API routes for file operations:

  • POST /api/files/upload - Request upload URL
  • GET /api/files/get-url - Get signed download URL
  • GET /api/files/view - Stream file content

Security

  • All uploads require authentication
  • File paths include user/organization IDs for isolation
  • Signed URLs expire after a configurable duration
  • MIME type validation prevents malicious uploads

On this page

FileUpload Component
Props
useFileUpload Hook
Server-Side Operations
Upload a File
Get a Signed URL
Delete a File
Check if File Exists
API Routes
Security