File Storage
shadcn Registry Component

File Storage System

A complete file storage solution with AWS S3 and Cloudflare R2 support. Includes dropzone component, file tracking, and example pages.

Cloudflare R2
AWS S3
Prisma 7
Dropzone

Quick Install

Install the file-storage component using the shadcn CLI:

pnpm dlx shadcn@latest add https://file-storage.desishub.com/r/file-storage.json

What's Included

Dropzone Component

Multi-variant dropzone with progress tracking, preview, and automatic upload to S3/R2.

Storage Clients

Pre-configured clients for AWS S3 and Cloudflare R2 with presigned URL generation.

API Routes

Ready-to-use API endpoints for file upload, delete, and tracking with file metadata storage.

2 Example Pages

/categories - List categories with image uploads. /file-storage - Track files, storage space & provider.

Installation Guide

1

Install the Component

Run the following command to install the file-storage component:

pnpm dlx shadcn@latest add https://file-storage.desishub.com/r/file-storage.json

This will install all required files and dependencies.

2

Set Up Prisma (if not already configured)

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/pg

Initialize Prisma:

pnpm dlx prisma init

Create a prisma.config.ts file:

import 'dotenv/config'
import { defineConfig } from 'prisma/config'

export default defineConfig({
  earlyAccess: true,
  schema: 'prisma/schema.prisma',
})
3

Add Prisma Models

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
}
4

Configure Environment Variables

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"
5

Generate Prisma Client & Push Schema

Generate the Prisma client and push your schema to the database:

pnpm dlx prisma generate
pnpm dlx prisma db push
6

Add Postinstall Script (for deployment)

Add this to your package.json for Vercel/production deployments:

{
  "scripts": {
    "postinstall": "prisma generate"
  }
}

Usage

Using the Dropzone Component

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": [],
      }}
    />
  );
}

Dropzone Variants

default
compact
minimal
avatar
inline

Installed Files

your-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

Example Pages Included

See it in Action

Check out the example pages to see the components working together.