mirror of
https://github.com/rmdes/indiekit-endpoint-podroll.git
synced 2026-06-24 15:03:44 +00:00
No description
- JavaScript 83.2%
- Nunjucks 12.4%
- CSS 4.4%
| assets | ||
| lib | ||
| locales | ||
| views | ||
| .gitignore | ||
| CLAUDE.md | ||
| index.js | ||
| package.json | ||
| README.md | ||
@rmdes/indiekit-endpoint-podroll
Podcast roll endpoint for Indiekit. Aggregates podcast episodes from a FreshRSS instance and provides JSON APIs for displaying a podroll page with episode listings and OPML sidebar.
Features
- Syncs podcast episodes from FreshRSS greader API
- Syncs podcast sources from OPML export
- Caches data in MongoDB for fast API responses
- Background sync at configurable intervals
- Public JSON APIs for frontend consumption
- Admin dashboard for manual sync and status
Installation
npm install @rmdes/indiekit-endpoint-podroll
Configuration
Add to your Indiekit config:
import PodrollEndpoint from "@rmdes/indiekit-endpoint-podroll";
export default {
plugins: [
new PodrollEndpoint({
episodesUrl: "https://your-freshrss.example/api/query.php?user=USER&t=TOKEN&f=greader",
opmlUrl: "https://your-freshrss.example/api/query.php?user=USER&t=TOKEN&f=opml",
syncInterval: 900000, // 15 minutes (default)
maxEpisodes: 100, // Maximum episodes to cache (default)
}),
],
};
API Endpoints
Public (no auth required)
| Endpoint | Description |
|---|---|
GET /podrollapi/api/episodes |
List episodes. Params: limit, offset, source |
GET /podrollapi/api/episodes/:id |
Get single episode |
GET /podrollapi/api/sources |
List podcast sources from OPML. Params: category |
GET /podrollapi/api/status |
Sync status and counts |
Protected (requires auth)
| Endpoint | Description |
|---|---|
GET /podrollapi/ |
Admin dashboard |
POST /podrollapi/sync |
Trigger manual sync |
POST /podrollapi/clear-resync |
Clear cache and re-sync |
Episode Response Schema
{
"items": [
{
"id": "unique-episode-id",
"title": "Episode Title",
"url": "https://podcast.example/episode",
"published": "2026-01-31T12:00:00.000Z",
"content": "<p>Episode description HTML</p>",
"author": "Author Name",
"enclosure": {
"url": "https://cdn.example/episode.mp3",
"type": "audio/mpeg",
"length": 12345678
},
"podcast": {
"title": "Podcast Name",
"url": "https://podcast.example",
"feedUrl": "https://podcast.example/feed.xml"
}
}
],
"total": 100,
"limit": 50,
"offset": 0,
"hasMore": true
}
Sources Response Schema
{
"items": [
{
"title": "Podcast Name",
"xmlUrl": "https://podcast.example/feed.xml",
"htmlUrl": "https://podcast.example",
"category": "Technology"
}
],
"total": 70,
"categories": ["Technology", "Culture", "Politics"]
}
Frontend Integration
The APIs are designed for client-side fetching. Example with vanilla JavaScript:
// Fetch episodes
const response = await fetch('/podrollapi/api/episodes?limit=20');
const { items, hasMore } = await response.json();
// Fetch sources for sidebar
const sourcesResponse = await fetch('/podrollapi/api/sources');
const { items: sources } = await sourcesResponse.json();
License
MIT