Stores the most recent item's published date on the blog document
during feed sync. Exposed in API response alongside lastFetchAt.
Enables sorting/displaying blogs by content freshness rather than
last fetch time.
Rename duplicate "sync" locale key to "syncResult" to fix the sources
list page showing [Object Object] instead of the Sync button label.
Add sort=recent and source= query params to the blogs API for the
sidebar widget tabs feature. Tag FeedLand blogs with source: "feedland"
and expose source field for all blogs in API responses.
Bump version to 1.0.22.
Adds FeedLand (feedland.com or self-hosted) as a new source type alongside
OPML and Microsub. Syncs subscriptions via FeedLand's public OPML endpoint
with optional category filtering and AJAX category discovery in the admin UI.
- Extract ~560 lines of inline CSS to external assets/styles.css
- Create intermediate layout (layouts/blogroll.njk) for CSS loading
- Use section(), badge(), button(), prose() macros instead of raw HTML
- Remove custom page headers (document.njk heading() handles via title/parent)
- Add parent breadcrumb navigation to all sub-pages
- Add consumeFlashMessage() to dashboard and sources controllers
- Rename CSS class prefix from br-* to blogroll-* for clarity
- Use upstream CSS custom properties without fallback values
- Fix Microsub orphan detection (soft-delete unsubscribed blogs)
- Fix upsert to conditionally set microsub fields (avoid path conflicts)
- Skip soft-deleted blogs during clear-and-resync
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Decode HTML entities (& ' etc) in feed titles and summaries
- Add isFuture flag to API items for future-dated posts
- Bump version to 1.0.12
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deleted blogs are now marked with status: "deleted" instead of being
removed from MongoDB. The upsertBlog function skips deleted feedUrls,
preventing OPML/Microsub sync from recreating them. All queries exclude
deleted blogs. Flash messages now use Indiekit's native notificationBanner.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Indiekit date filter calls parseISO() which expects a string.
MongoDB returns Date objects for item.published, causing
"dateString.split is not a function" error on the blog edit page.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Microsub source type to sync subscriptions from Microsub channels
- Use reference-based approach to avoid data duplication:
- Blogs store microsubFeedId reference instead of copying data
- Items for Microsub blogs are queried from microsub_items directly
- No duplicate storage or retention management needed
- Add channel filter and category prefix options for Microsub sources
- Add webhook endpoint for Microsub subscription change notifications
- Update scheduler to skip item fetching for Microsub blogs
- Update items storage to combine results from both collections
- Bump version to 1.0.7
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove 'Manual' source type (redundant with Blogs management)
- Rename 'Sources' to 'OPML Sync' for clarity
- Update labels to clarify URL syncs periodically, File is one-time import
- Fix date conversion in sources list controller
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add feed-discovery.js utility that discovers RSS/Atom/JSON feeds from website URLs
- Add /api/discover endpoint for frontend feed discovery
- Update blog edit form with discovery UI (enter website URL, discover feeds)
- Auto-populate feedUrl, title, and siteUrl from discovery results
- Handle multiple feed options (let user choose)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Indiekit date filter expects ISO strings, not JavaScript Date objects.
This fixes 'dateString.split is not a function' errors in the dashboard.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>