Tech Stack
Frontend
React 19
Modern UI library with hooks and concurrent features
TypeScript 5.8
Type-safe JavaScript for better DX
Vite 7
Lightning-fast build tool and dev server
CSS3
Custom styles with macOS vibrancy effects
Backend
Tauri 2
Lightweight alternative to Electron using native webviews
Rust
Systems programming language for performance and safety
Tokio
Async runtime for concurrent operations
macOS Keychain
Secure credential storage using native APIs
Storage & Services
- Cloudflare R2: S3-compatible object storage
- rust-s3: S3 client library for R2 uploads
- arboard: Cross-platform clipboard access
Project Structure
Core Rust Modules
main.rs - Application Entry Point
Location: src-tauri/src/main.rs:248-350
The main module handles:
- App initialization - Loads R2 config and settings from disk
- Tray icon - Creates menu bar icon with positioning logic
- Window management - Shows/hides window on tray icon click
- Tauri commands - Exposes Rust functions to frontend via
invoke_handler
config.rs - Configuration Management
Location: src-tauri/src/config.rs
Handles secure storage of R2 credentials and app settings:
R2Config Structure:
save_r2_config()- Saves secrets to macOS Keychain as JSON blobload_r2_config()- Loads config from file + Keychaindelete_r2_config()- Removes credentials from Keychainmigrate_keychain_entries()- One-time cleanup of old format
- Credentials: macOS Keychain (
com.metalayer.zipdrop) - Config:
~/.config/zipdrop/config.json - Settings:
~/.config/zipdrop/settings.json
processor.rs - File Processing
Location: src-tauri/src/processor.rs
Handles file validation, image conversion, and ZIP creation:
Processing Logic (see src-tauri/src/processor.rs:287-313):
- Single convertible image → WebP conversion at 80% quality
- Multiple files → ZIP archive with deflate compression
- Single non-image or WebP → Passthrough copy
ALLOWED_EXTENSIONS).
Key Functions:
validate_files()- Checks file count, size, and extensionsconvert_to_webp()- Converts images usingimagecratecreate_zip()- Creates compressed archives usingzipcrateprocess_files()- Main entry point orchestrating the workflow
uploader.rs - R2 Upload
Location: src-tauri/src/uploader.rs
Handles Cloudflare R2 uploads with retry logic:
Upload Flow:
- Read file data from disk
- Generate unique key:
u/{uuid}_{filename}.{ext} - Create S3-compatible bucket handle
- Upload with exponential backoff retry (up to 3 attempts)
- Return public URL
upload_to_r2()- Main upload with retry logicvalidate_r2_credentials()- Tests credentials by uploading test objectdelete_from_r2()- Removes objects from bucketis_transient_error()- Determines if error is worth retrying
Frontend Components
App.tsx - Main Component
Location: src/App.tsx
The single-page React app includes:
- Drop zone - File drag-and-drop interface
- Upload history - List of recent uploads with actions
- Settings panel - R2 configuration form
- Demo mode toggle - Switch between local and cloud storage
Key Dependencies
Rust Dependencies (Cargo.toml)
Frontend Dependencies (package.json)
macOS Integration
Vibrancy Effect
ZipDrop uses native macOS vibrancy for a translucent, frosted-glass effect:Tray Icon
The menu bar icon uses a template image for automatic dark/light mode support:Keychain Access
Credentials are stored using thekeyring crate with native macOS Keychain integration:
Next Steps
Getting Started
Set up your development environment
Building
Create production builds and distribution packages