audio streaming app plyr.fm
38
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: consolidate docs folders under docs/ (#1247)

move docs/, docs-internal/, and docs-site/ into a single docs/ umbrella
(docs/public, docs/internal, docs/site) so documentation lives in one place.

- update deploy-docs workflow paths + build/deploy commands
- recreate astro content symlink (docs/site/src/content/docs -> ../../../public)
- update root justfile, docs/site/justfile api-ref recipe
- fix loq.toml paths (3 entries were already stale from a prior move)
- update github links in public docs (artists/listeners/contributing)
- update skill files and STATUS.md references
- verified astro build still produces 43 pages

authored by

nate nowack and committed by
GitHub
1bd999e1 9543fe7a

+31 -31
+1 -1
.claude/skills/check-spans/SKILL.md
··· 3 3 argument-hint: [your question about what happened] 4 4 --- 5 5 6 - First read the Logfire documentation: @docs-internal/tools/logfire.md 6 + First read the Logfire documentation: @docs/internal/tools/logfire.md 7 7 8 8 Investigate: $ARGUMENTS 9 9
+2 -2
.claude/skills/contribute/SKILL.md
··· 15 15 - `CLAUDE.md` — project rules, stack, structure, conventions 16 16 - `STATUS.md` — active tasks and known issues 17 17 - `backend/.env.example` — all environment variables with comments 18 - - `docs-internal/local-development/setup.md` — full local dev walkthrough 18 + - `docs/internal/local-development/setup.md` — full local dev walkthrough 19 19 20 20 check [open issues](https://github.com/zzstoatzz/plyr.fm/issues) for things to work on. 21 21 ··· 29 29 # edit backend/.env — DATABASE_URL is required, see the file for details 30 30 ``` 31 31 32 - if you need to run the full stack locally, read `docs-internal/local-development/setup.md`. for frontend-only changes you may not need the backend running at all. 32 + if you need to run the full stack locally, read `docs/internal/local-development/setup.md`. for frontend-only changes you may not need the backend running at all. 33 33 34 34 ## step 3: make your change 35 35
+5 -5
.claude/skills/screenshot-docs/SKILL.md
··· 40 40 4. **snapshot**: `take_snapshot()` to get accessibility tree with element UIDs 41 41 5. **interact** (if needed): `click(uid)` / `fill(uid, value)` to reach the target state 42 42 6. **capture**: `take_screenshot(filePath, uid, fullPage, format, quality)` — use `format: "png"` 43 - 7. **save to**: `docs-site/public/screenshots/{name}.png` 43 + 7. **save to**: `docs/site/public/screenshots/{name}.png` 44 44 8. **review**: `open -a Preview <path>` and ask the user if framing looks right before committing 45 45 46 46 ### auth handling ··· 73 73 ![description](/screenshots/filename.png) 74 74 ``` 75 75 76 - the `docs-site/public/` directory is served at the root, so `/screenshots/` resolves correctly. 76 + the `docs/site/public/` directory is served at the root, so `/screenshots/` resolves correctly. 77 77 78 78 ## example session 79 79 ··· 86 86 3. wait_for(["sign in"]) 87 87 4. click(login_button_uid) 88 88 5. wait_for(["handle"]) 89 - 6. take_screenshot({ filePath: "docs-site/public/screenshots/login-page.png" }) 89 + 6. take_screenshot({ filePath: "docs/site/public/screenshots/login-page.png" }) 90 90 7. Read the image file to self-review framing 91 91 8. open -a Preview <path> and ask user to confirm 92 92 ``` ··· 136 136 ```bash 137 137 uv run --with Pillow python3 -c " 138 138 from PIL import Image 139 - img = Image.open('docs-site/public/screenshots/name.png') 139 + img = Image.open('docs/site/public/screenshots/name.png') 140 140 cropped = img.crop((0, 0, img.width, TARGET_HEIGHT)) # top-anchored crop 141 - cropped.save('docs-site/public/screenshots/name.png') 141 + cropped.save('docs/site/public/screenshots/name.png') 142 142 " 143 143 ``` 144 144
+4 -4
.github/workflows/deploy-docs.yml
··· 5 5 branches: 6 6 - main 7 7 paths: 8 - - "docs/**" 9 - - "docs-site/**" 8 + - "docs/public/**" 9 + - "docs/site/**" 10 10 - ".github/workflows/deploy-docs.yml" 11 11 workflow_dispatch: 12 12 ··· 24 24 - uses: oven-sh/setup-bun@v2 25 25 26 26 - name: build 27 - run: cd docs-site && bun install && bun run build 27 + run: cd docs/site && bun install && bun run build 28 28 29 29 - name: deploy to cloudflare pages 30 30 uses: cloudflare/wrangler-action@v3 31 31 with: 32 32 apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} 33 33 accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} 34 - command: pages deploy docs-site/dist --project-name plyr-fm-docs --branch main 34 + command: pages deploy docs/site/dist --project-name plyr-fm-docs --branch main
+1 -1
STATUS.md
··· 319 319 ## documentation 320 320 321 321 - **public docs**: [docs.plyr.fm](https://docs.plyr.fm) — for listeners, artists, developers, and contributors 322 - - **internal docs**: [docs-internal/](docs-internal/) — deployment, auth internals, runbooks, moderation 322 + - **internal docs**: [docs/internal/](docs/internal/) — deployment, auth internals, runbooks, moderation 323 323 - **lexicons**: [docs.plyr.fm/lexicons/overview](https://docs.plyr.fm/lexicons/overview/) — ATProto record schemas 324 324 325 325 ---
docs-internal/CLAUDE.md docs/internal/CLAUDE.md
docs-internal/README.md docs/internal/README.md
docs-internal/architecture/jams-queue-integration.md docs/internal/architecture/jams-queue-integration.md
docs-internal/architecture/jams-transport-decision.md docs/internal/architecture/jams-transport-decision.md
docs-internal/architecture/jams.md docs/internal/architecture/jams.md
docs-internal/authentication.md docs/internal/authentication.md
docs-internal/backend/atproto-identity.md docs/internal/backend/atproto-identity.md
docs-internal/backend/background-tasks.md docs/internal/backend/background-tasks.md
docs-internal/backend/configuration.md docs/internal/backend/configuration.md
docs-internal/backend/database/connection-pooling.md docs/internal/backend/database/connection-pooling.md
docs-internal/backend/database/neon.md docs/internal/backend/database/neon.md
docs-internal/backend/feature-flags.md docs/internal/backend/feature-flags.md
docs-internal/backend/genre-classification.md docs/internal/backend/genre-classification.md
docs-internal/backend/image-formats.md docs/internal/backend/image-formats.md
docs-internal/backend/liked-tracks.md docs/internal/backend/liked-tracks.md
docs-internal/backend/mood-search.md docs/internal/backend/mood-search.md
docs-internal/backend/playlist-recommendations.md docs/internal/backend/playlist-recommendations.md
docs-internal/backend/streaming-uploads.md docs/internal/backend/streaming-uploads.md
docs-internal/backend/transcoder.md docs/internal/backend/transcoder.md
docs-internal/content-gating-roadmap.md docs/internal/content-gating-roadmap.md
docs-internal/deployment/database-migrations.md docs/internal/deployment/database-migrations.md
+3 -3
docs-internal/deployment/environments.md docs/internal/deployment/environments.md
··· 116 116 **plyr-fm-docs**: 117 117 - framework: astro (starlight) 118 118 - deployed via GHA workflow (`.github/workflows/deploy-docs.yml`) using `wrangler pages deploy` 119 - - triggers on push to `main` when `docs/**` or `docs-site/**` change 120 - - build command: `cd docs-site && bun install && bun run build` 121 - - build output: `docs-site/dist` 119 + - triggers on push to `main` when `docs/public/**` or `docs/site/**` change 120 + - build command: `cd docs/site && bun install && bun run build` 121 + - build output: `docs/site/dist` 122 122 - custom domain: `docs.plyr.fm` 123 123 124 124 ### secrets management
docs-internal/frontend/data-loading.md docs/internal/frontend/data-loading.md
docs-internal/frontend/design-tokens.md docs/internal/frontend/design-tokens.md
docs-internal/frontend/keyboard-shortcuts.md docs/internal/frontend/keyboard-shortcuts.md
docs-internal/frontend/navigation.md docs/internal/frontend/navigation.md
docs-internal/frontend/portals.md docs/internal/frontend/portals.md
docs-internal/frontend/queue.md docs/internal/frontend/queue.md
docs-internal/frontend/redirect-after-login.md docs/internal/frontend/redirect-after-login.md
docs-internal/frontend/search.md docs/internal/frontend/search.md
docs-internal/frontend/state-management.md docs/internal/frontend/state-management.md
docs-internal/frontend/toast-notifications.md docs/internal/frontend/toast-notifications.md
docs-internal/legal/meetings/2026-01-02-notes.md docs/internal/legal/meetings/2026-01-02-notes.md
docs-internal/legal/meetings/2026-01-03-initial.md docs/internal/legal/meetings/2026-01-03-initial.md
docs-internal/legal/questions.md docs/internal/legal/questions.md
docs-internal/local-development/setup.md docs/internal/local-development/setup.md
docs-internal/moderation/atproto-labeler.md docs/internal/moderation/atproto-labeler.md
docs-internal/moderation/copyright-detection.md docs/internal/moderation/copyright-detection.md
docs-internal/moderation/overview.md docs/internal/moderation/overview.md
docs-internal/moderation/sensitive-content.md docs/internal/moderation/sensitive-content.md
docs-internal/offboarding.md docs/internal/offboarding.md
docs-internal/plans/.gitkeep docs/internal/plans/.gitkeep
docs-internal/rate-limiting.md docs/internal/rate-limiting.md
docs-internal/research/.gitkeep docs/internal/research/.gitkeep
docs-internal/research/2025-12-18-moderation-cleanup.md docs/internal/research/2025-12-18-moderation-cleanup.md
docs-internal/research/2025-12-19-beartype.md docs/internal/research/2025-12-19-beartype.md
docs-internal/research/2025-12-19-ios-share-extension-minimal-app.md docs/internal/research/2025-12-19-ios-share-extension-minimal-app.md
docs-internal/research/2025-12-19-web-share-target-ios-pwa.md docs/internal/research/2025-12-19-web-share-target-ios-pwa.md
docs-internal/research/2025-12-20-atprotofans-paywall-integration.md docs/internal/research/2025-12-20-atprotofans-paywall-integration.md
docs-internal/research/2025-12-20-moderation-architecture-overhaul.md docs/internal/research/2025-12-20-moderation-architecture-overhaul.md
docs-internal/research/2025-12-20-supporter-gated-content-architecture.md docs/internal/research/2025-12-20-supporter-gated-content-architecture.md
docs-internal/research/2026-01-01-atproto-oauth-permission-sets.md docs/internal/research/2026-01-01-atproto-oauth-permission-sets.md
docs-internal/research/2026-01-03-multi-account-experience.md docs/internal/research/2026-01-03-multi-account-experience.md
docs-internal/research/2026-01-29-atproto-media-service-patterns.md docs/internal/research/2026-01-29-atproto-media-service-patterns.md
docs-internal/research/2026-01-29-pds-blob-storage.md docs/internal/research/2026-01-29-pds-blob-storage.md
docs-internal/research/2026-02-28-redirect-after-login-ux.md docs/internal/research/2026-02-28-redirect-after-login-ux.md
docs-internal/runbooks/README.md docs/internal/runbooks/README.md
docs-internal/runbooks/connection-pool-exhaustion.md docs/internal/runbooks/connection-pool-exhaustion.md
docs-internal/security.md docs/internal/security.md
docs-internal/testing/README.md docs/internal/testing/README.md
docs-internal/testing/integration-tests.md docs/internal/testing/integration-tests.md
docs-internal/tools/logfire-client-traffic-dashboard.sql docs/internal/tools/logfire-client-traffic-dashboard.sql
docs-internal/tools/logfire-database-dashboard.sql docs/internal/tools/logfire-database-dashboard.sql
docs-internal/tools/logfire.md docs/internal/tools/logfire.md
docs-internal/tools/neon.md docs/internal/tools/neon.md
docs-internal/tools/pdsx.md docs/internal/tools/pdsx.md
docs-internal/tools/plyrfm.md docs/internal/tools/plyrfm.md
docs-internal/tools/skills.md docs/internal/tools/skills.md
docs-internal/tools/status-maintenance.md docs/internal/tools/status-maintenance.md
docs-internal/tools/tap.md docs/internal/tools/tap.md
docs-site/astro.config.mjs docs/site/astro.config.mjs
docs-site/bun.lockb docs/site/bun.lockb
+4 -4
docs-site/justfile docs/site/justfile
··· 18 18 19 19 # regenerate API reference from backend source 20 20 api-ref: 21 - rm -rf ../docs/developers/api-reference 22 - cd ../backend && uv run --with mdxify mdxify \ 21 + rm -rf ../public/developers/api-reference 22 + cd ../../backend && uv run --with mdxify mdxify \ 23 23 --all \ 24 24 --root-module backend.api \ 25 25 --format md \ 26 - --output-dir ../docs/developers/api-reference \ 26 + --output-dir ../docs/public/developers/api-reference \ 27 27 --no-update-nav \ 28 28 --exclude backend.api.tracks.services \ 29 29 --exclude backend.api.tracks.constants \ ··· 31 31 --exclude backend.api.migration \ 32 32 --exclude backend.api.pds_backfill 33 33 # strip backend-api- prefix, nest tracks subpackage 34 - cd ../docs/developers/api-reference && \ 34 + cd ../public/developers/api-reference && \ 35 35 for f in backend-api-*.md; do mv "$f" "${f#backend-api-}"; done && \ 36 36 mkdir -p tracks && \ 37 37 for f in tracks-*.md; do mv "$f" "tracks/${f#tracks-}"; done && \
docs-site/package.json docs/site/package.json
docs-site/public/favicon.png docs/site/public/favicon.png
docs-site/public/llms-full.txt docs/site/public/llms-full.txt
docs-site/public/llms.txt docs/site/public/llms.txt
docs-site/public/og.png docs/site/public/og.png
docs-site/public/screenshots/feed-track-card.png docs/site/public/screenshots/feed-track-card.png
docs-site/public/screenshots/landing-page.png docs/site/public/screenshots/landing-page.png
docs-site/public/screenshots/login-page.png docs/site/public/screenshots/login-page.png
docs-site/public/screenshots/portal-dashboard.png docs/site/public/screenshots/portal-dashboard.png
docs-site/public/screenshots/portal-track-editor.png docs/site/public/screenshots/portal-track-editor.png
docs-site/public/screenshots/search-overlay.png docs/site/public/screenshots/search-overlay.png
docs-site/public/screenshots/track-actions-menu.png docs/site/public/screenshots/track-actions-menu.png
docs-site/public/screenshots/upload-form.png docs/site/public/screenshots/upload-form.png
docs-site/src/components/HeroWaveform.astro docs/site/src/components/HeroWaveform.astro
docs-site/src/components/SocialIcons.astro docs/site/src/components/SocialIcons.astro
docs-site/src/components/Stats.astro docs/site/src/components/Stats.astro
docs-site/src/components/TrackSearch.astro docs/site/src/components/TrackSearch.astro
docs-site/src/components/TrendingTracks.astro docs/site/src/components/TrendingTracks.astro
docs-site/src/content.config.ts docs/site/src/content.config.ts
-1
docs-site/src/content/docs
··· 1 - ../../../docs
docs-site/src/styles/custom.css docs/site/src/styles/custom.css
docs-site/tsconfig.json docs/site/tsconfig.json
docs-site/wrangler.toml docs/site/wrangler.toml
+2 -2
docs/artists.md docs/public/artists.md
··· 35 35 36 36 ![the track editor — title, description, album, tags, artwork, and suggested tags](/screenshots/portal-track-editor.png) 37 37 38 - <span id="auto-tagging"></span>when you add tags, you can opt in to **auto-tag with recommended genres** — plyr.fm runs [ML genre classification](https://github.com/zzstoatzz/plyr.fm/blob/main/docs-internal/backend/genre-classification.md) on the audio using the [effnet-discogs](https://replicate.com/mtg/effnet-discogs) model and suggests tags automatically. you can accept, remove, or add your own. auto-suggested tags typically appear within a few seconds of upload. 38 + <span id="auto-tagging"></span>when you add tags, you can opt in to **auto-tag with recommended genres** — plyr.fm runs [ML genre classification](https://github.com/zzstoatzz/plyr.fm/blob/main/docs/internal/backend/genre-classification.md) on the audio using the [effnet-discogs](https://replicate.com/mtg/effnet-discogs) model and suggests tags automatically. you can accept, remove, or add your own. auto-suggested tags typically appear within a few seconds of upload. 39 39 40 40 5. **see it live** — your track is playable immediately and indexed for discovery 41 41 6. **embed it** — copy the embed code to put a player on your website or blog (see [embeds](#embeds) below) ··· 130 130 131 131 ## leaving 132 132 133 - you can leave plyr.fm at any time. download your tracks as a ZIP from the [portal](https://plyr.fm/portal), then delete your account — this removes all data from plyr.fm's infrastructure. your atproto records stay on your PDS by default, but you can choose to delete those too. for the full technical details, see the [offboarding documentation](https://github.com/zzstoatzz/plyr.fm/blob/main/docs-internal/offboarding.md). 133 + you can leave plyr.fm at any time. download your tracks as a ZIP from the [portal](https://plyr.fm/portal), then delete your account — this removes all data from plyr.fm's infrastructure. your atproto records stay on your PDS by default, but you can choose to delete those too. for the full technical details, see the [offboarding documentation](https://github.com/zzstoatzz/plyr.fm/blob/main/docs/internal/offboarding.md).
+2 -2
docs/contributing.md docs/public/contributing.md
··· 59 59 just frontend run 60 60 ``` 61 61 62 - the backend needs a Postgres connection. you can use the [Neon](https://neon.tech) dev instance or a local Postgres — set `DATABASE_URL` in your `.env`. see [`backend/.env.example`](https://github.com/zzstoatzz/plyr.fm/blob/main/backend/.env.example) for all configuration options and the [local development setup guide](https://github.com/zzstoatzz/plyr.fm/blob/main/docs-internal/local-development/setup.md) for detailed walkthrough. 62 + the backend needs a Postgres connection. you can use the [Neon](https://neon.tech) dev instance or a local Postgres — set `DATABASE_URL` in your `.env`. see [`backend/.env.example`](https://github.com/zzstoatzz/plyr.fm/blob/main/backend/.env.example) for all configuration options and the [local development setup guide](https://github.com/zzstoatzz/plyr.fm/blob/main/docs/internal/local-development/setup.md) for detailed walkthrough. 63 63 64 64 ## workflow 65 65 ··· 89 89 - use `uv` for Python (never `pip`) 90 90 - add regression tests when fixing bugs 91 91 92 - detailed internal documentation (environment setup, deployment, architecture) is in [`docs-internal/`](https://github.com/zzstoatzz/plyr.fm/tree/main/docs-internal). 92 + detailed internal documentation (environment setup, deployment, architecture) is in [`docs/internal/`](https://github.com/zzstoatzz/plyr.fm/tree/main/docs/internal).
docs/developers/api-reference/account.md docs/public/developers/api-reference/account.md
docs/developers/api-reference/activity.md docs/public/developers/api-reference/activity.md
docs/developers/api-reference/albums.md docs/public/developers/api-reference/albums.md
docs/developers/api-reference/artists.md docs/public/developers/api-reference/artists.md
docs/developers/api-reference/audio.md docs/public/developers/api-reference/audio.md
docs/developers/api-reference/auth.md docs/public/developers/api-reference/auth.md
docs/developers/api-reference/discover.md docs/public/developers/api-reference/discover.md
docs/developers/api-reference/exports.md docs/public/developers/api-reference/exports.md
docs/developers/api-reference/feeds.md docs/public/developers/api-reference/feeds.md
docs/developers/api-reference/jams.md docs/public/developers/api-reference/jams.md
docs/developers/api-reference/lists.md docs/public/developers/api-reference/lists.md
docs/developers/api-reference/meta.md docs/public/developers/api-reference/meta.md
docs/developers/api-reference/moderation.md docs/public/developers/api-reference/moderation.md
docs/developers/api-reference/now_playing.md docs/public/developers/api-reference/now_playing.md
docs/developers/api-reference/oembed.md docs/public/developers/api-reference/oembed.md
docs/developers/api-reference/preferences.md docs/public/developers/api-reference/preferences.md
docs/developers/api-reference/queue.md docs/public/developers/api-reference/queue.md
docs/developers/api-reference/search.md docs/public/developers/api-reference/search.md
docs/developers/api-reference/stats.md docs/public/developers/api-reference/stats.md
docs/developers/api-reference/tracks/comments.md docs/public/developers/api-reference/tracks/comments.md
docs/developers/api-reference/tracks/likes.md docs/public/developers/api-reference/tracks/likes.md
docs/developers/api-reference/tracks/listing.md docs/public/developers/api-reference/tracks/listing.md
docs/developers/api-reference/tracks/metadata_service.md docs/public/developers/api-reference/tracks/metadata_service.md
docs/developers/api-reference/tracks/mutations.md docs/public/developers/api-reference/tracks/mutations.md
docs/developers/api-reference/tracks/overview.md docs/public/developers/api-reference/tracks/overview.md
docs/developers/api-reference/tracks/playback.md docs/public/developers/api-reference/tracks/playback.md
docs/developers/api-reference/tracks/shares.md docs/public/developers/api-reference/tracks/shares.md
docs/developers/api-reference/tracks/tags.md docs/public/developers/api-reference/tracks/tags.md
docs/developers/api-reference/tracks/uploads.md docs/public/developers/api-reference/tracks/uploads.md
docs/developers/api-reference/users.md docs/public/developers/api-reference/users.md
docs/developers/auth.md docs/public/developers/auth.md
docs/developers/index.md docs/public/developers/index.md
docs/developers/quickstart.md docs/public/developers/quickstart.md
docs/glossary.md docs/public/glossary.md
docs/index.mdx docs/public/index.mdx
docs/legal/privacy.md docs/public/legal/privacy.md
docs/legal/terms.md docs/public/legal/terms.md
docs/lexicons/overview.md docs/public/lexicons/overview.md
+1 -1
docs/listeners.md docs/public/listeners.md
··· 68 68 69 69 ## leaving 70 70 71 - you can leave anytime (we're sad to see you go 😢). to delete your account and all your data from plyr.fm, go to the [portal](https://plyr.fm/portal) and click "delete account". for full detail on what gets deleted, see the [offboarding documentation](https://github.com/zzstoatzz/plyr.fm/blob/main/docs-internal/offboarding.md). 71 + you can leave anytime (we're sad to see you go 😢). to delete your account and all your data from plyr.fm, go to the [portal](https://plyr.fm/portal) and click "delete account". for full detail on what gets deleted, see the [offboarding documentation](https://github.com/zzstoatzz/plyr.fm/blob/main/docs/internal/offboarding.md). 72 72 73 73 ## even after you leave 74 74
+1
docs/site/src/content/docs
··· 1 + ../../../public
docs/troubleshooting.md docs/public/troubleshooting.md
+1 -1
justfile
··· 3 3 mod backend 4 4 mod transcoder 'services/transcoder' 5 5 mod moderation 'services/moderation' 6 - mod docs 'docs-site' 6 + mod docs 'docs/site' 7 7 8 8 9 9 # show available commands
+4 -4
loq.toml
··· 87 87 max_lines = 715 88 88 89 89 [[rules]] 90 - path = "docs-internal/authentication.md" 90 + path = "docs/internal/authentication.md" 91 91 max_lines = 631 92 92 93 93 [[rules]] 94 - path = "docs/backend/liked-tracks.md" 94 + path = "docs/internal/backend/liked-tracks.md" 95 95 max_lines = 507 96 96 97 97 [[rules]] 98 - path = "docs/deployment/database-migrations.md" 98 + path = "docs/internal/deployment/database-migrations.md" 99 99 max_lines = 633 100 100 101 101 [[rules]] 102 - path = "docs/tools/neon.md" 102 + path = "docs/internal/tools/neon.md" 103 103 max_lines = 523 104 104 105 105 [[rules]]