Skip to content

Draft reminder email: email organizers once about a draft they haven't published #560

Open

Description

@richshaw

Why

Nothing brings an organizer back to a draft they didn't finish. #532 built an email for this, but it sat on top of the review-page stack, which is closed while the draft → publish → share flow is redesigned (#498). The automatic email doesn't depend on that design, so it can ship on its own.

What to do

Rebuild #532's email as a new PR from main. The code is on the branch claude/issue-506-draft-email, and #532's diff shows only the email.

Bring over:

  • The scheduled email. It goes out 3 hours after a draft is started (DRAFT_NUDGE_DELAY_HOURS in src/lib/draft-nudge.ts), and only while the signup is still an undeleted draft, has a slot filled in, and its organizer can still edit it. Drafts started more than 48 hours ago get none, so the first deploy doesn't email every old draft.
  • Not for drafts an AI connector created. The assistant already gives the organizer the links.
  • Jobs. draft-nudges.dispatch (a scan every 10 minutes) and draft-nudges.send (one job per due draft, which checks every rule again first). A draft.nudge_sent activity row stops a second send. The shared "which rules failed" SQL is src/jobs/due-rules.ts.
  • The template and subject ("Ready to publish: {title}"), in src/email/subjects.ts.
  • Turning it off. Each email has a link and List-Unsubscribe headers. The link opens /unsubscribe/drafts, which asks first and can turn the emails back on. One-click unsubscribe posts to POST /api/public/draft-email-optout. Both are token-checked and rate-limited per IP. The setting is one column, organizers.draft_emails_opted_out_at. Its migration needs a new number after main's latest.
  • Docs. The privacy page (bump "Last updated"), docs/telemetry.md, the help page line, and the jobs section of CLAUDE.md.
  • pnpm drafts:due, like pnpm reminders:due.

Leave for the redesign (#498, #506):

  • "Not yet. Email me a link to finish later". It was a button on the review page.

Changes from #532:

  • The main button. "Check it and publish" opened the review page. On main, /app/signups/[id] opens the Build tab, so the button should say something that fits, such as "Finish and publish".
  • The "So far" line. "12 slots · 3 days · 3 people each" used the review page's headline helper (signupHeadline, from Open a draft with something in it on "Check your signup, then share it" #528). Either bring that small pure function over with its tests, or drop the line.

Decisions (defaults from #532)

  1. Delay: 3 hours, and only for drafts started in the last 48 hours.
  2. Off switch: per organizer, through the link in the email. There's no settings page for it.
  3. AI connector drafts: they don't get the email.
  4. New: keep the "So far" line, or drop it?

Watch for

  • One worker. As with reminders, the check that stops a second email holds only with one worker process.
  • Trust docs change in the same PR.

Done when

  • A due draft gets exactly one email. A published, deleted, empty, opted-out, connector-made or too-old draft gets none. Email organizers once about a draft they haven't published #532 has a DB test for each case.
  • The template renders in the worker test.
  • The legal pages say organizers may get one email about an unpublished draft.
  • pnpm lint && pnpm typecheck && pnpm knip && pnpm test and pnpm test:db pass.

Activity

  1. added
    enhancementNew feature or request
    pipeline:uxChanges what a person using OpenSignup sees or does
    on Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpipeline:uxChanges what a person using OpenSignup sees or does

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions