commits
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
fetch statuses first and get handle from actorHandle field,
eliminating PLC lookup for users with existing statuses.
falls back to PLC lookup only for new users with no statuses.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
quickslice provides actorHandle directly in the query response,
eliminating the need for parallel resolveDidToHandle calls on
every feed item.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
instead of showing "clears now" for already-expired statuses, now
displays "expired", "expired Xm ago", "expired Xh ago", or "expired Xd ago"
depending on how long ago the status expired.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
quickslice rewrite replaces the custom rust backend.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
rewrite: quickslice backend + cloudflare pages frontend
- build quickslice from source at v0.17.3 (includes sub claim fix)
- frontend on cloudflare pages, backend on fly.io
- add readme with deployment docs
- clean up old deployment artifacts
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- removed invalid lexicon app.status.record (app is not a valid TLD)
- removed unused xyz.statusphere.status lexicon
- removed unused dev_utils.rs module
- project now only uses io.zzstoatzz.status.record (the correct NSID)
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- adds `just dev` command that runs cargo watch
- uses port 3000 to avoid conflicts with other local services
- watches src and templates directories for changes
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Change emoji seeding to sync new files on every deploy
- Only copy if destination doesn't exist (preserves manual uploads)
- Fix CI workflow by adding rustfmt component to toolchain
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fix emoji loading inefficiency and 404 errors
- Use placeholder images in emoji picker initially
- Load actual images after a frame to prevent race conditions
- Properly handle URL-encoded filenames like se%C3%B1or-bufo.png
- Add emoji-resolver.js that loads filename mappings from API
- Replace hardcoded .png/.gif extensions with placeholder images
- Eliminate 404 errors by using correct extensions from the start
- Support any file extension (.png, .gif, .jpg, .webp, etc.)
- Maintain backward compatibility for existing data
The resolver loads once, caches the mappings, and updates all emoji
images with their correct filenames, preventing unnecessary 404s.
馃 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Revert "Revert "Revert "Fix OAuth same-site issue with auth domain workaround"""
Revert "Revert "Fix OAuth same-site issue with auth domain workaround""
The automatic redirect was causing an infinite loop when accessing
auth.zzstoatzz.com/login. Now both domains serve the login page
directly without redirecting.
The OAuth flow will still use auth.zzstoatzz.com for the actual
authentication because that's configured in OAUTH_REDIRECT_BASE.
Revert "Fix OAuth same-site issue with auth domain workaround"
Fix OAuth same-site issue with auth domain workaround
- Fix host header injection vulnerability by removing host header check
- Add uses_separate_auth_domain() helper method for clarity
- Validate URLs at startup to fail fast on misconfiguration
- Simplify redirect logic using the new helper method
Security fix: No longer trusts Host header from requests, instead uses
configured URLs to determine redirect behavior.
- Add APP_URL to preview deployment secrets
- This ensures OAuth callback redirects to preview URL, not localhost
- Add APP_URL config for main app domain
- Redirect login from status domain to auth domain
- After OAuth success, redirect back to status domain
- Use config values instead of hardcoding URLs
This works around the PDS rejecting same-site OAuth requests by using auth.zzstoatzz.com for OAuth flow while keeping status.zzstoatzz.io as the main app.
Fix OAuth login issues for self-hosted PDS
- Fix SqliteStateStore and SqliteSessionStore to return Ok(None) instead of error when no state/session exists
- Add missing OAuth scopes to localhost configuration (profile and follows access)
- Remove unused NoSessionFound error variant
This fixes the OAuth flow failing when using a self-hosted PDS by ensuring the state stores properly handle missing entries and the localhost config declares all required scopes.
Immersive emoji picker modal
- Add position:relative and z-index to emoji-picker to ensure it properly blocks clicks
- Remove debug logging
- Replace undefined loadCustomEmojis with ensureCustomEmojis
- Remove unnecessary stopPropagation that was breaking modal
- Prevent modal from closing when clicking Custom tab
- Add event listener cleanup to prevent memory leaks
- Add CSS fallback for inset property for browser compatibility
- Stop event propagation on emoji picker to prevent accidental closes
Fix link hover colors to respect accent color preference
- Replace hardcoded blue hover color with color-mix() calculation
- Ensures all hover states respect user's chosen accent color
- Fixes 'your status' button showing blue on hover
- Add explicit :link and :visited states to prevent browser default blue
- Ensure :hover and :active states use var(--accent) consistently
- Fixes issue where status author links showed blue on hover
fix: Allow emoji-only status changes without text
When creating a new status with only an emoji change (no text), the
validation was incorrectly showing 'No changes'. Fixed by:
1. Properly handling the case where there's no current status (emoji is null)
2. Triggering validation after emoji selection from picker
3. Only disabling submission when the new status is identical to existing
Fixes #56
Co-authored-by: nate nowack <zzstoatzz@users.noreply.github.com>
Add GitHub footer with link to source repository
- Added fixed GitHub icon and link in bottom-left corner
- Styled to match existing site theme using CSS variables
- Appears on all pages via base.html template
- Responsive design hides text on mobile, keeping only icon
- Positioned opposite to bug report button for balance
Co-authored-by: nate nowack <zzstoatzz@users.noreply.github.com>
fmt: rustfmt regression tests
feat(webhooks): add webhook settings UI + API and signed delivery on status changes
instead of showing "clears now" for already-expired statuses, now
displays "expired", "expired Xm ago", "expired Xh ago", or "expired Xd ago"
depending on how long ago the status expired.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- build quickslice from source at v0.17.3 (includes sub claim fix)
- frontend on cloudflare pages, backend on fly.io
- add readme with deployment docs
- clean up old deployment artifacts
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- removed invalid lexicon app.status.record (app is not a valid TLD)
- removed unused xyz.statusphere.status lexicon
- removed unused dev_utils.rs module
- project now only uses io.zzstoatzz.status.record (the correct NSID)
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add emoji-resolver.js that loads filename mappings from API
- Replace hardcoded .png/.gif extensions with placeholder images
- Eliminate 404 errors by using correct extensions from the start
- Support any file extension (.png, .gif, .jpg, .webp, etc.)
- Maintain backward compatibility for existing data
The resolver loads once, caches the mappings, and updates all emoji
images with their correct filenames, preventing unnecessary 404s.
馃 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix host header injection vulnerability by removing host header check
- Add uses_separate_auth_domain() helper method for clarity
- Validate URLs at startup to fail fast on misconfiguration
- Simplify redirect logic using the new helper method
Security fix: No longer trusts Host header from requests, instead uses
configured URLs to determine redirect behavior.
- Add APP_URL config for main app domain
- Redirect login from status domain to auth domain
- After OAuth success, redirect back to status domain
- Use config values instead of hardcoding URLs
This works around the PDS rejecting same-site OAuth requests by using auth.zzstoatzz.com for OAuth flow while keeping status.zzstoatzz.io as the main app.
- Fix SqliteStateStore and SqliteSessionStore to return Ok(None) instead of error when no state/session exists
- Add missing OAuth scopes to localhost configuration (profile and follows access)
- Remove unused NoSessionFound error variant
This fixes the OAuth flow failing when using a self-hosted PDS by ensuring the state stores properly handle missing entries and the localhost config declares all required scopes.
When creating a new status with only an emoji change (no text), the
validation was incorrectly showing 'No changes'. Fixed by:
1. Properly handling the case where there's no current status (emoji is null)
2. Triggering validation after emoji selection from picker
3. Only disabling submission when the new status is identical to existing
Fixes #56
Co-authored-by: nate nowack <zzstoatzz@users.noreply.github.com>
- Added fixed GitHub icon and link in bottom-left corner
- Styled to match existing site theme using CSS variables
- Appears on all pages via base.html template
- Responsive design hides text on mobile, keeping only icon
- Positioned opposite to bug report button for balance
Co-authored-by: nate nowack <zzstoatzz@users.noreply.github.com>