No description
  • TypeScript 99%
  • JavaScript 0.7%
  • HTML 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Ricardo e511ba5fb8 fix(popup): label the drafts control instead of relying on an emoji
The header control rendered as an empty box on Linux font sets without a
glyph for U+1F5D2, leaving the one affordance meant to make drafts
findable as the least visible thing in the header. It now reads "2
drafts" as a chip, which also says what it does without a tooltip.

Folded into v1.6.2 rather than tagged separately: nothing had been
uploaded yet, so re-cutting costs nothing and shipping the worse version
would have cost a review round to correct.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-16 18:55:28 +02:00
.github/workflows ci: bump GitHub Actions to v5 / Node 24 baseline 2026-05-19 17:35:18 +02:00
assets/icon feat(assets): feather icon set at 16/32/48/96/128 + manifest wiring 2026-05-18 16:36:09 +02:00
components feat(popup): move the post-type picker to a vertical rail 2026-08-15 21:52:45 +02:00
core fix(logging): keep the context on log entries 2026-08-16 18:40:47 +02:00
docs/site release: v1.6.0 2026-08-16 15:07:43 +02:00
entrypoints fix(popup): label the drafts control instead of relying on an emoji 2026-08-16 18:55:28 +02:00
public/icon feat(assets): feather icon set at 16/32/48/96/128 + manifest wiring 2026-05-18 16:36:09 +02:00
scripts release: v1.6.0 2026-08-16 15:07:43 +02:00
storage feat(options): record a debug log users can hand over 2026-08-15 19:46:25 +02:00
tests feat(popup): reach drafts from the composer header 2026-08-16 18:45:07 +02:00
.gitignore chore: gitignore wxt zip artifacts at repo root 2026-05-17 22:19:04 +02:00
.prettierignore fix: connect accounts on Firefox and on servers with delegated IndieAuth 2026-08-12 15:23:09 +02:00
.prettierrc.json chore: migrate from Biome to ESLint + Prettier (Biome crashed twice) 2026-05-18 11:50:06 +02:00
bun.lock feat(composer): Markdown toolbar + lazy-loaded preview pane 2026-05-19 18:09:22 +02:00
CHANGELOG.md fix(popup): label the drafts control instead of relying on an emoji 2026-08-16 18:55:28 +02:00
CLAUDE.md docs: bring CLAUDE.md and README up to date with 1.4–1.6 2026-08-16 15:32:01 +02:00
eslint.config.js chore: migrate from Biome to ESLint + Prettier (Biome crashed twice) 2026-05-18 11:50:06 +02:00
LICENSE docs: CHANGELOG, PRIVACY policy, README, LICENSE 2026-05-18 16:40:14 +02:00
package.json release: v1.6.2 2026-08-16 18:51:57 +02:00
playwright.config.ts test(e2e): playwright config + extension loader helpers 2026-05-18 14:20:11 +02:00
PRIVACY.md fix(permissions): drop unused activeTab + correct AI metadata convention attribution 2026-05-19 14:15:21 +02:00
README.md docs: bring CLAUDE.md and README up to date with 1.4–1.6 2026-08-16 15:32:01 +02:00
tsconfig.json chore: wxt prepare as postinstall to generate type declarations 2026-05-18 07:16:55 +02:00
vitest.config.ts feat(menus): define context menu items + prefill builder for all 7 entry points 2026-05-18 09:31:35 +02:00
wxt.config.ts chore(build): drop modulepreload hints from extension pages 2026-08-12 15:55:25 +02:00

🪶 Plume

Cross-browser Micropub client extension. Post to your IndieWeb-compatible blog from any page — toolbar composer or right-click context menus.

Latest release License: MIT

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).

Plume's toolbar popup composing a note with tags and syndication chips

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.

Plume's bookmark composer pre-filled with URL and title from a context-menu click

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.

Plume's options page showing accounts, retry queue, and draft posts

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.

Plume's composer showing the successful post confirmation toast


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 (480720 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=source and 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=category from 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 shortcutAlt+Shift+P opens the composer popup (rebindable in browser settings).
  • IndieAuth + PKCE via chrome.identity.launchWebAuthFlow. 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.
  • No telemetry — your data stays in your browser. See PRIVACY.md.

Install

To load the Chrome build as an unpacked extension:

  1. From the latest release, download the Chrome zip asset (named plume-<version>-chrome.zip) and extract it.
  2. Open chrome://extensions, enable "Developer mode" (top right).
  3. 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.local abstractions (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.