@rmdes/indiekit-endpoint-blogroll
v1.0.23
Published
Blogroll endpoint for Indiekit. Aggregates blog feeds from OPML, JSON feeds, or manual entry.
Maintainers
Readme
Blogroll Endpoint for Indiekit
An Indiekit plugin that provides a comprehensive blogroll management system with feed aggregation, admin UI, and public API.
Features
- Multiple Source Types: Import blogs from OPML files/URLs, Microsub subscriptions, or add manually
- Background Feed Fetching: Automatically syncs blogs and caches recent items
- Microsub Integration: Mirror your Microsub subscriptions as a blogroll (zero duplication)
- Admin UI: Manage sources, blogs, and view recent activity
- Public JSON API: Read-only endpoints for frontend integration
- OPML Export: Export your blogroll as OPML (all or by category)
- Feed Discovery: Auto-discover feeds from website URLs
- Item Retention: Automatic cleanup of old items (encourages fresh content discovery)
Installation
npm install @rmdes/indiekit-endpoint-blogrollConfiguration
Add to your indiekit.config.js:
import BlogrollEndpoint from "@rmdes/indiekit-endpoint-blogroll";
export default {
plugins: [
new BlogrollEndpoint({
mountPath: "/blogrollapi", // Admin UI and API base path
syncInterval: 3600000, // 1 hour (in milliseconds)
maxItemsPerBlog: 50, // Items to fetch per blog
maxItemAge: 7, // Days - older items auto-deleted
fetchTimeout: 15000 // 15 seconds per feed fetch
})
]
};Requirements
- Indiekit:
>=1.0.0-beta.25 - MongoDB: Required for data storage
- Optional:
@rmdes/indiekit-endpoint-microsubfor Microsub integration
Usage
Admin UI
Navigate to /blogrollapi in your Indiekit instance to access:
- Dashboard: View sync status, blog counts, recent activity
- Sources: Manage OPML and Microsub sources
- Blogs: Add/edit/delete individual blogs, refresh feeds
- Manual Sync: Trigger immediate sync or clear and resync
Source Types
- OPML URL: Point to a public OPML file (e.g., your feed reader's export)
- OPML File: Paste OPML XML directly into the form
- Microsub: Import subscriptions from your Microsub channels
- Manual: Add individual blog feeds one at a time
Public API
All API endpoints return JSON (except OPML export which returns XML).
List Blogs
GET /blogrollapi/api/blogs?category=Tech&limit=100&offset=0Get Blog with Recent Items
GET /blogrollapi/api/blogs/:idList Items Across All Blogs
GET /blogrollapi/api/items?blog=<id>&category=Tech&limit=50&offset=0List Categories
GET /blogrollapi/api/categoriesSync Status
GET /blogrollapi/api/statusExport OPML
GET /blogrollapi/api/opml (all blogs)
GET /blogrollapi/api/opml/:category (specific category)Example Response
GET /blogrollapi/api/blogs
{
"items": [
{
"id": "507f1f77bcf86cd799439011",
"title": "Example Blog",
"description": "A great blog about tech",
"feedUrl": "https://example.com/feed",
"siteUrl": "https://example.com",
"feedType": "rss",
"category": "Tech",
"tags": ["programming", "web"],
"photo": "https://example.com/icon.png",
"status": "active",
"itemCount": 25,
"pinned": false,
"lastFetchAt": "2026-02-13T10:30:00.000Z"
}
],
"total": 42,
"hasMore": true
}GET /blogrollapi/api/items
{
"items": [
{
"id": "507f1f77bcf86cd799439011",
"url": "https://example.com/post/hello",
"title": "Hello World",
"summary": "My first blog post...",
"published": "2026-02-13T10:00:00.000Z",
"isFuture": false,
"author": { "name": "Jane Doe" },
"photo": ["https://example.com/image.jpg"],
"categories": ["announcement"],
"blog": {
"id": "507f1f77bcf86cd799439011",
"title": "Example Blog",
"siteUrl": "https://example.com",
"category": "Tech",
"photo": "https://example.com/icon.png"
}
}
],
"hasMore": false
}Microsub Integration
If you have @rmdes/indiekit-endpoint-microsub installed, the blogroll can mirror your subscriptions:
- Create a Microsub source in the admin UI
- Select specific channels or sync all channels
- Add a category prefix (optional) to distinguish Microsub blogs
- Blogs and items are referenced, not duplicated
Benefits:
- Zero data duplication - items are served directly from Microsub
- Automatic orphan cleanup when feeds are unsubscribed
- Webhook support for real-time updates
Background Sync
The plugin automatically syncs in the background:
- Initial Sync: Runs 15 seconds after server startup
- Periodic Sync: Runs every
syncIntervalmilliseconds (default 1 hour) - What it Does:
- Syncs enabled sources (OPML/Microsub)
- Fetches new items from active blogs
- Deletes items older than
maxItemAgedays - Updates sync statistics
Manual Sync:
- Trigger from the dashboard
- Use
POST /blogrollapi/sync(protected endpoint) - Use
POST /blogrollapi/clear-resyncto clear and resync all
Feed Discovery
The plugin includes auto-discovery for finding feeds from website URLs:
// In the admin UI, when adding a blog, paste a website URL
// The plugin will:
// 1. Check <link rel="alternate"> tags in HTML
// 2. Try common feed paths (/feed, /rss, /atom.xml, etc.)
// 3. Suggest discovered feedsItem Retention
By default, items older than 7 days are automatically deleted during sync. This encourages discovery of fresh content rather than archiving everything.
To Change Retention:
new BlogrollEndpoint({
maxItemAge: 30 // Keep items for 30 days instead
})Blog Status
- active: Blog is working, fetching items normally
- error: Last fetch failed (see
lastErrorfor details) - deleted: Soft-deleted, won't be recreated by sync
Navigation
The plugin adds itself to Indiekit's navigation:
- Menu Item: "Blogroll" (requires database)
- Shortcut: Bookmark icon in admin dashboard
Security
- Protected Routes: Admin UI and management endpoints require authentication
- Public Routes: Read-only API endpoints are publicly accessible
- XSS Prevention: Feed content is sanitized with
sanitize-html - Feed Discovery: Protected to prevent abuse (requires authentication)
Supported Feed Formats
- RSS 2.0
- Atom 1.0
- JSON Feed 1.0
Contributing
Report issues at: https://github.com/rmdes/indiekit-endpoint-blogroll/issues
License
MIT
