A modern, animated file upload widget with image compression, progress tracking, and cloud storage integration. Built with React, TypeScript, Node.js and Framer Motion.
- π¨ Beautiful UI - Modern design with smooth animations using Framer Motion
- π Drag & Drop - Intuitive file selection with React Dropzone
- ποΈ Image Compression - Automatic image optimization before upload
- π Progress Tracking - Real-time upload progress with visual indicators
- βοΈ Cloud Storage - Integration with Cloudflare R2 for file storage
- βΈοΈ Upload Control - Cancel, retry, and manage uploads
- π± Responsive - Works on desktop and mobile devices
- π― TypeScript - Fully typed for better development experience
This project consists of two main parts:
- Frontend (
/web) - React application with Vite - Backend (
/server) - Node.js API with Fastify
- Node.js 18+
- pnpm (recommended) or npm
- Cloudflare R2 account (for file storage)
git clone <repository-url>
cd upload-widget# Install root dependencies
pnpm install
# Install frontend dependencies
cd web
pnpm install
# Install backend dependencies
cd ../server
pnpm installCreate a .env file in the server directory:
CLOUDFLARE_ACCESS_KEY_ID=your_access_key
CLOUDFLARE_SECRET_ACCESS_KEY=your_secret_key
CLOUDFLARE_BUCKET=your_bucket_name
CLOUDFLARE_ACCOUNT_ID=your_account_id
CLOUDFLARE_PUBLIC_URL=https://your-bucket.your-domain.comTerminal 1 - Backend:
cd server
pnpm devTerminal 2 - Frontend:
cd web
pnpm devThe application will be available at http://localhost:5174 (or the next available port).
- React 19 - UI library
- TypeScript - Type safety
- Vite - Build tool and dev server
- Tailwind CSS - Styling
- Framer Motion - Animations
- Zustand - State management
- Immer - Immutable state updates
- Radix UI - Accessible components
- React Dropzone - File drag & drop
- Axios - HTTP client
- Node.js - Runtime
- Fastify - Web framework
- TypeScript - Type safety
- Zod - Schema validation
- AWS SDK - Cloudflare R2 integration
upload-widget/
βββ web/ # Frontend React app
β βββ src/
β β βββ components/ # React components
β β β βββ ui/ # Reusable UI components
β β β βββ upload-widget-* # Widget-specific components
β β βββ store/ # Zustand state management
β β βββ http/ # API client functions
β β βββ utils/ # Utility functions
β βββ package.json
βββ server/ # Backend API
β βββ src/
β β βββ routes/ # API routes
β β βββ functions/ # Business logic
β β βββ storage/ # Storage providers
β βββ package.json
βββ README.md
Main widget component with collapsible functionality and smooth animations.
Individual upload item with progress bar, status indicators, and action buttons.
File selection area with drag & drop support.
Zustand store managing upload state with Immer for immutable updates.
Configure compression settings in web/src/utils/compress-image.ts:
const compressedFile = await compressImage({
file: upload.file,
maxWidth: 1000, // Maximum width
maxHeight: 1000, // Maximum height
quality: 0.8, // Compression quality (0-1)
});The backend uses Cloudflare R2 for file storage. To use a different provider, modify server/src/storage/providers/r2-storage.ts.
Uploads a compressed image file to cloud storage.
Request:
multipart/form-datawithfilefield
Response:
{
"url": "https://your-bucket.your-domain.com/path/to/file.jpg"
}The project uses Tailwind CSS with custom configurations:
- Colors: Zinc-based dark theme
- Animations: Framer Motion for smooth transitions
- Components: Radix UI for accessibility
- Icons: Lucide React icon library
cd web
pnpm build
# Deploy the dist/ foldercd server
# Set environment variables
# Deploy the server- Framer Motion for smooth animations
- Radix UI for accessible components
- Tailwind CSS for styling
- Zustand for state management