feat: add atprotofans support link mode (#562)
* feat: add atprotofans support link mode
adds three support link modes for artist profiles:
- none: no support link displayed
- atprotofans: links to atprotofans.com/profile/{handle}
- custom: user-provided https:// URL (existing behavior)
backend:
- validate support_url accepts 'atprotofans' magic value
- reject non-https URLs for custom links
- add tests for all three modes
frontend:
- portal page: radio button selector for support link mode
- artist profile: compute actual URL from mode + handle
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: validate atprotofans eligibility before selection
checks user's PDS for com.atprotofans.profile/self record with
acceptingSupporters=true before allowing atprotofans selection.
- client-side check on portal load (no backend sprawl)
- shows "set up" link when not eligible
- shows "ready" when eligible
- disables option when ineligible
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: use ATProto SDK for proper handle/PDS resolution
- add @atproto/api SDK to frontend for proper ATProto operations
- fix portal atprotofans eligibility check to resolve DID to PDS first
- fix backend handles.py to use AsyncIdResolver instead of bsky.social
- fix frontend error.svelte to use SDK for handle resolution
the issue was hardcoded bsky.social URLs which don't work for users
on self-hosted PDS instances. now we properly resolve DIDs via
plc.directory and query the user's actual PDS.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: show 'profile ready' as link to atprotofans profile
when eligible, the status now shows "profile ready" as a clickable
link to the user's actual atprotofans profile page.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: correct atprotofans URL to use /u/{did} not /profile/{handle}
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
authored by
This is a binary file and will not be displayed.