music on atproto
plyr.fm
1# [plyr.fm](https://plyr.fm)
2
3music on [atproto](https://atproto.com)
4
5check the [plyr.fm artist page](https://plyr.fm/u/plyr.fm) for the latest [auto-generated](.github/workflows/status-maintenance.yml) development podcast!
6
7<details>
8<summary>tech stack</summary>
9
10### backend
11- **framework**: [FastAPI](https://fastapi.tiangolo.com)
12- **database**: [Neon PostgreSQL](https://neon.com)
13- **storage**: [Cloudflare R2](https://developers.cloudflare.com/r2/)
14- **hosting**: [Fly.io](https://fly.io)
15- **auth**: [atproto OAuth 2.1](https://atproto.com/specs/oauth) ([fork with OAuth implementation](https://github.com/zzstoatzz/atproto))
16
17### frontend
18- **framework**: [SvelteKit](https://kit.svelte.dev)
19- **runtime**: [Bun](https://bun.sh)
20- **hosting**: [Cloudflare Pages](https://pages.cloudflare.com)
21- **styling**: vanilla CSS (lowercase aesthetic)
22
23</details>
24
25<details>
26<summary>local development</summary>
27
28### prerequisites
29
30- [uv](https://docs.astral.sh/uv/) for Python package management
31- [bun](https://bun.sh/) for frontend development
32- [just](https://github.com/casey/just) for task running (recommended)
33
34### quick start
35
36using [just](https://github.com/casey/just):
37
38```bash
39# install dependencies (uv handles backend venv automatically)
40uv sync # For root-level deps, if any, and initializes uv
41just frontend install
42
43# run backend (hot reloads at http://localhost:8001)
44just backend run
45
46# run frontend (hot reloads at http://localhost:5173)
47just frontend dev
48
49# run transcoder (hot reloads at http://localhost:8082)
50just transcoder run
51```
52
53</details>
54
55<details>
56<summary>features</summary>
57
58### listening
59- audio playback with persistent queue across tabs/devices
60- like tracks with counts visible to all listeners
61- browse artist profiles and discographies
62- share tracks and albums with nice link previews
63
64### creating
65- well-scoped OAuth authentication via ATProto (bluesky accounts)
66- upload tracks with title, artwork, and featured artists
67- organize tracks into albums with cover art
68- edit metadata and replace artwork anytime
69- track play counts and like analytics
70- publish ATProto track and like records to your PDS
71
72</details>
73
74
75<details>
76<summary>project structure</summary>
77
78```
79plyr.fm/
80├── backend/ # FastAPI app & Python tooling
81│ ├── src/backend/ # application code
82│ │ ├── api/ # public endpoints
83│ │ ├── _internal/ # internal services
84│ │ ├── models/ # database schemas
85│ │ └── storage/ # storage adapters
86│ ├── tests/ # pytest suite
87│ └── alembic/ # database migrations
88├── frontend/ # SvelteKit app
89│ ├── src/lib/ # components & state
90│ └── src/routes/ # pages
91├── transcoder/ # Rust audio service
92├── docs/ # documentation
93└── justfile # task runner
94```
95
96</details>
97
98<details>
99<summary>costs</summary>
100
101~$35-40/month:
102- fly.io backend (production): ~$5/month (shared-cpu-1x, 256MB RAM)
103- fly.io backend (staging): ~$5/month (shared-cpu-1x, 256MB RAM)
104- fly.io transcoder: ~$0-5/month (auto-scales to zero when idle)
105- neon postgres: $5/month (starter plan)
106- audd audio fingerprinting: ~$10/month (enterprise API for copyright detection)
107- cloudflare pages: free (frontend hosting)
108- cloudflare r2: ~$0.16/month (6 buckets across dev/staging/prod)
109
110</details>
111
112## links
113
114- **production**: https://plyr.fm
115- **API docs**: https://api.plyr.fm/docs
116- **python SDK / MCP server**: [plyrfm](https://github.com/zzstoatzz/plyr-python-client) ([PyPI](https://pypi.org/project/plyrfm/))
117- **repository**: https://github.com/zzstoatzz/plyr.fm
118
119## documentation
120
121- [deployment guide](docs/deployment/environments.md)
122- [configuration](docs/backend/configuration.md)
123- [full documentation](docs/README.md)