- TypeScript 99.2%
- JavaScript 0.5%
- HTML 0.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
The type picker was presentational only. Switching away from a target type left that type's URL in composer state, and `handleSubmit` posts the whole state — so the payload still carried the stale property, and Micropub servers discover the post type from the properties they receive. Pasting a URL into the Bookmark composer, then switching to Article and posting, sent a 26 KB article that still carried `bookmark-of`; the server checked that before its "name + content ⇒ article" rule and filed the post under /bookmarks/. Bookmark → Reply was the same leak with both `bookmark-of` and `in-reply-to` on the wire. The sync effect now owns all four target fields through `targetFields` in the new `core/post-target.ts`: the field the selected type uses carries the URL, the other three are cleared. Nothing is lost, because the composer holds the typed URL in its own state and re-populates whichever field the next type needs. Draft scoping improves for free — an article that started as a bookmark now files under "general" instead of the bookmark's URL. |
||
| .github/workflows | ||
| assets/icon | ||
| components | ||
| core | ||
| docs | ||
| entrypoints | ||
| public/icon | ||
| scripts | ||
| storage | ||
| tests | ||
| .gitignore | ||
| .prettierignore | ||
| .prettierrc.json | ||
| bun.lock | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| eslint.config.js | ||
| LICENSE | ||
| package.json | ||
| playwright.config.ts | ||
| PRIVACY.md | ||
| README.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
| wxt.config.ts | ||
🪶 Plume
Cross-browser Micropub client extension. Post to your IndieWeb-compatible blog from any page — toolbar composer or right-click context menus.
Latest release · Landing page · Privacy
Quick composer
Click the toolbar feather. Type. Pick tags. Choose where to syndicate. Post.
The whole loop takes ~5 seconds and never leaves the page you were reading.
Keyboard shortcut: Alt+Shift+P (rebindable).
Right-click to bookmark, reply, quote, like
Right-click any page, link, image, or text selection. Plume opens with the right fields pre-filled — URL of what you're bookmarking, page title, the passage you highlighted as a Markdown blockquote with citation.
Drafts, retry queue, multi-account
Auto-save while you write — drafts survive across popup closes. Posts that hit a network blip get queued and retried in the background with exponential backoff. Connect multiple Micropub blogs and switch between them.
Posted, with a link back
When the server confirms, Plume shows you the URL of your new post and closes. Your content lands on your blog with whatever syndication targets and metadata you chose.
Features
- Quick composer in the toolbar popup — notes, articles, replies, bookmarks, likes, reposts, quotes, photos, picked from a vertical rail so every type is one click away.
- Markdown toolbar + preview — bold/italic/link/list/quote/code/heading buttons above the textarea; toggle a live rendered preview pane (snarkdown + DOMPurify, lazy-loaded).
- Pop-out composer (
↗button) opens the same composer in a tab at desk-width (480–720 px) for long-form article writing. - Capture from anywhere — right-click any page, link, selection, or image to post.
- MediaPicker — browse files already on your server via
?q=sourceand reuse them in new posts. - Multi-account — connect multiple Micropub blogs, switch between them.
- Drafts auto-save while you type; restore on next popup open (7-day TTL).
- Retry queue with exponential backoff (30s → 24h) for failed posts.
- Live-updating queue and draft lists on the options page (subscribed to
chrome.storage.onChanged). - Server-aware — reads
?q=config,?q=post-types,?q=categoryfrom your blog. Post types are labelled with your server's own names, types it doesn't advertise are dimmed, and detected extension properties get "✓ Server supports" badges. - AI transparency metadata — optional per-post fields disclosing AI involvement.
- Keyboard shortcut —
Alt+Shift+Popens the composer popup (rebindable in browser settings). - IndieAuth + PKCE via
chrome.identity.launchWebAuthFlow, or through an ordinary browser tab where that API is missing (Firefox for Android) or turned off in settings. Connecting an account shows each step as it happens — permission, endpoint discovery, token exchange, server config — so a failure says which part failed. - A debug log you can hand over — errors are always recorded; tick one box to record the steps leading up to them. Access tokens and authorization codes are stripped before anything is written, so it's safe to paste into an issue.
- A welcome page on first install that explains Micropub and IndieAuth without assuming you already know them.
- Narrow permissions — install asks for nothing broad; host permissions requested per-account. Plume also runs a small script on its own sign-in callback page,
https://rmdes.github.io/plume/callback.html, to read the sign-in result from that page's address and hand it to the extension; on the tab-based sign-in the authorization code and state do pass through that GitHub Pages URL and may reach its server logs, but the code is single-use and bound to a PKCE verifier that never leaves your browser, so it's useless on its own. It runs nowhere else. - No telemetry — your data stays in your browser. See PRIVACY.md.
Install
- Chrome Web Store: Install on Chrome
- Mozilla AMO: Install on Firefox
- Direct download: latest release (Chrome zip + Firefox zip + source)
To load the Chrome build as an unpacked extension:
- From the latest release, download the Chrome zip asset (named
plume-<version>-chrome.zip) and extract it. - Open
chrome://extensions, enable "Developer mode" (top right). - Click "Load unpacked" and select the extracted directory.
Build from source
bun install
bun run dev # Chrome dev mode (hot reload)
bun run dev:firefox # Firefox dev mode
bun run build # Production build
bun run test # Unit tests (vitest) — note `run`: bare `bun test` uses
# Bun's own runner, which doesn't understand vitest mocks
bun run test:e2e # Playwright E2E (chromium)
bun run screenshots # Regenerate the screenshots above
Architecture
core/— pure-logic modules (Micropub HTTP, IndieAuth + PKCE, retry executor, normalization, extension detection)storage/—chrome.storage.localabstractions (accounts, drafts, queue, defaults, logs, session)entrypoints/— extension surfaces (popup, options, background service worker)components/— shared Preact components (composer chips, AI metadata panel, MediaPicker)tests/— vitest unit tests and Playwright E2E (chromium)scripts/— capture-screenshots, lint-fetch privacy enforcement
Built with WXT + Preact + TypeScript. Linted with ESLint + Prettier.
Project-specific conventions and gotchas are documented in CLAUDE.md.
License
MIT — see LICENSE.



