Summary
Share to Bluesky (shipped in v0.5.0, #33) renders on the self-hosted Rex app, but a real publish only completes when the instance is reached at http://127.0.0.1:3000. A self-hoster hitting their box at its real address (LAN IP, Tailscale hostname, a reverse-proxied domain) can't complete OAuth sign-in.
Why
The publish feature is entirely client-side (browser → PDS); the Rust backend is not involved. The OAuth client_id is chosen by origin in packages/shared/src/contexts/BlueskyAuth.tsx:
| Origin |
client_id |
Real publish |
127.0.0.1 / [::1] |
spec loopback client |
✅ |
localhost |
— (warns, bails; spec requires 127.0.0.1) |
❌ |
| any other origin |
falls back to hosted https://pantryhost.app/client-metadata.json |
❌ redirect_uri mismatch |
The hosted client metadata's redirect_uris list only pantryhost.app / my.pantryhost.app, so the AT authorization server rejects a redirect back to a self-hosted address.
There's a getProdClientId() override, but it only reaches the browser via VITE_ATPROTO_CLIENT_ID at build time (Tier 1's Vite build). The Rex/app path reads process.env.ATPROTO_CLIENT_ID, which Rex does not inline into the client bundle — the same limitation that forced the dry-run flag onto a <meta> channel in _document.tsx.
What it would take (no Rust)
- A runtime channel so
ATPROTO_CLIENT_ID reaches the Rex client — a <meta name="atproto-client-id"> tag in packages/app/pages/_document.tsx, mirroring the atproto-publish-dry-run fix; getProdClientId() reads it browser-side.
- The self-hoster serves their own
client-metadata.json at a public HTTPS URL whose redirect_uris include their instance's callback (AT OAuth requires the client_id to be a publicly-resolvable HTTPS document). Needs docs + ideally a helper to generate the metadata.
Until then, document that self-hosted publishing works via http://127.0.0.1:3000 on the box itself, and defaults to safe dry-run everywhere else.
Related
Cross-device publish-state reconcile: #36
Summary
Share to Bluesky (shipped in v0.5.0, #33) renders on the self-hosted Rex app, but a real publish only completes when the instance is reached at
http://127.0.0.1:3000. A self-hoster hitting their box at its real address (LAN IP, Tailscale hostname, a reverse-proxied domain) can't complete OAuth sign-in.Why
The publish feature is entirely client-side (browser → PDS); the Rust backend is not involved. The OAuth
client_idis chosen by origin inpackages/shared/src/contexts/BlueskyAuth.tsx:127.0.0.1/[::1]localhosthttps://pantryhost.app/client-metadata.jsonThe hosted client metadata's
redirect_urislist onlypantryhost.app/my.pantryhost.app, so the AT authorization server rejects a redirect back to a self-hosted address.There's a
getProdClientId()override, but it only reaches the browser viaVITE_ATPROTO_CLIENT_IDat build time (Tier 1's Vite build). The Rex/app path readsprocess.env.ATPROTO_CLIENT_ID, which Rex does not inline into the client bundle — the same limitation that forced the dry-run flag onto a<meta>channel in_document.tsx.What it would take (no Rust)
ATPROTO_CLIENT_IDreaches the Rex client — a<meta name="atproto-client-id">tag inpackages/app/pages/_document.tsx, mirroring theatproto-publish-dry-runfix;getProdClientId()reads it browser-side.client-metadata.jsonat a public HTTPS URL whoseredirect_urisinclude their instance's callback (AT OAuth requires theclient_idto be a publicly-resolvable HTTPS document). Needs docs + ideally a helper to generate the metadata.Until then, document that self-hosted publishing works via
http://127.0.0.1:3000on the box itself, and defaults to safe dry-run everywhere else.Related
Cross-device publish-state reconcile: #36