7.8 KiB
7.8 KiB
Architecture Documentation
Overview
Downlink is a Next.js application that provides a web interface for downloading YouTube videos and audio files. The application uses server-side processing with yt-dlp and provides a modern, responsive UI built with shadcn/ui.
System Architecture
┌─────────────┐
│ Browser │
│ (Client) │
└──────┬──────┘
│ HTTP Requests
▼
┌─────────────────────────────────┐
│ Next.js App Router │
│ ┌───────────────────────────┐ │
│ │ UI Components (React) │ │
│ └───────────────────────────┘ │
│ ┌───────────────────────────┐ │
│ │ API Routes │ │
│ │ - /api/info │ │
│ │ - /api/download │ │
│ └───────────┬───────────────┘ │
└──────────────┼──────────────────┘
│
▼
┌─────────────────────────────────┐
│ Business Logic Layer │
│ ┌───────────────────────────┐ │
│ │ lib/youtube.ts │ │
│ │ - getVideoInfo() │ │
│ │ - downloadVideo() │ │
│ └───────────┬───────────────┘ │
└──────────────┼──────────────────┘
│
▼
┌─────────────────────────────────┐
│ External Tools │
│ ┌───────────────────────────┐ │
│ │ yt-dlp (Python) │ │
│ │ - Video download │ │
│ │ - Format conversion │ │
│ └───────────────────────────┘ │
│ ┌───────────────────────────┐ │
│ │ ffmpeg (via yt-dlp) │ │
│ │ - Audio transcoding │ │
│ └───────────────────────────┘ │
└─────────────────────────────────┘
Component Structure
Frontend Components
app/page.tsx
Main page component containing:
- URL input field
- Video information display
- Format selection (video/audio)
- Download button
- Error handling and success states
UI Components (components/ui/)
shadcn/ui components:
button.tsx: Button componentinput.tsx: Input field componentcard.tsx: Card container componentlabel.tsx: Form label componentselect.tsx: Dropdown select component
Backend Components
API Routes
app/api/info/route.ts
- Handles POST requests for video information
- Validates YouTube URL
- Calls
getVideoInfo()fromlib/youtube.ts - Returns video metadata
app/api/download/route.ts
- Handles POST requests for downloads
- Validates request body (url, format, formatType)
- Calls
downloadVideo()fromlib/youtube.ts - Returns download URL and file information
Business Logic
lib/youtube.ts
Core functionality:
getVideoInfo(url): Fetches video metadata using yt-dlpdownloadVideo(request): Downloads and processes video/audioensureDirectories(): Creates necessary directoriessanitizeFilename(): Sanitizes filenames for safe storage
lib/types.ts
Centralized TypeScript type definitions:
VideoFormat,AudioFormat: Format type unionsDownloadRequest,DownloadResponse: API request/response typesVideoInfo,FormatOption: Video metadata types
lib/utils.ts
Utility functions:
cn(): Tailwind class name mergerisValidYouTubeUrl(): URL validationextractYouTubeId(): Extract video ID from URL
Data Flow
Video Information Flow
- User enters YouTube URL and clicks "Get Info"
- Frontend sends POST request to
/api/info - API route validates URL and calls
getVideoInfo() getVideoInfo()executesyt-dlp --dump-json- JSON response is parsed and formatted
- Video info (title, thumbnail, duration) returned to frontend
- Frontend displays video information
Download Flow
- User selects format and clicks "Download"
- Frontend sends POST request to
/api/download - API route validates request and calls
downloadVideo() downloadVideo():- Generates unique file ID
- Constructs yt-dlp command based on format
- Executes download command
- Moves file to
/public/downloads/ - Returns download URL
- Frontend receives download URL
- User can download file via provided link
File Storage
Directory Structure
Downlink/
├── downloads/ # Temporary storage (gitignored)
│ └── [fileId].[ext] # Downloaded files before processing
├── public/
│ └── downloads/ # Public downloads (gitignored)
│ └── [fileId].[ext] # Final files served to users
File Naming
- Format:
[timestamp]-[randomId].[extension] - Example:
1234567890-abc123.mp4 - Prevents filename conflicts
- Timestamp enables cleanup of old files
Dependencies
Runtime Dependencies
- next: Next.js framework
- react: React library
- react-dom: React DOM rendering
- lucide-react: Icon library
- @radix-ui/*: UI component primitives
- tailwind-merge: Tailwind class merging
- clsx: Conditional class names
System Dependencies
- yt-dlp: Python-based YouTube downloader
- ffmpeg: Media conversion tool (used by yt-dlp)
Development Dependencies
- typescript: TypeScript compiler
- tailwindcss: CSS framework
- eslint: Code linting
Security Considerations
Current Implementation
- URL validation to ensure YouTube URLs only
- Filename sanitization to prevent directory traversal
- Server-side processing (no client-side download logic)
Recommended Enhancements
- Rate limiting to prevent abuse
- File size limits
- User authentication/authorization
- Download quotas per user/IP
- Automatic file cleanup
- CORS configuration
- Input sanitization for all user inputs
Performance Considerations
Current Limitations
- Synchronous file operations (could block for large files)
- No progress tracking during downloads
- Files stored in memory during copy operations
- No caching of video information
Optimization Opportunities
- Stream large files instead of loading into memory
- Implement download progress tracking
- Cache video metadata
- Use background jobs for long-running downloads
- Implement CDN for file serving
- Add database for download history
Deployment Considerations
Requirements
- Node.js 18+ runtime
- Python 3.6+ (for yt-dlp)
- ffmpeg installed on server
- Sufficient disk space for downloads
- Network access to YouTube
Environment Variables
Currently none required, but consider:
MAX_FILE_SIZE: Maximum file size limitCLEANUP_INTERVAL: File cleanup scheduleALLOWED_DOMAINS: Allowed video platformsSTORAGE_PATH: Custom storage location
Scaling Considerations
- Stateless API design (can scale horizontally)
- File storage should be shared (S3, etc.) for multi-instance deployments
- Consider message queue for download processing
- Implement caching layer for video metadata