Safari was collapsing the invisible spacer button. Added min-width
and box-sizing to force consistent width across browsers.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 1px spacing between status buttons
- Rounded corners on all buttons
- Invisible spacer for consistent row alignment
- Added scripts/deploy.sh for auto-incrementing version on deploy
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- idx_domains_to_check: status WHERE last_checked_at IS NULL
- idx_domains_to_crawl: status WHERE last_checked_at IS NOT NULL AND last_crawled_at IS NULL
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When no status filter is provided, the domains API now excludes
domains with 'skip' status (including bare TLDs) by default.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Domains without a dot (e.g., "com", "net", "org") are bare TLDs
from Common Crawl data and should not be processed as domains.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Feed details now expand inline instead of navigating to new page
- Add TLD section headers with domains sorted by TLD then name
- Add TLD filter button to show/hide domain sections by TLD
- Feed status behavior: pass creates account, hold crawls only, skip stops, drop cleans up
- Auto-follow new accounts from directory account (1440.news)
- Fix handle derivation (removed duplicate .1440.news suffix)
- Increase domain import batch size to 100k
- Various bug fixes for account creation and profile updates
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When setting publish_status to deny, now performs complete cleanup:
- Deletes all posts from the feed account on PDS
- Deletes the PDS account itself
- Clears published_at timestamps on all items
- Clears the publish_account field on the feed
Added Publisher methods:
- DeleteAllPosts: lists and deletes all posts from an account
- DeleteRecord: deletes a single AT Protocol record
- DeleteAccount: deletes account via PDS admin API
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replaced complex checks (digit-dash, all-digit hostname) with simple rule:
deny any domain starting with a digit, except 1440.news.
Database: denied 2,870,090 domains and 24,885 feeds.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Deny domains where hostname is all digits (e.g., 0000114.com)
- Never auto-deny 1440.news or subdomains
- Auto-pass feeds from 1440.news sources
- Updated 554,085 domains and 3,213 feeds in database
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
TTLMinutes, UpdateFreq, ErrorCount, ItemCount, and NoUpdate columns
can be NULL in the database. Use pointer types and handle them properly
to avoid scan errors.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Detect JSON Feed format (jsonfeed.org) via version field
- Parse JSON Feed metadata and items
- Support application/feed+json MIME type for feed discovery
- Include "json" as valid feed type (not auto-denied)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Feeds with type other than 'rss' or 'atom' (e.g., 'unknown') are now
automatically denied on discovery. Also updated 164 existing feeds.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added ability to toggle between alphabetical and feed count sorting when
viewing domains under a TLD. Includes UI toggle in breadcrumb area and
backend support for the sort parameter.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /api/tldStats endpoint for domain/feed counts per TLD
- Show stats bar at top when browsing a TLD
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use labeled links (Article · Audio) instead of raw URLs in posts
- Add language filter dropdown to dashboard with toggle selection
- Auto-deny feeds with no language on discovery
- Add deny/undeny buttons for domains to block crawling
- Denied domains set feeds to dead status, preventing future checks
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Changed short URL format from app.1440.news/r/{code} to url.1440.news/{code}
- Added Traefik routing for url.1440.news domain
- Root handler checks Host header to route url.1440.news requests
- Legacy /r/ path still supported for backwards compatibility
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- New short_urls and clicks tables for URL mapping and analytics
- /r/{code} redirect endpoint with click tracking
- Short URLs use 6-char base64 hash codes (26 chars total)
- Publish loop now shortens article links and enclosure URLs
- Enables podcast audio URLs to fit in posts (139 → 26 chars)
- Tracks: timestamp, referrer, user agent, anonymized IP
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Load enclosure fields in GetAllUnpublishedItems query
- Only include enclosure URL if it fits within post length limit
- Shorter video/audio enclosures will be included when they fit
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The PDS restricts the first segment of local handles to 18 characters,
not the AT Protocol spec of 63. Added abbreviation map for long
category names:
- science-and-environment -> sci-env
- entertainment-and-arts -> ent-arts
- technology -> tech (when needed)
- etc.
Fixes "Handle too long" errors for BBC category feeds.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Bluesky has a ~976KB blob limit. Images larger than 900KB are now
automatically resized using CatmullRom scaling and re-encoded as
JPEG with 85% quality. Iteratively scales down (90%, 72%, 58%...)
until under limit, with minimum dimensions of 100x100.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Filter imported domains to only .com TLD for now.
Re-enabled the import loop that was disabled for testing.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
BBC CDN supports larger image sizes by changing the URL path.
Upgrade /standard/240/ and /standard/480/ to /standard/800/.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Both createdAt and rkey now use the original publication date,
so posts sort consistently by their original publication time.
Falls back to DiscoveredAt if PubDate is not available.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Posts now use the item pub_date for the createdAt field instead
of the current time, so posts show their original publication time.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>