Skip to content

build spec #1

Description

@jeremymanning

Summary

Build a from-scratch, open-source Thunderbird MailExtension that adds Gmail-style snooze to email: hide a message from the inbox now, and have it return automatically at a chosen time. It includes a Gmail-style quick-options menu and a slick, themed calendar date/time picker, triggered by a single-key b shortcut (plus a toolbar button and context menu). It runs fully locally — no external service, no Gmail API.

Why build our own

  • Thunderbird has no native snooze.
  • Gmail's server-side snooze isn't reachable via IMAP or the Gmail API (we confirmed this), so a Thunderbird key can't trigger real Gmail snooze.
  • The polished existing add-on (Snooze Ninja) is paid/closed-source.
  • Building our own gives full control over behavior and a UI we can make exactly as slick as we want.

Goals

  • Single-key b opens a snooze menu, just like Gmail.
  • Gmail-style quick presets plus a custom date/time picker.
  • A slick, smooth, themed UI — matches Thunderbird's theme (light/dark) and the OS accent.
  • Reliable local return of snoozed messages that survives Thunderbird restarts and missed alarms.
  • Works with a Gmail (IMAP) account; ideally account-agnostic.

Non-goals (v1)

  • No server-side/cross-device return. The return happens while Thunderbird is running; if TB was closed at the due time, the message returns on next launch. Document this tradeoff prominently.
  • No mobile, no natural-language time parsing.

User experience

Triggering the snooze menu

  • Press b with a message selected/focused in the message list (true single key, like Gmail).
  • Also available via a toolbar button (message list + reader) and a right-click "Snooze…" context menu item.
  • Acts on the focused message, or on all selected messages if several are selected.
  • b must not fire while typing in a search box, the quick-filter, a compose window, or any text input (respect focus — mirror tbkeys' stopCallback).

The snooze menu (Gmail-style)

A small popup anchored near the message/toolbar, with rows showing icon + label + the computed return time (right-aligned), hover highlight, and full keyboard nav (↑/↓, Enter, Esc):

  • Later today — default +3 hours; if that lands too late, fall back to "This evening" 6:00 PM (configurable).
  • Tomorrow — next day at the morning time (default 8:00 AM). e.g. "Tomorrow, 8:00 AM".
  • This weekend — upcoming Saturday at morning time (if already the weekend, next Saturday).
  • Next week — upcoming Monday at morning time.
  • Pick date & time… — opens the calendar picker.

The calendar date/time picker (the slick part)

  • Themed month calendar: current month, prev/next navigation, today highlighted, past dates disabled.
  • Pick a date → choose a time: preset chips (Morning 8:00 / Afternoon 1:00 / Evening 6:00) plus a custom time input.
  • Smooth transitions (month slide, selection pop), rounded corners, soft shadow, clear focus rings, a live preview of the resulting return datetime, and Confirm / Cancel.
  • Fully keyboard-drivable and accessible.

Theming & feel

  • Match Thunderbird's active theme (light/dark) and OS accent color. Use Thunderbird's in-content theme CSS variables and prefers-color-scheme; no hard-coded colors.
  • Lightweight and instant — vanilla JS + CSS (no heavy framework) for control, load speed, and no layout jank.

Technical design

Add-on type & manifest

  • Thunderbird MailExtension. Recommend Manifest V2 for the broadest, most stable API coverage on current Thunderbird (revisit MV3 later).
  • Permissions (approx.): messagesRead, messagesMove, messagesUpdate/messagesModify, accountsRead, folders, storage, alarms, menus.
  • Components: background script; message-display action + browser action (toolbar button + popup); menus; options page; and an Experiment API for the single-key b handler (below).

Message & folder operations (MailExtension APIs)

  • Target messages via mailTabs.getSelectedMessages() / message-display APIs.
  • Ensure a "Snoozed" folder exists per account (folders.query / folders.create); on Gmail this becomes a label.
  • Snooze = messages.move(ids, snoozedFolder) + persist a schedule entry.
  • Return = messages.move(ids, originalFolder) + messages.update(id, {read:false}) (and optionally {flagged:true} / a tag) for visibility.

Scheduling & return

  • Persist each snooze in storage.local: { key, headerMessageId, accountId, originalFolderId, snoozedFolderId, returnAtEpochMs }. Track by headerMessageId (stable across moves), since numeric message ids can change.
  • Use browser.alarms for the next due time; on onAlarm, process everything now due.
  • On startup (and periodically), scan for overdue entries and process them → handles the "TB was closed" case.
  • Robustness: local-time math with DST awareness; message-not-found (moved/deleted) → graceful skip; guard against double-returns.

Keyboard shortcut (single-key b)

  • The WebExtension commands API generally can't bind a bare letter (needs a modifier). For a true single-key b, use a small Experiment API that installs a keydown listener on the mail:3pane window — exactly the technique tbkeys uses (Mousetrap + a focus-aware stopCallback). Reference: github.com/wshanks/tbkeys (addon/implementation.js, addon/modules/mousetrap.js).
  • Make the key configurable (default b). Ensure it doesn't double-bind if tbkeys is also installed (we intentionally left b unbound in tbkeys).
  • Note: shipping an Experiment API means the add-on is fully privileged (not a "lite"/store-listable build) — fine for a self-hosted / sideloaded add-on.

Options / settings

Configurable: morning time, "later today" offset / evening time, weekend day, Snoozed folder name, return behavior (mark unread, flag/tag), the shortcut key, and per-account enable.

Suggested file layout

manifest.json
background.js                 // scheduler, alarms, orchestration
lib/schedule.js              // compute preset datetimes + persistence
lib/messages.js              // move / return / ensure-folder / mark helpers
popup/menu.{html,js,css}     // Gmail-style quick menu
popup/calendar.{html,js,css} // slick date/time picker
options/options.{html,js,css}
experiment/keys.js + schema.json  // single-key `b` handler (tbkeys-style)
icons/

Implementation plan (parallelizable — for batches of agents)

Each task gets its own branch + PR referencing this issue, with frequent commits. After the scaffold, most run in parallel:

  • T0 Scaffold — manifest, background stub, build/package to .xpi, load in TB. (blocking)
  • T1 Message ops — ensure Snoozed folder; move to/from; mark unread/flag.
  • T2 Scheduler — storage schema, alarms, startup catch-up, edge cases (interfaces with T1).
  • T3 Snooze menu UI — Gmail-style quick options + computed times + keyboard nav.
  • T4 Calendar picker UI — slick themed date/time selector + animations.
  • T5 Theming — light/dark + system accent via TB theme vars; polish (follows T3/T4).
  • T6 Keyboard b — Experiment API keydown handler (tbkeys-style), configurable.
  • T7 Toolbar button + context menus.
  • T8 Options page.
  • T9 Integration + testing on a real Gmail account (final).

Testing plan (real messages, no mocks)

  • Manual end-to-end on a real Gmail/IMAP account in Thunderbird:
    • Snooze via b → menu → each preset and a custom date; verify the message leaves the inbox into "Snoozed" and returns at the chosen time, unread.
    • Return while TB is running (alarm) and return after restarting TB across the due time (startup catch-up).
    • Multiple selected messages; a threaded conversation.
    • Timezone/DST sanity; message deleted/moved before return → graceful no-op.
  • UI: screenshots of the menu and calendar in light and dark themes; check alignment, contrast, overlap, spacing, and animation smoothness.
  • Don't sign off until verified with real examples.

References / code to borrow

  • tbkeys (github.com/wshanks/tbkeys, MIT-style) — single-key handling via Experiment API + Mousetrap + focus-aware stopCallback. Reuse the keyboard technique.
  • Open-source Thunderbird snooze add-ons on addons.thunderbird.net (check each listing for a source link — e.g. "Snooze – Remind Me Later", "SnoozeFlow"): reference move/alarm/return mechanics. Do not copy non-open code (Snooze Ninja is paid/closed).
  • Thunderbird MailExtension API docs: messages, folders, alarms, menus, messageDisplayAction, storage.

Open questions / decisions to confirm

  1. Preset set & default times — confirm: Later today (+3h), Tomorrow 8:00, This weekend Sat 8:00, Next week Mon 8:00. Add "Someday"/"Next month"?
  2. Return surfacing — unread only, or also flag/star/tag? (True "bump to top" isn't possible for date-sorted IMAP; unread + flag is the realistic signal. Stretch: investigate re-dating/re-injection to bump — risky.)
  3. Scope — account-agnostic, or Gmail-only for v1?
  4. Snoozed storage — dedicated "Snoozed" folder/label (recommended). Confirm the name.
  5. Manifest V2 vs V3.

Constraints

  • Repo is public — never commit private info (email addresses, account data, message contents, tokens). Keep all code generic.
  • Local-only; document the "Thunderbird must be running for the timed return" tradeoff prominently in the README.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions