initial commit
This commit is contained in:
223
docs/architecture.md
Normal file
223
docs/architecture.md
Normal file
@@ -0,0 +1,223 @@
|
||||
# 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 component
|
||||
- `input.tsx`: Input field component
|
||||
- `card.tsx`: Card container component
|
||||
- `label.tsx`: Form label component
|
||||
- `select.tsx`: Dropdown select component
|
||||
|
||||
### Backend Components
|
||||
|
||||
#### API Routes
|
||||
|
||||
**`app/api/info/route.ts`**
|
||||
- Handles POST requests for video information
|
||||
- Validates YouTube URL
|
||||
- Calls `getVideoInfo()` from `lib/youtube.ts`
|
||||
- Returns video metadata
|
||||
|
||||
**`app/api/download/route.ts`**
|
||||
- Handles POST requests for downloads
|
||||
- Validates request body (url, format, formatType)
|
||||
- Calls `downloadVideo()` from `lib/youtube.ts`
|
||||
- Returns download URL and file information
|
||||
|
||||
#### Business Logic
|
||||
|
||||
**`lib/youtube.ts`**
|
||||
Core functionality:
|
||||
- `getVideoInfo(url)`: Fetches video metadata using yt-dlp
|
||||
- `downloadVideo(request)`: Downloads and processes video/audio
|
||||
- `ensureDirectories()`: Creates necessary directories
|
||||
- `sanitizeFilename()`: Sanitizes filenames for safe storage
|
||||
|
||||
**`lib/types.ts`**
|
||||
Centralized TypeScript type definitions:
|
||||
- `VideoFormat`, `AudioFormat`: Format type unions
|
||||
- `DownloadRequest`, `DownloadResponse`: API request/response types
|
||||
- `VideoInfo`, `FormatOption`: Video metadata types
|
||||
|
||||
**`lib/utils.ts`**
|
||||
Utility functions:
|
||||
- `cn()`: Tailwind class name merger
|
||||
- `isValidYouTubeUrl()`: URL validation
|
||||
- `extractYouTubeId()`: Extract video ID from URL
|
||||
|
||||
## Data Flow
|
||||
|
||||
### Video Information Flow
|
||||
1. User enters YouTube URL and clicks "Get Info"
|
||||
2. Frontend sends POST request to `/api/info`
|
||||
3. API route validates URL and calls `getVideoInfo()`
|
||||
4. `getVideoInfo()` executes `yt-dlp --dump-json`
|
||||
5. JSON response is parsed and formatted
|
||||
6. Video info (title, thumbnail, duration) returned to frontend
|
||||
7. Frontend displays video information
|
||||
|
||||
### Download Flow
|
||||
1. User selects format and clicks "Download"
|
||||
2. Frontend sends POST request to `/api/download`
|
||||
3. API route validates request and calls `downloadVideo()`
|
||||
4. `downloadVideo()`:
|
||||
- Generates unique file ID
|
||||
- Constructs yt-dlp command based on format
|
||||
- Executes download command
|
||||
- Moves file to `/public/downloads/`
|
||||
- Returns download URL
|
||||
5. Frontend receives download URL
|
||||
6. 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 limit
|
||||
- `CLEANUP_INTERVAL`: File cleanup schedule
|
||||
- `ALLOWED_DOMAINS`: Allowed video platforms
|
||||
- `STORAGE_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
|
||||
Reference in New Issue
Block a user