Files
you-music/AGENTS.md

15 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

⚠️ 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 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 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
  • 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:

Features:

  • Hot reload for both frontend and backend
  • Instant file changes
  • Native performance
  • Logs in logs/ directory

Docker Deployment

docker-compose up -d

Ports:

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/

    @router.get("/new-endpoint")
    async def new_endpoint(db: AsyncSession = Depends(get_db)):
        # Implementation
        pass
    
  2. Add to router in backend/main.py

    app.include_router(new_router, prefix="/api/new", tags=["new"])
    
  3. Add API client function in frontend/src/api/client.ts

    export const newApi = {
      getItems: () => api.get('/new-endpoint'),
    }
    
  4. 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

  1. Create component in frontend/src/components/

    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

    class Music(Base):
        # ... existing fields ...
        new_field: Mapped[Optional[str]] = mapped_column(String, nullable=True)
    
  2. Create migration

    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

    ./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 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)

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

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

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 sync
  • 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

  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
  • xiaomusic: Inspired download logic and yt-dlp usage
  • spotube: UI/UX design inspiration
  • shadcn/ui: Component library
  • yt-dlp: Download engine

Resources

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