# AGENTS.md - AI/LLM Context Guide This document provides context for AI agents and LLMs to understand and work with the YouMusic project effectively. ## Project Overview **YouMusic** is a modern, full-stack web music player with download capabilities. It allows users to search, download, and play music from YouTube and Bilibili, manage playlists, and share music links. ### Technology Stack - **Backend**: Python 3.13, FastAPI, SQLAlchemy (async), yt-dlp, mutagen, uv (package manager) - **Frontend**: React 18, TypeScript, Vite, TanStack Query, shadcn/ui, Tailwind CSS - **Database**: SQLite with aiosqlite (async driver) - **Deployment**: Docker Compose, or local development scripts ### Project Type - Full-stack web application - Single-page application (SPA) - REST API backend - Mobile-first responsive design - Single-user, no authentication ## Architecture ### Backend (FastAPI) ``` backend/ ├── main.py # Entry point, FastAPI app initialization └── app/ ├── api/ # REST API endpoints │ ├── music.py # Music CRUD operations │ ├── playlist.py # Playlist management │ ├── download.py # Download from YouTube/Bilibili │ └── search.py # Search online sources ├── core/ │ └── config.py # Settings using Pydantic ├── db/ │ └── session.py # SQLAlchemy async setup ├── models/ │ └── models.py # Music, Playlist, associations ├── schemas/ │ └── schemas.py # Pydantic request/response models └── services/ ├── downloader.py # yt-dlp music download logic └── search.py # YouTube/Bilibili search ``` **Key Backend Concepts:** - Async/await throughout for performance - Background tasks for downloads - RESTful API design - Auto-generated OpenAPI/Swagger docs at `/docs` - CORS enabled for frontend communication ### Frontend (React) ``` frontend/src/ ├── main.tsx # React app entry, providers ├── App.tsx # Main app, routing, player state ├── components/ │ ├── ui/ # shadcn/ui components │ ├── player/ # Music player │ ├── search/ # Search interface │ └── playlist/ # Playlist management ├── api/ │ └── client.ts # Axios API client ├── lib/ │ └── utils.ts # Helper functions └── types/ └── index.ts # TypeScript interfaces ``` **Key Frontend Concepts:** - Component-based architecture - TanStack Query for server state - React Router for navigation - shadcn/ui for accessible components - Mobile-first responsive design - Hot module replacement (HMR) in dev ## Database Schema **⚠️ IMPORTANT: Database Migrations** This project uses **Alembic** for database migrations. When modifying database schema: 1. Never delete the database in production 2. Always create migrations: `cd backend && ./migrate.sh create "description"` 3. Review the generated migration in `alembic/versions/` 4. Apply with: `./migrate.sh upgrade` 5. See [MIGRATIONS.md](MIGRATIONS.md) for complete guide Migrations run automatically on app startup, so existing deployments will auto-upgrade. ### Tables **music** - `id`: Primary key - `title`: Song name - `artist`: Artist/singer name (nullable) - `album`: Album name (nullable) - `duration`: Length in seconds (nullable) - `file_path`: Relative path to audio file - `file_size`: File size in bytes - `source_url`: Original download URL (nullable) - `source_type`: "youtube", "bilibili", "local", "upload" - `thumbnail`: Image URL (nullable) - `lyrics`: Song lyrics (nullable) - `created_at`, `updated_at`: Timestamps **playlists** - `id`: Primary key - `name`: Playlist name (unique) - `description`: Playlist description (nullable) - `thumbnail`: Playlist image (nullable) - `created_at`, `updated_at`: Timestamps **playlist_music** (Many-to-Many) - `playlist_id`: Foreign key to playlists - `music_id`: Foreign key to music - `position`: Order in playlist - `added_at`: Timestamp ### Relationships - One playlist has many music items - One music item can be in many playlists ## API Endpoints ### Music API (`/api/music/`) - `GET /` - List all music - `GET /search?q={query}` - Search local library - `GET /{id}` - Get music by ID - `GET /artist/{name}` - Get all music by artist - `PUT /{id}` - Update metadata - `DELETE /{id}` - Delete music and file - `POST /upload` - Upload music file - `POST /scan` - Scan directory for new files ### Playlist API (`/api/playlists/`) - `GET /` - List all playlists - `POST /` - Create playlist - `GET /{id}` - Get playlist with songs - `GET /name/{name}` - Get playlist by name - `PUT /{id}` - Update playlist - `DELETE /{id}` - Delete playlist - `POST /{id}/music/{music_id}` - Add song - `DELETE /{id}/music/{music_id}` - Remove song ### Download API (`/api/download/`) - `POST /music` - Download single track (background task) - `POST /playlist` - Download entire playlist (background task) - `GET /status` - Download queue status ### Search API (`/api/search/`) - `GET /?q={query}&source={all|youtube|bilibili}` - Search online - `GET /youtube?q={query}` - Search YouTube only - `GET /bilibili?q={query}` - Search Bilibili only ## Core Features ### 1. Music Download (from xiaomusic) The download logic is adapted from [xiaomusic](https://github.com/hanxi/xiaomusic) using `yt-dlp`: ```python # Core download command yt-dlp --no-playlist -x --audio-format mp3 \ --audio-quality 0 --paths {music_dir} \ -o "{title}.%(ext)s" {url} ``` **Supported sources:** - YouTube videos and playlists - Bilibili videos - Any site supported by yt-dlp ### 2. Music Player - HTML5 audio element - Play/pause, skip forward/back - Volume control with mute - Progress bar with seeking - Auto-play next in queue - Display current track info ### 3. Search - **Local**: SQLAlchemy LIKE queries on title/artist - **Online**: yt-dlp JSON dump for YouTube, Bilibili API for Bilibili - Combined results with thumbnails - Artist-based filtering ### 4. Playlists - Create, read, update, delete - Add/remove songs - Play entire playlist - Maintain song order ### 5. Music Sharing - Share via URL: `/?music={id}` - Auto-load and play shared music - Deep linking support ## Development Modes ### Local Development (Fastest) ```bash ./dev-setup.sh # First time ./dev.sh # Daily development ./dev-stop.sh # Stop servers ``` **Ports:** - Frontend: http://localhost:3000 (Vite dev server) - Backend: http://localhost:8000 (uvicorn with reload) **Features:** - Hot reload for both frontend and backend - Instant file changes - Native performance - Logs in `logs/` directory ### Docker Deployment ```bash docker-compose up -d ``` **Ports:** - Combined app: http://localhost:8000 (frontend served by backend) ## File Conventions ### Backend - **Naming**: `snake_case` for files, functions, variables - **Async**: All I/O operations use `async`/`await` - **Type hints**: All functions have type hints - **Imports**: Absolute imports from `app.` ### Frontend - **Naming**: `PascalCase` for components, `camelCase` for functions/variables - **Files**: `.tsx` for components, `.ts` for utilities - **Exports**: Named exports preferred - **Hooks**: Custom hooks in `hooks/` directory ### API Communication - All endpoints return JSON - Error responses follow FastAPI conventions - Request/response validated by Pydantic schemas - CORS enabled for cross-origin requests ## Common Tasks for AI Agents ### Adding a New API Endpoint 1. **Create endpoint in `backend/app/api/`** ```python @router.get("/new-endpoint") async def new_endpoint(db: AsyncSession = Depends(get_db)): # Implementation pass ``` 2. **Add to router in `backend/main.py`** ```python app.include_router(new_router, prefix="/api/new", tags=["new"]) ``` 3. **Add API client function in `frontend/src/api/client.ts`** ```typescript export const newApi = { getItems: () => api.get('/new-endpoint'), } ``` 4. **Use in component with TanStack Query** ```typescript const { data } = useQuery({ queryKey: ['new-items'], queryFn: async () => { const response = await newApi.getItems() return response.data } }) ``` ### Adding a New UI Component 1. **Create component in `frontend/src/components/`** ```typescript export default function NewComponent({ prop }: Props) { return