A complete file storage solution with AWS S3 and Cloudflare R2 support. Includes dropzone component, file tracking, and example pages.
Install the file-storage component using the shadcn CLI:
pnpm dlx shadcn@latest add https://file-storage.desishub.com/r/file-storage.jsonMulti-variant dropzone with progress tracking, preview, and automatic upload to S3/R2.
Pre-configured clients for AWS S3 and Cloudflare R2 with presigned URL generation.
Ready-to-use API endpoints for file upload, delete, and tracking with file metadata storage.
/categories - List categories with image uploads. /file-storage - Track files, storage space & provider.
Run the following command to install the file-storage component:
pnpm dlx shadcn@latest add https://file-storage.desishub.com/r/file-storage.jsonThis will install all required files and dependencies.
If you don't have Prisma set up yet, install the required packages:
pnpm add @prisma/client @prisma/adapter-pg dotenv pg
pnpm add -D prisma tsx @types/pgInitialize Prisma:
pnpm dlx prisma initCreate a prisma.config.ts file:
import 'dotenv/config'
import { defineConfig } from 'prisma/config'
export default defineConfig({
earlyAccess: true,
schema: 'prisma/schema.prisma',
})Add the following models to your existing prisma/schema.prisma file:
Important: Don't replace your entire schema!
Only add the models below to your existing schema file.
// Required: File model for tracking uploads
model File {
id String @id @default(cuid())
name String
size Int
publicUrl String
type String
key String @unique
provider StorageProvider @default(cloudflare)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum StorageProvider {
aws
cloudflare
}
// Optional: Example Category model with file upload
model Category {
id String @id @default(cuid())
name String
slug String @unique
image String
description String?
isFeatured Boolean @default(false)
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}Add these environment variables to your .env file:
# Database
DATABASE_URL="postgresql://user:password@localhost:5432/dbname"
# AWS S3 Configuration (if using S3)
AWS_S3_REGION="us-east-1"
AWS_S3_BUCKET_NAME="your-bucket-name"
AWS_S3_ACCESS_KEY_ID=""
AWS_S3_SECRET_ACCESS_KEY=""
# Cloudflare R2 Configuration (if using R2)
CLOUDFLARE_R2_ACCESS_KEY_ID=""
CLOUDFLARE_R2_SECRET_ACCESS_KEY=""
CLOUDFLARE_R2_ENDPOINT="https://your-account-id.r2.cloudflarestorage.com"
CLOUDFLARE_R2_BUCKET_NAME="your-bucket-name"
CLOUDFLARE_R2_PUBLIC_DEV_URL="https://pub-xxx.r2.dev"Generate the Prisma client and push your schema to the database:
pnpm dlx prisma generate
pnpm dlx prisma db pushAdd this to your package.json for Vercel/production deployments:
{
"scripts": {
"postinstall": "prisma generate"
}
}import { Dropzone, FileWithMetadata } from "@/components/ui/dropzone";
import { useState } from "react";
export function MyComponent() {
const [files, setFiles] = useState<FileWithMetadata[]>([]);
return (
<Dropzone
provider="cloudflare" // or "aws"
variant="default" // "default" | "compact" | "minimal" | "avatar" | "inline"
maxFiles={5}
maxSize={1024 * 1024 * 10} // 10MB
onFilesChange={setFiles}
accept={{
"image/*": [],
"application/pdf": [],
}}
/>
);
}defaultcompactminimalavatarinlineyour-project/
├── app/
│ ├── (example)/
│ │ ├── categories/ # /categories - List categories with image upload
│ │ │ └── page.tsx
│ │ └── file-storage/ # /file-storage - Track files & storage stats
│ │ └── page.tsx
│ └── api/
│ ├── s3/
│ │ ├── upload/route.ts # S3 presigned URL generation
│ │ └── delete/route.ts # S3 file deletion
│ ├── r2/
│ │ ├── upload/route.ts # R2 presigned URL generation
│ │ └── delete/route.ts # R2 file deletion
│ └── v1/
│ ├── categories/ # Category CRUD endpoints
│ └── files/ # File listing & stats endpoints
├── components/
│ ├── ui/
│ │ ├── dropzone.tsx # Main dropzone component (5 variants)
│ │ └── error-display.tsx # Error display component
│ └── file-storage/
│ ├── categories/ # Category management components
│ └── files/ # File listing components
├── lib/
│ ├── s3Client.ts # AWS S3 client
│ ├── r2Client.ts # Cloudflare R2 client
│ ├── prisma.ts # Prisma client singleton
│ ├── fileDataExtractor.ts # URL metadata extractor
│ ├── getNormalDate.ts # Date formatter
│ └── api/
│ ├── categories/ # Category API helpers
│ └── files/ # File API helpers
└── prisma/
└── schema.prisma.example # Prisma models to add/categories/file-storageCheck out the example pages to see the components working together.