58206d5b1823a5fd9a20668669f68f01325656ad
Changed from image.write((data) => data) callback pattern to image.write(outputFormatEnum) which correctly writes the image data in the specified format. This should now produce valid WebP files with proper RIFF headers (52 19 46 46 magic bytes). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Convert UI
A modern, browser-based file conversion application built with Next.js 16, Tailwind CSS 4, and WebAssembly. Convert videos, audio, and images directly in your browser without uploading files to any server.
Features
- 🎬 Video Conversion - Convert between MP4, WebM, AVI, MOV, MKV, and GIF
- 🎵 Audio Conversion - Convert between MP3, WAV, OGG, AAC, and FLAC
- 🖼️ Image Conversion - Convert between PNG, JPG, WebP, GIF, BMP, TIFF, and SVG
- 🔒 Privacy First - All conversions happen locally in your browser, no server uploads
- ⚡ Fast & Efficient - Powered by WebAssembly for near-native performance
- 🎨 Beautiful UI - Modern, responsive design with dark/light theme support
- 🔍 Smart Search - Fuzzy search for quick format selection
- 📝 Conversion History - Track your recent conversions
- 🎯 Drag & Drop - Easy file upload with drag-and-drop support
Tech Stack
- Next.js 16 - React framework with App Router and static export
- React 19 - Latest React with concurrent features
- TypeScript 5 - Type-safe development
- Tailwind CSS 4 - Utility-first CSS with OKLCH color system
- FFmpeg.wasm - Video and audio conversion
- ImageMagick WASM - Image processing and conversion
- Fuse.js - Fuzzy search for format selection
- Lucide React - Beautiful icon library
Getting Started
Prerequisites
- Node.js 22+ (managed via nvm)
- pnpm (enabled via corepack)
Installation
# Clone the repository
git clone <repository-url>
cd convert-ui
# Install dependencies
pnpm install
# Run development server
pnpm dev
Open http://localhost:3000 to view the app.
Build for Production
# Build static export
pnpm build
# Output will be in the /out directory
Project Structure
convert-ui/
├── app/ # Next.js App Router
│ ├── layout.tsx # Root layout with theme
│ ├── page.tsx # Main page
│ └── globals.css # Global styles
├── components/
│ ├── converter/ # Converter components
│ │ ├── FileConverter.tsx # Main state manager
│ │ ├── FileUpload.tsx # Drag-and-drop upload
│ │ ├── FormatSelector.tsx # Format selection with search
│ │ ├── ConversionPreview.tsx # Preview and download
│ │ └── ConversionOptions.tsx # Format-specific options
│ ├── layout/
│ │ └── ThemeToggle.tsx # Dark/light theme toggle
│ └── ui/ # Reusable UI components
│ ├── Button.tsx
│ ├── Card.tsx
│ ├── Toast.tsx
│ ├── Progress.tsx
│ ├── Skeleton.tsx
│ └── Input.tsx
├── lib/
│ ├── converters/ # Conversion services
│ │ ├── ffmpegService.ts # Video/audio conversion
│ │ └── imagemagickService.ts # Image conversion
│ ├── wasm/
│ │ └── wasmLoader.ts # WASM module lazy loading
│ ├── storage/
│ │ └── history.ts # Conversion history
│ └── utils/
│ ├── cn.ts # Class name utility
│ ├── fileUtils.ts # File operations
│ ├── formatMappings.ts # Supported formats
│ └── debounce.ts # Debounce utility
└── types/
└── conversion.ts # TypeScript interfaces
Supported Formats
Video (FFmpeg)
- Input/Output: MP4, WebM, AVI, MOV, MKV, GIF
Audio (FFmpeg)
- Input/Output: MP3, WAV, OGG, AAC, FLAC
Images (ImageMagick)
- Input/Output: PNG, JPG, WebP, GIF, BMP, TIFF, SVG
How It Works
- File Upload - Users can drag-and-drop or click to select a file
- Format Detection - The app automatically detects the input format
- Format Selection - Choose from compatible output formats
- Conversion - WASM modules are loaded on-demand and process the file
- Download - Preview and download the converted file
WASM Architecture
- Lazy Loading - WASM modules are only loaded when needed
- Memory Management - Proper cleanup after each conversion
- Progress Tracking - Real-time progress updates during conversion
- Error Handling - Graceful error handling with user-friendly messages
Browser Compatibility
- Chrome/Edge - Full support
- Firefox - Full support
- Safari - Full support (with SharedArrayBuffer)
Note: Some features require SharedArrayBuffer support. The app sets the required COOP/COEP headers for this.
Performance
- File Size Limit - 500MB (configurable)
- Conversion Speed - Varies by file size and format
- Images: < 5s for typical files
- Videos: Depends on length and quality
- Memory Usage - Managed automatically with cleanup
Development
Scripts
# Development server with Turbopack
pnpm dev
# Build for production
pnpm build
# Run production server
pnpm start
# Lint code
pnpm lint
Adding New Formats
- Add format to
lib/utils/formatMappings.ts - Implement converter in appropriate service
- Update type definitions in
types/conversion.ts
Customizing Theme
Colors are defined in app/globals.css using OKLCH color space. Modify CSS variables to change the theme:
:root {
--primary: oklch(22.4% 0.053 285.8);
--background: oklch(100% 0 0);
/* ... other colors */
}
Docker Deployment
# Build Docker image
docker build -t convert-ui .
# Run container
docker run -p 80:80 convert-ui
The Dockerfile uses a multi-stage build with Nginx to serve the static export.
Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
License
MIT License - See LICENSE file for details
Acknowledgments
- FFmpeg.wasm - Video/audio conversion
- ImageMagick WASM - Image processing
- Next.js - React framework
- Tailwind CSS - Styling
- Fuse.js - Fuzzy search
Support
For issues, questions, or suggestions, please open an issue on GitHub.
Made with ❤️ using Next.js 16 and WebAssembly
Description
Languages
TypeScript
94.9%
CSS
4.3%
Dockerfile
0.8%