Skip to content

Tool to store selected substack posts offline

License

Notifications You must be signed in to change notification settings

kxrtiswithak/substack-offline

Repository files navigation

Substack Offline 📬

Save Substack posts for offline reading with assets preserved, from a popup-first Chrome extension.

Highlights ✨

  • Popup-first UI (no "Open Full App in Tab" action in normal user flow).
  • Batch save by number of posts or date range.
  • Save the currently open post from the active tab.
  • Closable toast notifications plus structured console logs.
  • Offline-friendly snapshot rewriting for images, embeds, and media fallbacks.

Current UX 🧭

  • Click the extension icon to open the popup.
  • Publication URL auto-populates when the active tab can be resolved to a publication.
  • Save Posts uses a one-click folder flow: choose a folder once per batch, then posts are written as .html files into that folder.
  • Save Current Post saves the active post route directly.
  • Saved post titles are clickable to open.
  • Delete controls include a trash icon per post and Delete All per publication.

Supported URL Patterns ✅

Save Current Post and publication detection handle:

  • Canonical post URLs: https://<publication>/p/<slug>
  • Substack root post routes: https://substack.com/home/post/p-<id>
  • Substack root post routes: https://substack.com/inbox/post/<id>
  • Profile routes for publication resolution: https://substack.com/@<handle>
  • Substack/custom domains where post preview metadata resolves the canonical post.

Keyboard Shortcuts ⌨️

Default commands from manifest.json:

  • Alt+Shift+E opens the extension popup (_execute_action).
  • Alt+Shift+S saves the currently open Substack post (save-active-post).

You can change shortcuts at chrome://extensions/shortcuts.

Requirements

  • Node.js >= 24.11 < 25 (Volta pinned to 24.13.0).
  • npm.
  • Chrome or Chromium browser with Manifest V3 support.
  • Logged-in Substack session in the same browser profile.

Install

npm install

Build

npm run build

Build output:

  • build/extension-package

Load Unpacked Extension

  1. Open chrome://extensions.
  2. Enable Developer mode.
  3. Click Load unpacked.
  4. Select build/extension-package.

Data Storage 🗂️

  • Settings and UI metadata are stored in chrome.storage.local.
  • Batch folder-save posts are stored in your chosen folder via File System Access API.
  • Active post saves and persisted snapshots are written through Chrome Downloads under Downloads/Substack Offline Saver/<publication>/....

Toasts and Logs 🧪

  • UI messages appear as short-lived toasts with a Close action.
  • The same events are logged to console with [substack-offline/ui] and metadata.
  • Logged metadata includes fields such as event, level, message, publication URL, post ID/title, save counts, and job ID when available.

NPM Commands

  • npm run lint - ESLint.
  • npm run test - unit tests (Vitest).
  • npm run test:e2e - live e2e tests.
  • npm run build - TypeScript build + UI build + extension packaging.
  • npm run build:ui - UI bundle only.
  • npm run build:watch - TypeScript watch mode.
  • npm run start - print packaged extension path.
  • npm run start:cli - run legacy CLI output.

Formatting enforcement in validation and regression loops:

  • pretest runs npx prettier --write ..
  • prebuild runs npx prettier --write . and lint.

Recommended Dev Loop 🔁

  1. Make changes.
  2. Run npm run test.
  3. Run npm run build.
  4. Reload the extension in chrome://extensions.

Troubleshooting

Wrong publication auto-populated for inbox route

  • Ensure you are on a real post route (/inbox/post/<id> or /home/post/p-<id>).
  • Rebuild and reload the extension to pick up latest inbox-resolution logic.

"Could not find substack.sid cookie"

  • Log in at https://substack.com in the same browser profile.

Saved post opens fail with permission errors

  • Confirm downloads and downloads.open permissions are present in the loaded build.
  • Reload extension after upgrading.

Extension not visible after loading

  • Confirm you selected build/extension-package.

Security Notes 🔐

  • Do not share browser profile data.
  • Do not share exported extension storage blindly.
  • The extension uses your own authenticated session to fetch content you can already access.

About

Tool to store selected substack posts offline

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Packages

No packages published