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