Jens Mittelbach76 downloadsImport starred RSS reader items as notes with YAML frontmatter.
Import starred or saved RSS reader items into Obsidian as Markdown notes with YAML frontmatter.
Article title - RSS shortHash.md.| Reader | Plugin provider | Setup notes |
|---|---|---|
| FreshRSS | Google Reader-compatible or Fever-compatible | Use the API URLs from FreshRSS settings, usually /api/greader.php or /api/fever.php, with the FreshRSS API password. |
| Tiny Tiny RSS | Tiny Tiny RSS | Enable the JSON API and use the /api/ endpoint. Starred items are imported from the special starred feed. |
| Inoreader | Inoreader | Use https://www.inoreader.com. OAuth bearer token is preferred; legacy ClientLogin can use username/password plus optional App ID/App Key. |
| Feedly | Feedly | Requires a Feedly API bearer token and a stream ID. For Feedly Teams this is usually a board, folder, or AI Feed stream ID. |
| Miniflux | Miniflux | Use a Miniflux API token. The plugin fetches /v1/entries?starred=true. Miniflux can also be used through its Fever API. |
Other likely compatible readers include services or servers that expose Google Reader-compatible or Fever-compatible APIs, such as CommaFeed, FeedHQ, The Old Reader, and BazQux. Compatibility depends on the exact API variant and authentication requirements.
https://rss.example.com/api/greader.phphttps://rss.example.com/api/fever.phphttps://rss.example.com/tt-rss/api/https://rss.example.comurl; comma-separated legacy names are supported.rss.content_source and content_fetched_at in frontmatter.Credentials are stored in this plugin's Obsidian data file. By default, the plugin only sends network requests to the reader API URL you configure.
The - RSS <hash> filename suffix is still used for newly imported notes so items with the same title but different URLs do not target the same file path. The plugin also stores the same stable hash as rss_hash in imported note frontmatter and recognizes the legacy filename suffix for older imports. Existing imports are skipped when that hash is found in the configured Output folder and its subfolders, so you can rename imported notes as long as rss_hash remains in the note frontmatter. When Skip duplicate links is enabled, the plugin also scans Markdown frontmatter in that folder tree for the configured URL property names before importing. URLs are compared after light normalization: surrounding whitespace and URL fragments are ignored, hostnames are compared case-insensitively, default HTTP/HTTPS ports are ignored, and trailing path slashes are ignored. Query strings are preserved.
For reliable deduplication, keep these frontmatter properties in imported notes:
rss_hash: Required for rename-safe duplicate detection. The plugin adds this automatically, including to custom template output when it is missing.url: Required only when Skip duplicate links is enabled with the default duplicate URL property. If you configure different duplicate URL properties, keep those properties instead.Existing notes imported before rss_hash was added can still be detected by the legacy - RSS <hash>.md filename suffix until they are renamed. If you rename those older notes, add rss_hash first.
If Fetch article source text is enabled, the plugin also requests article URLs from your starred items and extracts readable content with Defuddle. It only accepts HTTP and HTTPS URLs, skips localhost/private-network-style hosts, limits article responses to 2 MB, removes scripts/forms/active content/inline event handlers, disables Defuddle's async third-party fallbacks, and converts the extracted HTML to Markdown before writing notes. Remote article images are removed unless Include remote images is enabled; when enabled, only safe HTTP and HTTPS image links are kept, and Obsidian may contact those image hosts when rendering notes. This may still disclose your IP address and user agent to article websites. If you want local copies of remote images, consider using an attachment-localizing Obsidian plugin such as Local Images Plus.
Set Note template to a vault path such as Templates/Starred news item. Wikilinks such as [[Templates/Starred news item]] also work. When Templater is installed, the plugin injects these objects before rendering:
rss: the full import context.item: alias for rss.item, containing normalized reader fields.content: alias for rss.content, containing selected HTML/Markdown content fields.Common fields include rss.title, rss.url, rss.reader, rss.author, rss.feedTitle, rss.feedUrl, rss.publishedAt, rss.updatedAt, rss.importedAt, rss.tags, rss.notePath, rss.fileName, rss.shortHash, rss.byline, rss.contentHtml, rss.summaryHtml, rss.selectedContentHtml, rss.contentMarkdown, rss.summaryMarkdown, rss.contentSource, and rss.contentFetchedAt. The default YAML fields are also available as rss.frontmatter.
Sample rss object with representative values:
{
"id": "tag:example.com,2026:starred/12345",
"title": "Shipping small plugins without breaking your vault",
"url": "https://example.com/posts/shipping-small-plugins",
"reader": "miniflux",
"author": "Casey Example",
"feedTitle": "Example Engineering",
"feedUrl": "https://example.com/feed.xml",
"publishedAt": "2026-05-24T08:30:00.000Z",
"updatedAt": "2026-05-24T09:10:00.000Z",
"contentHtml": "<p>Full article body.</p><p>It has several paragraphs.</p>",
"summaryHtml": "<p>Short reader summary.</p>",
"contentSource": "article_url",
"contentFetchedAt": "2026-05-30T11:42:13.000Z",
"importedAt": "2026-05-30T11:42:14.000Z",
"tags": ["rss", "starred"],
"notePath": "News/Shipping small plugins without breaking your vault - RSS a1b2c3d4.md",
"fileName": "Shipping small plugins without breaking your vault - RSS a1b2c3d4.md",
"shortHash": "a1b2c3d4",
"byline": "Example Engineering | Casey Example | 2026-05-24",
"selectedContentHtml": "<p>Full article body.</p><p>It has several paragraphs.</p>",
"contentMarkdown": "Full article body.\n\nIt has several paragraphs.",
"summaryMarkdown": "Short reader summary.",
"content": {
"html": "<p>Full article body.</p><p>It has several paragraphs.</p>",
"markdown": "Full article body.\n\nIt has several paragraphs.",
"readerHtml": "<p>Full article body.</p><p>It has several paragraphs.</p>",
"summaryHtml": "<p>Short reader summary.</p>",
"summaryMarkdown": "Short reader summary.",
"source": "article_url",
"fetchedAt": "2026-05-30T11:42:13.000Z"
},
"item": {
"id": "tag:example.com,2026:starred/12345",
"title": "Shipping small plugins without breaking your vault",
"url": "https://example.com/posts/shipping-small-plugins",
"reader": "miniflux",
"author": "Casey Example",
"feedTitle": "Example Engineering",
"feedUrl": "https://example.com/feed.xml",
"publishedAt": "2026-05-24T08:30:00.000Z",
"updatedAt": "2026-05-24T09:10:00.000Z",
"contentHtml": "<p>Full article body.</p><p>It has several paragraphs.</p>",
"summaryHtml": "<p>Short reader summary.</p>",
"contentSource": "article_url",
"contentFetchedAt": "2026-05-30T11:42:13.000Z"
},
"frontmatter": {
"title": "Shipping small plugins without breaking your vault",
"url": "https://example.com/posts/shipping-small-plugins",
"reader": "miniflux",
"reader_item_id": "tag:example.com,2026:starred/12345",
"imported": "2026-05-30T11:42:14.000Z",
"rss_hash": "a1b2c3d4",
"author": "Casey Example",
"feed": "Example Engineering",
"feed_url": "https://example.com/feed.xml",
"published": "2026-05-24T08:30:00.000Z",
"updated": "2026-05-24T09:10:00.000Z",
"content_source": "article_url",
"content_fetched_at": "2026-05-30T11:42:13.000Z",
"tags": ["rss", "starred"]
}
}
Using the sample object above, these template markers render to these values:
{{rss.title}} -> Shipping small plugins without breaking your vault{{rss.summaryMarkdown}} -> Short reader summary.{{rss.contentMarkdown}} -> Full article body. followed by It has several paragraphs.{{item.feedTitle}} -> Example Engineering{{content.markdown}} -> same value as {{rss.contentMarkdown}}{{content.summaryMarkdown}} -> same value as {{rss.summaryMarkdown}}summaryMarkdown and contentMarkdown are intentionally different fields. summaryMarkdown always comes from the reader-provided summary. contentMarkdown comes from the content selected for the note body, which is either full article content or the summary when full article content is unavailable or disabled. That means the two fields are identical only when the reader exposes no separate full content, or when the selected note content falls back to the summary.
Typical reader field coverage:
| Reader | author |
feedTitle / feedUrl |
publishedAt |
updatedAt |
contentHtml |
summaryHtml |
Notes |
|---|---|---|---|---|---|---|---|
| Google Reader-compatible | Usually | Usually | Usually | Usually | Sometimes | Sometimes | Depends on what the server exposes in content and summary. |
| Inoreader | Usually | Usually | Usually | Usually | Sometimes | Sometimes | Uses the Google Reader-compatible mapping. |
| Feedly | Usually | Usually | Usually | Usually | Sometimes | Sometimes | Often provides both full content and summary, but not for every entry. |
| Tiny Tiny RSS | Usually | Usually | Usually | No | Usually | Sometimes | summaryHtml comes from TT-RSS excerpt. |
| Fever API | Sometimes | Usually | Usually | No | Usually | No | No separate summary field is currently mapped. |
| Miniflux | Sometimes | Usually | Usually | Usually | Usually | No | No separate summary field is currently mapped. |
Usually and Sometimes reflect both the upstream API and the specific item. A reader may omit fields for some entries even when it supports them in general. If Fetch article source text is enabled, contentHtml, contentMarkdown, contentSource, and contentFetchedAt can also change after the initial reader import because the plugin may replace reader content with extracted article content.
Example template:
---
title: <% JSON.stringify(rss.title) %>
url: <% JSON.stringify(rss.url) %>
reader: <% JSON.stringify(rss.reader) %>
imported: <% JSON.stringify(rss.importedAt) %>
rss_hash: <% JSON.stringify(rss.shortHash) %>
tags:
<%* for (const tag of rss.tags) { tR += ` - ${JSON.stringify(tag)}\n`; } -%>
---
# <% rss.title %>
<% rss.byline %>
[Read original](<% rss.url %>)
<% rss.contentMarkdown %>
If Templater is not installed, the plugin still replaces simple placeholders such as {{rss.title}}, {{rss.contentMarkdown}}, and {{content.markdown}}. Templater JavaScript blocks only run when Templater is installed. Use templates you trust, because Templater templates can execute JavaScript.
If Include debug view is enabled, imported notes also end with a collapsed Obsidian callout that shows the normalized incoming item. Use Formatted JSON to inspect the exact serialized values visible to templates, or Field view for a one-field-per-line summary.
If you want to perform additional AI processing of the imported news items (e.g. automatic tagging, abstract writing etc.), consider using the AI for Templater plugin.
Install dependencies:
npm install
Run a development build with watch mode:
npm run dev
Create a production build:
npm run build
Release tags must exactly match manifest.json's version and must not use a leading v.
When a GitHub release is published, or when the release workflow is run manually, GitHub Actions builds the plugin and uploads these required release assets:
manifest.jsonmain.jsstyles.cssThe workflow fails if any asset is missing or empty, or if the tag does not match the manifest version.