No description
Find a file
Charles Kelsoe e83caf2a3d Add endless scroll, select-all, item counts, and custom-domain Substack detection
Import window:
- Endless scroll: an IntersectionObserver auto-loads older Substack archive
  pages as a bottom sentinel scrolls into view. The "Load older" button stays
  as a fallback and end-of-archive indicator.
- Select-all toggle that checks every available (not imported, not dismissed)
  loaded item and flips to "Deselect all" once all are selected.
- Toolbar counts: a running loaded count that reads "All N items" once the
  archive is exhausted, and an "x of y selected" count beside the toggle.

Resolver:
- Detect a custom-domain Substack by its <generator>Substack</generator> feed
  marker, so it classifies as substack (and gains archive backfill) instead of
  falling back to generic. Backward compatible: feeds without the marker stay
  generic.

Settings:
- A "Re-detect" button on each feed editor page re-resolves the feed and
  updates its source type in place, upgrading a feed saved as generic without
  removing and re-adding it. feedId is left untouched so dedup and dismissals
  stay valid.

Adds unit coverage for selectableItemIds, selectAllControlState, and the
generator-marker detection on both the probe and explicit-feed-url paths.
2026-06-15 17:34:02 -04:00
.github Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
__tests__ Add endless scroll, select-all, item counts, and custom-domain Substack detection 2026-06-15 17:34:02 -04:00
scripts Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
.editorconfig Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
.gitignore Wave A: leaf modules (logger, pacer, paywall, dismiss, index, note-writer) 2026-06-14 14:11:12 -04:00
.npmrc Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
add-feed-modal.ts Fix add-feed Save button doing nothing 2026-06-14 16:16:47 -04:00
CHANGELOG.md Add endless scroll, select-all, item counts, and custom-domain Substack detection 2026-06-15 17:34:02 -04:00
cleanup.ts Feature: per-feed deterministic cleanup (link-host + trim rules) 2026-06-14 17:34:05 -04:00
CONTRIBUTING.md Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
debug-logger.ts Wave A: leaf modules (logger, pacer, paywall, dismiss, index, note-writer) 2026-06-14 14:11:12 -04:00
dismiss-store.ts Wave A: leaf modules (logger, pacer, paywall, dismiss, index, note-writer) 2026-06-14 14:11:12 -04:00
duplicate-prompt-modal.ts Phase 5: apply adversarial-review fixes 2026-06-14 15:26:45 -04:00
esbuild.config.mjs Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
eslint.config.mts Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
feed-picker-modal.ts Phase 5: apply adversarial-review fixes 2026-06-14 15:26:45 -04:00
feed-resolver.ts Add endless scroll, select-all, item counts, and custom-domain Substack detection 2026-06-15 17:34:02 -04:00
feed-source.ts Feature: Substack archive backfill (load older than the RSS window) 2026-06-14 17:18:56 -04:00
feed-xml.ts Wave B: XML parser, HTML-to-Markdown converter, feed resolver 2026-06-14 14:32:39 -04:00
fetch-pacer.ts Wave A: leaf modules (logger, pacer, paywall, dismiss, index, note-writer) 2026-06-14 14:11:12 -04:00
folder-suggest.ts Wave D: import services and UI shell 2026-06-14 15:01:59 -04:00
html-converter.ts Converter: strip Substack app-install / subscribe / CTA clutter 2026-06-14 16:27:53 -04:00
image-downloader.ts Phase 5: apply adversarial-review fixes 2026-06-14 15:26:45 -04:00
import-modal.ts Add endless scroll, select-all, item counts, and custom-domain Substack detection 2026-06-15 17:34:02 -04:00
import-runner.ts Feature: per-feed deterministic cleanup (link-host + trim rules) 2026-06-14 17:34:05 -04:00
jest.config.cjs Add jest test harness: obsidian mock + moduleNameMapper wiring 2026-06-14 14:03:11 -04:00
LICENSE Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
main.ts Feature: per-feed deterministic cleanup (link-host + trim rules) 2026-06-14 17:34:05 -04:00
manifest.json Release 0.4.0: per-feed deterministic cleanup rules 2026-06-14 17:34:57 -04:00
media-downloader.ts Feature: per-feed media (audio/video) download 2026-06-14 16:59:44 -04:00
note-writer.ts Feature: per-feed media (audio/video) download 2026-06-14 16:59:44 -04:00
package-lock.json Release 0.4.0: per-feed deterministic cleanup rules 2026-06-14 17:34:57 -04:00
package.json Release 0.4.0: per-feed deterministic cleanup rules 2026-06-14 17:34:57 -04:00
paywall-detector.ts Wave A: leaf modules (logger, pacer, paywall, dismiss, index, note-writer) 2026-06-14 14:11:12 -04:00
PRIVACY.md Docs: MVP-accurate README, PRIVACY, SECURITY 2026-06-14 14:40:39 -04:00
README.md README: add early-development/use-at-own-risk notice, requirements, full feature list 2026-06-14 17:51:37 -04:00
SECURITY.md Docs: MVP-accurate README, PRIVACY, SECURITY 2026-06-14 14:40:39 -04:00
settings-tab.ts Add endless scroll, select-all, item counts, and custom-domain Substack detection 2026-06-15 17:34:02 -04:00
settings.ts Feature: per-feed deterministic cleanup (link-host + trim rules) 2026-06-14 17:34:05 -04:00
source-common.ts Feature: Substack archive backfill (load older than the RSS window) 2026-06-14 17:18:56 -04:00
source-generic.ts Feature: Substack archive backfill (load older than the RSS window) 2026-06-14 17:18:56 -04:00
source-substack.ts Feature: Substack archive backfill (load older than the RSS window) 2026-06-14 17:18:56 -04:00
styles.css Add endless scroll, select-all, item counts, and custom-domain Substack detection 2026-06-15 17:34:02 -04:00
tsconfig.json Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
turndown-plugin-gfm.d.ts Wave B: XML parser, HTML-to-Markdown converter, feed resolver 2026-06-14 14:32:39 -04:00
types.d.ts Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
ui-helpers.ts Wave D: import services and UI shell 2026-06-14 15:01:59 -04:00
vault-index.ts Wave A: leaf modules (logger, pacer, paywall, dismiss, index, note-writer) 2026-06-14 14:11:12 -04:00
version-bump.mjs Scaffold from standard plugin template 2026-06-14 13:57:19 -04:00
versions.json Release 0.4.0: per-feed deterministic cleanup rules 2026-06-14 17:34:57 -04:00

RSS Importer

CI Release GitHub Downloads GitHub Stars Obsidian License Latest Release

Import articles and podcasts from RSS, Atom, and Substack feeds into your vault as Markdown notes, organized by source feed and deduplicated by note identity.

It is an importer, not a reader. It writes notes you own and then gets out of the way.

Warning

Early development, use at your own risk. RSS Importer is in active early development and is not yet production-ready. Features and note formats may still change, and bugs are possible. It writes (and, with the cleanup command, rewrites) notes in your vault, so keep backups and try it on a test vault first. Provided "as is", without warranty, under the MIT License. It is not yet in the Obsidian Community Plugins store — install via BRAT or manually (see below).

Requirements

  • Obsidian v1.13.0 or newer.
  • Desktop only (Windows, macOS, Linux). It is not available on mobile.

Features

  • Multiple sources. Add any RSS, Atom, or podcast feed. Substack publications are first-class: paste an @handle, a subdomain, a custom domain, or a post URL and the plugin resolves it to the right feed.
  • One folder per feed, never re-imports. Each feed imports into its own destination folder, and every note carries a stable identity in its frontmatter, so moving or renaming notes never causes duplicates on the next import. Reorganize into subfolders freely.
  • Add-feed preview. Paste a feed and resolve it to preview the publication title, host, recent item titles, and source type before you commit.
  • Three-state import window. Each item shows as imported, dismissed, or available, with checkboxes, live progress, and a result summary. Dismissing is reversible, and imported items update immediately.
  • Archive backfill. For Substack feeds, a "Load older" control pages back through the publication's archive, well beyond the recent RSS window, fetching older posts on demand.
  • Clean Markdown. Article HTML is converted to tidy Markdown (headings, lists, tables, code blocks with language, captions, footnotes), with Substack subscribe/app/share widgets stripped.
  • Per-feed cleanup rules. Remove promotional clutter by link target (for example a "buy me a coffee" or subscribe block) or trim a trailing footer, applied on import and re-runnable over existing notes with the Clean up imported notes command. Matching is by link and structure, not wording, so rules keep working when the text changes.
  • Images. Link to the original image URLs, or download images into your vault.
  • Media. Download podcast/audio/video enclosures into a vault subfolder or to a folder outside the vault, per feed.
  • Tidy tags. Feed tags are written to a feed-tags note property by default so they do not flood the global tag pane, or to Obsidian tags if you prefer.
  • Per-feed overrides. Most defaults (destination, note name, images, media, cleanup, tags) can be set globally and overridden per feed.

Usage

  1. Open Settings → RSS Importer → Feeds → Add feed. Paste a feed URL or Substack handle, click Resolve to preview, choose a destination folder, optionally add tags and cleanup rules, and save.
  2. Run the Import from a feed command (or the ribbon icon) to open the import window. Select items and import; for Substack, use Load older to reach archived posts. The summary reports what was created, skipped, or failed.
  3. Optionally run Clean up imported notes to re-apply a feed's cleanup rules to notes you already imported.

Installation

Not yet in the Obsidian Community Plugins store. For now, use BRAT or a manual install.

BRAT installs and updates pre-release plugins straight from GitHub.

  1. Install the BRAT plugin from Community Plugins.
  2. Open BRAT settings and click Add Beta Plugin.
  3. Enter: https://github.com/ckelsoe/obsidian-rss-importer
  4. Enable RSS Importer in Settings → Community plugins.

Manual installation

  1. Download main.js, manifest.json, and styles.css from the latest release.
  2. Create a folder named rss-importer in your vault's .obsidian/plugins/ directory.
  3. Copy the downloaded files into this folder.
  4. Reload Obsidian, then enable RSS Importer in Settings → Community plugins.

From Obsidian Community Plugins

Once the plugin is accepted into the store, you will be able to find it under Settings → Community plugins → Browse by searching for RSS Importer.

Changelog

See CHANGELOG.md for release history.

Contributing

See CONTRIBUTING.md for setup, quality gates, and conventions.

License

MIT. See LICENSE.