mirror of
https://github.com/wahyd4/you-music.git
synced 2026-08-08 20:59:47 +10:00
563 lines
15 KiB
Markdown
563 lines
15 KiB
Markdown
# 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 <div>...</div>
|
|
}
|
|
```
|
|
|
|
2. **Use shadcn/ui components** from `@/components/ui/`
|
|
3. **Add to routing in `App.tsx`** if needed
|
|
4. **Use Tailwind for styling**
|
|
|
|
### Modifying Database Schema
|
|
|
|
**IMPORTANT: We use Alembic for database migrations. Never delete the database in production!**
|
|
|
|
1. **Update model in `backend/app/models/models.py`**
|
|
```python
|
|
class Music(Base):
|
|
# ... existing fields ...
|
|
new_field: Mapped[Optional[str]] = mapped_column(String, nullable=True)
|
|
```
|
|
|
|
2. **Create migration**
|
|
```bash
|
|
cd backend
|
|
./migrate.sh create "Add new_field to music table"
|
|
```
|
|
|
|
3. **Review generated migration** in `backend/alembic/versions/*.py`
|
|
- Check auto-generated SQL is correct
|
|
- Edit if needed (e.g., for renaming columns, data migrations)
|
|
|
|
4. **Apply migration**
|
|
```bash
|
|
./migrate.sh upgrade
|
|
```
|
|
|
|
5. **Update schema in `backend/app/schemas/schemas.py`** if needed
|
|
|
|
**Notes:**
|
|
- Migrations run automatically on app startup
|
|
- Never edit applied migrations - create new ones
|
|
- Use `./migrate.sh downgrade` to rollback if needed
|
|
- See [MIGRATIONS.md](MIGRATIONS.md) for complete guide
|
|
|
|
### Adding Download Source
|
|
|
|
1. **Check yt-dlp support** (most sites already supported)
|
|
2. **Add search function** in `backend/app/services/search.py`
|
|
3. **Update search endpoint** in `backend/app/api/search.py`
|
|
4. **Add UI** in `frontend/src/components/search/SearchPage.tsx`
|
|
|
|
## Environment Variables
|
|
|
|
### Backend (.env)
|
|
```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)
|
|
```env
|
|
VITE_API_URL=http://localhost:8000
|
|
```
|
|
|
|
## Testing
|
|
|
|
### Backend
|
|
```bash
|
|
cd backend
|
|
pytest
|
|
```
|
|
|
|
### Frontend
|
|
```bash
|
|
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 framework
|
|
- `uvicorn` - ASGI server
|
|
- `sqlalchemy` - ORM
|
|
- `aiosqlite` - Async SQLite driver
|
|
- `alembic` - Database migrations
|
|
- `yt-dlp` - Universal downloader
|
|
- `mutagen` - Audio metadata
|
|
- `pydantic` - Data validation
|
|
|
|
### Key Frontend Packages
|
|
- `react` - UI library
|
|
- `@tanstack/react-query` - Data fetching
|
|
- `react-router-dom` - Routing
|
|
- `axios` - HTTP client
|
|
- `tailwindcss` - Styling
|
|
- `lucide-react` - Icons
|
|
|
|
## Code Patterns
|
|
|
|
### Backend Async Pattern
|
|
```python
|
|
async def get_items(db: AsyncSession = Depends(get_db)):
|
|
result = await db.execute(select(Model))
|
|
items = result.scalars().all()
|
|
return items
|
|
```
|
|
|
|
### Frontend Query Pattern
|
|
```typescript
|
|
const { data, isLoading } = useQuery({
|
|
queryKey: ['items'],
|
|
queryFn: async () => {
|
|
const response = await api.get('/items')
|
|
return response.data
|
|
}
|
|
})
|
|
```
|
|
|
|
### Error Handling
|
|
```python
|
|
# 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 sync`
|
|
- Frontend: `npm install`
|
|
|
|
### "Port already in use"
|
|
```bash
|
|
lsof -ti:8000 | xargs kill -9 # Backend
|
|
lsof -ti:3000 | xargs kill -9 # Frontend
|
|
```
|
|
|
|
### "FFmpeg not found"
|
|
```bash
|
|
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
|
|
1. Check if dependencies are already installed
|
|
2. Follow existing code patterns
|
|
3. Update both backend and frontend if needed
|
|
4. Add type hints/types
|
|
5. Test the feature
|
|
6. Update relevant documentation
|
|
|
|
### When Debugging
|
|
1. Check logs first
|
|
2. Verify dependencies are installed
|
|
3. Ensure servers are running
|
|
4. Test API endpoints separately
|
|
5. Check browser console
|
|
|
|
### When Refactoring
|
|
1. Don't break existing features
|
|
2. Maintain async patterns
|
|
3. Keep type safety
|
|
4. Update tests if they exist
|
|
5. 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
|
|
|
|
1. **Simplicity** - Easy to understand and modify
|
|
2. **Performance** - Fast response times, efficient queries
|
|
3. **Maintainability** - Clear structure, good documentation
|
|
4. **Mobile-First** - Responsive design, touch-friendly
|
|
5. **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.
|
|
|
|
No need to create summary doc after made changes
|