14 KiB
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
Tables
music
id: Primary keytitle: Song nameartist: Artist/singer name (nullable)album: Album name (nullable)duration: Length in seconds (nullable)file_path: Relative path to audio filefile_size: File size in bytessource_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 keyname: 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 playlistsmusic_id: Foreign key to musicposition: Order in playlistadded_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 musicGET /search?q={query}- Search local libraryGET /{id}- Get music by IDGET /artist/{name}- Get all music by artistPUT /{id}- Update metadataDELETE /{id}- Delete music and filePOST /upload- Upload music filePOST /scan- Scan directory for new files
Playlist API (/api/playlists/)
GET /- List all playlistsPOST /- Create playlistGET /{id}- Get playlist with songsGET /name/{name}- Get playlist by namePUT /{id}- Update playlistDELETE /{id}- Delete playlistPOST /{id}/music/{music_id}- Add songDELETE /{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 onlineGET /youtube?q={query}- Search YouTube onlyGET /bilibili?q={query}- Search Bilibili only
Core Features
1. Music Download (from xiaomusic)
The download logic is adapted from xiaomusic using yt-dlp:
# 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)
./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
docker-compose up -d
Ports:
- Combined app: http://localhost:8000 (frontend served by backend)
File Conventions
Backend
- Naming:
snake_casefor 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:
PascalCasefor components,camelCasefor functions/variables - Files:
.tsxfor components,.tsfor 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
-
Create endpoint in
backend/app/api/@router.get("/new-endpoint") async def new_endpoint(db: AsyncSession = Depends(get_db)): # Implementation pass -
Add to router in
backend/main.pyapp.include_router(new_router, prefix="/api/new", tags=["new"]) -
Add API client function in
frontend/src/api/client.tsexport const newApi = { getItems: () => api.get('/new-endpoint'), } -
Use in component with TanStack Query
const { data } = useQuery({ queryKey: ['new-items'], queryFn: async () => { const response = await newApi.getItems() return response.data } })
Adding a New UI Component
-
Create component in
frontend/src/components/export default function NewComponent({ prop }: Props) { return <div>...</div> } -
Use shadcn/ui components from
@/components/ui/ -
Add to routing in
App.tsxif needed -
Use Tailwind for styling
Modifying Database Schema
- Update model in
backend/app/models/models.py - Update schema in
backend/app/schemas/schemas.py - Delete database
rm data/youmusic.db(recreates on restart) - Restart backend to create new schema
Adding Download Source
- Check yt-dlp support (most sites already supported)
- Add search function in
backend/app/services/search.py - Update search endpoint in
backend/app/api/search.py - Add UI in
frontend/src/components/search/SearchPage.tsx
Environment Variables
Backend (.env)
DATABASE_URL=sqlite+aiosqlite:///./data/youmusic.db
MUSIC_DIR=./data/music
UPLOAD_DIR=./data/uploads
TEMP_DIR=./data/temp
FFMPEG_LOCATION=ffmpeg
PROXY=http://proxy:port # Optional
Frontend (.env)
VITE_API_URL=http://localhost:8000
Testing
Backend
cd backend
pytest
Frontend
cd frontend
npm test
API Testing
- Visit http://localhost:8000/docs for interactive testing
- Use curl, Postman, or Thunder Client
Dependencies
Key Backend Packages
fastapi- Web frameworkuvicorn- ASGI serversqlalchemy- ORMaiosqlite- Async SQLite driveryt-dlp- Universal downloadermutagen- Audio metadatapydantic- Data validation
Key Frontend Packages
react- UI library@tanstack/react-query- Data fetchingreact-router-dom- Routingaxios- HTTP clienttailwindcss- Stylinglucide-react- Icons
Code Patterns
Backend Async Pattern
async def get_items(db: AsyncSession = Depends(get_db)):
result = await db.execute(select(Model))
items = result.scalars().all()
return items
Frontend Query Pattern
const { data, isLoading } = useQuery({
queryKey: ['items'],
queryFn: async () => {
const response = await api.get('/items')
return response.data
}
})
Error Handling
# Backend
raise HTTPException(status_code=404, detail="Not found")
# Frontend
try {
await api.call()
toast.success('Success!')
} catch (error) {
toast.error('Failed!')
}
Performance Considerations
Backend
- Use async for all I/O operations
- Background tasks for long-running downloads
- Database indexes on frequently queried fields
- Limit query results with pagination
Frontend
- Lazy load components
- Use TanStack Query caching
- Debounce search inputs
- Optimize images
Security
Backend
- Input validation via Pydantic
- SQL injection protection via SQLAlchemy
- Path traversal protection in file operations
- CORS configuration
Frontend
- XSS protection via React
- No eval() or dangerouslySetInnerHTML
- Sanitize user inputs
- Secure URL parsing
Debugging
Backend
- Check logs:
tail -f logs/backend.log - Use print statements (shown in logs)
- FastAPI auto-reloads on code changes
- Test in browser: http://localhost:8000/docs
Frontend
- Check logs:
tail -f logs/frontend.log - Browser console for errors
- React DevTools for component inspection
- Network tab for API calls
Common Errors
"Module not found"
- Backend: Activate .venv,
uv pip install -r requirements.txt - Frontend:
npm install
"Port already in use"
lsof -ti:8000 | xargs kill -9 # Backend
lsof -ti:3000 | xargs kill -9 # Frontend
"FFmpeg not found"
brew install ffmpeg # macOS
sudo apt-get install ffmpeg # Ubuntu
"Database locked"
- Only one process can write at a time
- Restart backend:
./dev-stop.sh && ./dev.sh
AI Agent Guidelines
When Adding Features
- Check if dependencies are already installed
- Follow existing code patterns
- Update both backend and frontend if needed
- Add type hints/types
- Test the feature
- Update relevant documentation
When Debugging
- Check logs first
- Verify dependencies are installed
- Ensure servers are running
- Test API endpoints separately
- Check browser console
When Refactoring
- Don't break existing features
- Maintain async patterns
- Keep type safety
- Update tests if they exist
- Follow project conventions
Code Style
- Backend: Follow PEP 8, use async/await
- Frontend: Use TypeScript, functional components
- Both: Clear variable names, comments for complex logic
Project Goals
- Simplicity - Easy to understand and modify
- Performance - Fast response times, efficient queries
- Maintainability - Clear structure, good documentation
- Mobile-First - Responsive design, touch-friendly
- Single-User - No authentication complexity
Related Projects
- xiaomusic: Inspired download logic and yt-dlp usage
- spotube: UI/UX design inspiration
- shadcn/ui: Component library
- yt-dlp: Download engine
Resources
- FastAPI docs: https://fastapi.tiangolo.com
- React docs: https://react.dev
- yt-dlp: https://github.com/yt-dlp/yt-dlp
- shadcn/ui: https://ui.shadcn.com
- TanStack Query: https://tanstack.com/query
Version Information
- Current Version: 1.0.0
- Python: 3.13
- uv: Latest
- Node.js: 18+
- React: 18.3.1
- FastAPI: 0.115.0
License
MIT License - Free to use and modify
For AI Agents: This project is well-structured, fully typed, and follows modern best practices. Feel free to suggest improvements, add features, or refactor code while maintaining the existing patterns and architecture.