1# local development setup 2 3## prerequisites 4 5- **python**: 3.11+ (managed via `uv`) 6- **node/bun**: for frontend development 7- **postgres**: local database (optional - can use neon dev instance) 8- **ffmpeg**: for transcoder development (optional) 9 10## quick start 11 12```bash 13# clone repository 14gh repo clone zzstoatzz/plyr.fm 15cd plyr.fm 16 17# install python dependencies 18uv sync 19 20# install frontend dependencies 21cd frontend && bun install && cd .. 22 23# copy environment template 24cp .env.example .env 25# edit .env with your credentials 26 27# run backend 28uv run uvicorn backend.main:app --reload --host 0.0.0.0 --port 8001 29 30# run frontend (separate terminal) 31cd frontend && bun run dev 32``` 33 34visit http://localhost:5173 to see the app. 35 36## environment configuration 37 38### required environment variables 39 40create a `.env` file in the project root: 41 42```bash 43# database (use neon dev instance or local postgres) 44DATABASE_URL=postgresql+asyncpg://localhost/plyr # local 45# DATABASE_URL=<neon-dev-connection-string> # neon dev 46 47# oauth (uses client metadata discovery - no registration required) 48ATPROTO_CLIENT_ID=http://localhost:8001/oauth-client-metadata.json 49ATPROTO_CLIENT_SECRET=<your-client-secret> 50ATPROTO_REDIRECT_URI=http://localhost:5173/auth/callback 51OAUTH_ENCRYPTION_KEY=<base64-encoded-32-byte-key> 52 53# storage (r2 or filesystem) 54STORAGE_BACKEND=filesystem # or "r2" for cloudflare r2 55R2_BUCKET=audio-dev 56R2_PRIVATE_BUCKET=audio-private-dev # for supporter-gated content 57R2_IMAGE_BUCKET=images-dev 58R2_ENDPOINT_URL=<your-r2-endpoint> 59R2_PUBLIC_BUCKET_URL=<your-r2-public-url> 60R2_PUBLIC_IMAGE_BUCKET_URL=<your-r2-image-public-url> 61AWS_ACCESS_KEY_ID=<your-r2-access-key> 62AWS_SECRET_ACCESS_KEY=<your-r2-secret> 63 64# optional: observability 65LOGFIRE_ENABLED=false # set to true to enable 66LOGFIRE_WRITE_TOKEN=<your-token> 67LOGFIRE_ENVIRONMENT=development 68 69# optional: notifications 70NOTIFY_ENABLED=false 71``` 72 73### generating oauth encryption key 74 75```bash 76python -c "import base64, os; print(base64.b64encode(os.urandom(32)).decode())" 77``` 78 79## database setup 80 81### option 1: use neon dev instance (recommended) 82 831. get dev database URL from neon console or `.env.example` 842. set `DATABASE_URL` in `.env` 853. run migrations: `uv run alembic upgrade head` 86 87### option 2: local postgres 88 89```bash 90# install postgres 91brew install postgresql@15 # macos 92# or use docker 93 94# create database 95createdb plyr 96 97# run migrations 98DATABASE_URL=postgresql+asyncpg://localhost/plyr uv run alembic upgrade head 99``` 100 101## running services 102 103### backend 104 105```bash 106# standard run 107uv run uvicorn backend.main:app --reload 108 109# with custom port 110uv run uvicorn backend.main:app --reload --port 8001 111 112# with host binding (for mobile testing) 113uv run uvicorn backend.main:app --reload --host 0.0.0.0 --port 8001 114``` 115 116backend api docs: http://localhost:8001/docs 117 118### frontend 119 120```bash 121cd frontend 122 123# development server 124bun run dev 125 126# custom port 127PORT=5174 bun run dev 128 129# expose to network (for mobile testing) 130bun run dev -- --host 131``` 132 133frontend: http://localhost:5173 134 135### transcoder (optional) 136 137```bash 138cd transcoder 139 140# install rust toolchain if needed 141rustup update 142 143# install ffmpeg 144brew install ffmpeg # macos 145 146# run transcoder 147cargo run 148 149# with custom port 150TRANSCODER_PORT=9000 cargo run 151 152# with debug logging 153RUST_LOG=debug cargo run 154``` 155 156transcoder: http://localhost:8080 157 158## development workflow 159 160### making backend changes 161 1621. edit code in `src/backend/` 1632. uvicorn auto-reloads on file changes 1643. test endpoints at http://localhost:8001/docs 1654. check logs in terminal 166 167### making frontend changes 168 1691. edit code in `frontend/src/` 1702. vite auto-reloads on file changes 1713. view changes at http://localhost:5173 1724. check console for errors 173 174### creating database migrations 175 176```bash 177# make model changes in src/backend/models/ 178 179# generate migration 180uv run alembic revision --autogenerate -m "description" 181 182# review generated migration in alembic/versions/ 183 184# apply migration 185uv run alembic upgrade head 186 187# test downgrade 188uv run alembic downgrade -1 189uv run alembic upgrade head 190``` 191 192see [database-migrations.md](../deployment/database-migrations.md) for details. 193 194### running tests 195 196```bash 197# all tests 198uv run pytest 199 200# specific test file 201uv run pytest tests/api/test_tracks.py 202 203# with verbose output 204uv run pytest -v 205 206# with coverage 207uv run pytest --cov=backend 208 209# watch mode (re-run on changes) 210uv run pytest-watch 211``` 212 213## mobile testing 214 215to test on mobile devices on your local network: 216 217### 1. find your local ip 218 219```bash 220# macos/linux 221ifconfig | grep "inet " | grep -v 127.0.0.1 222 223# windows 224ipconfig 225``` 226 227### 2. run backend with host binding 228 229```bash 230uv run uvicorn backend.main:app --reload --host 0.0.0.0 --port 8001 231``` 232 233### 3. run frontend with network exposure 234 235```bash 236cd frontend && bun run dev -- --host 237``` 238 239### 4. access from mobile 240 241- backend: http://<your-ip>:8001 242- frontend: http://<your-ip>:5173 243 244## troubleshooting 245 246### backend won't start 247 248**symptoms**: `ModuleNotFoundError` or import errors 249 250**solutions**: 251```bash 252# reinstall dependencies 253uv sync 254 255# check python version 256uv run python --version # should be 3.11+ 257 258# verify environment 259uv run python -c "from backend.main import app; print('ok')" 260``` 261 262### database connection errors 263 264**symptoms**: `could not connect to server` or SSL errors 265 266**solutions**: 267```bash 268# verify DATABASE_URL is set 269echo $DATABASE_URL 270 271# test connection 272uv run python -c "from backend.config import settings; print(settings.database.url)" 273 274# check postgres is running (if local) 275pg_isready 276 277# verify neon credentials (if remote) 278# check neon console for connection string 279``` 280 281### frontend build errors 282 283**symptoms**: `module not found` or dependency errors 284 285**solutions**: 286```bash 287# reinstall dependencies 288cd frontend && rm -rf node_modules && bun install 289 290# clear cache 291rm -rf frontend/.svelte-kit 292 293# check node version 294node --version # should be 18+ 295bun --version 296``` 297 298### oauth redirect errors 299 300**symptoms**: `invalid redirect_uri` or callback errors 301 302**solutions**: 303```bash 304# verify ATPROTO_REDIRECT_URI matches frontend URL 305# should be: http://localhost:5173/auth/callback 306 307# check ATPROTO_CLIENT_ID is accessible (should return client metadata JSON) 308curl http://localhost:8001/oauth-client-metadata.json 309``` 310 311### r2 upload failures 312 313**symptoms**: `failed to upload to R2` or storage errors 314 315**solutions**: 316```bash 317# verify credentials 318echo $AWS_ACCESS_KEY_ID 319echo $AWS_SECRET_ACCESS_KEY 320echo $R2_BUCKET 321 322# test r2 connectivity 323uv run python -c " 324from backend.storage import get_storage_backend 325storage = get_storage_backend() 326print(storage.bucket_name) 327" 328 329# or use filesystem backend for local development 330STORAGE_BACKEND=filesystem uv run uvicorn backend.main:app --reload 331``` 332 333## useful commands 334 335```bash 336# backend 337uv run uvicorn backend.main:app --reload # start backend 338uv run pytest # run tests 339uv run alembic upgrade head # run migrations 340uv run python -m backend.utilities.cli # admin cli 341 342# frontend 343cd frontend && bun run dev # start frontend 344cd frontend && bun run build # build for production 345cd frontend && bun run preview # preview production build 346cd frontend && bun run check # type check 347 348# transcoder 349cd transcoder && cargo run # start transcoder 350cd transcoder && cargo test # run tests 351cd transcoder && cargo build --release # build for production 352``` 353 354## next steps 355 356- read [backend/configuration.md](../backend/configuration.md) for config details 357- read [frontend/state-management.md](../frontend/state-management.md) for frontend patterns 358- read [tools/](../tools/) for development tools (logfire, neon, pdsx) 359- check [deployment/](../deployment/) when ready to deploy