Resolve each feed's most recent sender domain and serve its favicon at
GET /favicon/:feedId, falling back to the project icon. Icons are fetched
in the background on ingestion (direct /favicon.ico then a DuckDuckGo
fallback), cached base64 in KV keyed by domain with a 1-week TTL so the
fetch only fires when absent. Exposed via RSS <image> / Atom <icon>/<logo>
and rendered in the admin feed list, plus a landing-page feature card.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
Replace the demo nightly KV wipe with a per-feed expiry. Feeds can be
given a lifetime at creation (and edited later); FEED_TTL_HOURS locks the
value server-side and greys out the UI field. Expired feeds stay visible
in admin (greyed, actions disabled), return 410 on rss/atom/entries, and
reject inbound emails. The scheduled handler now purges only expired
feeds (KV + R2 attachments) on an hourly global cron.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Add src/utils/urls.ts with baseUrl, feedRssUrl, feedAtomUrl, feedUrl,
feedEmailAddress, feedTopicPattern
- Add optional EMAIL_DOMAIN env var so web domain and email domain can
differ (e.g. demo.kill-the.news serves feeds, @kill-the.news receives mail)
- Replace all inline domain template literals with the new helpers
- Remove unused site_url/feed_url fields from FeedConfig
- Remove unused feedPath param from fetchFeedData
- Extract verifyCallback() to deduplicate verifyAndStoreSubscription /
verifyAndDeleteSubscription
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Atom feed URL shown in both list and table views (new Atom column)
- Remove container-wide toggle — both views now use max-width 1200px
- Update dashboard title and login title to kill-the-news
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Moves the 650-line inline JS template literal from admin.tsx into a
proper TypeScript source file with full type annotations. esbuild
compiles it to a minified IIFE committed in src/scripts/generated/,
which is imported and inlined into the HTML response as before.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Convert login page and dashboard GET routes from hono/html tagged template
literals to typed JSX using the <Layout> component. Extracts reusable
CopyIcon, CheckIcon, and CopyFieldInline components. Dashboard inline
script (~650 lines) preserved exactly via dangerouslySetInnerHTML constant.
All auth logic, CSRF middleware, and API routes are unchanged.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>