Conversational AI music artist recommendations.
  • Python 51.2%
  • TypeScript 43.5%
  • Dockerfile 2.3%
  • JavaScript 2.2%
  • HTML 0.7%
Find a file
2026-04-08 09:30:37 -04:00
alembic Rewrite Findarr as a conversational AI music discovery app 2026-04-07 23:55:08 -04:00
app Rewrite Findarr as a conversational AI music discovery app 2026-04-07 23:55:08 -04:00
frontend Rewrite Findarr as a conversational AI music discovery app 2026-04-07 23:55:08 -04:00
nginx Rewrite Findarr as a conversational AI music discovery app 2026-04-07 23:55:08 -04:00
.env.example Rewrite Findarr as a conversational AI music discovery app 2026-04-07 23:55:08 -04:00
.gitignore Add node_modules and frontend/dist to .gitignore 2026-04-07 23:58:04 -04:00
.python-version Initial project scaffold for Findarr 2026-04-05 11:49:24 -04:00
alembic.ini Initial project scaffold for Findarr 2026-04-05 11:49:24 -04:00
CLAUDE.md Rewrite Findarr as a conversational AI music discovery app 2026-04-07 23:55:08 -04:00
docker-compose.yml Change frontend port to prevent local collision 2026-04-08 09:30:37 -04:00
Dockerfile Fix Docker build errors 2026-04-05 19:26:00 -04:00
LICENSE Initial project scaffold for Findarr 2026-04-05 11:49:24 -04:00
pyproject.toml Rewrite Findarr as a conversational AI music discovery app 2026-04-07 23:55:08 -04:00
README.md Rewrite Findarr as a conversational AI music discovery app 2026-04-07 23:55:08 -04:00
uv.lock Rewrite Findarr as a conversational AI music discovery app 2026-04-07 23:55:08 -04:00

Findarr

A self-hosted AI music discovery app. Chat with Claude to find artists you'll love — based on your taste, not charts.

How it works

Findarr is a split-pane chat interface: describe the music you love on the left, and artist suggestions appear as cards on the right. As you chat and react to suggestions, a taste profile builds up and informs future recommendations.

  • Conversational discovery — the AI asks questions, learns your taste, and suggests artists when you're ready
  • Artist cards — each suggestion shows genre tags, a one-sentence explanation, and links to Spotify, YouTube, Last.fm, and Bandcamp
  • Feedback buttons — Like, Dislike, Meh, Already Have, or flag a suggestion as non-existent; each response updates your taste profile and prompts a follow-up
  • Taste profile — a live prose summary of your musical preferences, updated automatically as the conversation develops
  • Pluggable mode architecture — Similar Artists is the first mode; new discovery modes slot in without changing core logic

Requirements

  • Python 3.12+ with uv
  • Node.js 22+ (frontend dev only)
  • An Anthropic API key
  • Docker + Docker Compose (for containerised deployment)

Quick Start (Docker)

cp .env.example .env
# Edit .env — set ANTHROPIC_API_KEY and SECRET_KEY
docker compose up -d

The app is available at http://localhost:8088.

Development Setup

# Install Python dependencies
uv sync

# Copy and configure environment
cp .env.example .env  # set ANTHROPIC_API_KEY

# Start the backend (auto-reload on :8000)
uv run uvicorn app.main:app --reload

# In a second terminal — start the frontend dev server (on :5173)
cd frontend
npm install
npm run dev

Open http://localhost:5173.

Environment Variables

Variable Default Description
DATABASE_URL sqlite+aiosqlite:///./findarr.db SQLite path or postgresql+asyncpg://… DSN
ANTHROPIC_API_KEY Required. Claude API key
SECRET_KEY Random secret for encrypting stored credentials (future use)
LASTFM_API_KEY Optional. Enables artist images on cards
LOG_LEVEL info debug, info, warning, or error

Project Structure

app/
├── main.py              # FastAPI app, lifespan, route registration
├── config.py            # Pydantic settings
├── database.py          # SQLAlchemy async engine
├── api/
│   ├── chat.py          # POST /chat → SSE stream
│   ├── feedback.py      # POST /feedback
│   └── taste_profile.py # GET /taste-profile
├── ai/
│   ├── client.py        # Anthropic async client
│   ├── tools.py         # suggest_artists + update_taste_profile tool schemas
│   └── prompts.py       # System prompt builder
├── modes/
│   ├── base.py          # Abstract ChatMode
│   ├── registry.py      # Mode registry
│   └── similar_artists.py
├── models/
│   └── taste_profile.py # Singleton DB model
├── schemas/             # Pydantic request/response types
└── taste/
    ├── profile.py       # DB helpers
    └── updater.py       # Feedback → profile mutations

frontend/src/
├── api/                 # Typed API client + shared types
├── components/
│   ├── artists/         # ArtistGrid, ArtistCard, FeedbackButtons, ListeningLinks
│   ├── chat/            # ChatPane, MessageBubble, ChatInput
│   ├── layout/          # SplitPane
│   └── taste-profile/   # TasteProfileDrawer
└── hooks/               # useChat (SSE), useTasteProfile

Adding a New Mode

  1. Create app/modes/your_mode.py — subclass ChatMode, set mode_id, display_name, description, and implement system_instructions
  2. Register it in app/modes/registry.py
  3. Pass mode: "your_mode_id" in the chat request from the frontend

License

MIT — see LICENSE.