Fixed Apple Music embeds not working in the email preview—Apple now requires the name slug in embed URLs
Fixed 500 errors when previewing transactional emails (e.g. subscription confirmation) with invalid template syntax like empty variable tags in the Fancy Mode editor
Cleaned up the automations UI
Added Firewall rule for penalizing email addresses which failed to subscribe to other newsletters
Improved UX for subscribing whilst authenticated as a subscriber to another newsletter
Improved various parts of the automations UI
Improved the copy of premium emails sent to paid subscribers
Fixed the janky styling of the forgotten password page
Fixed (hopefully!) another infinite-reload bug
Fixed a bug when navigating across integrations drawers
Improved performance of Fancy Mode editor
Added Firewall rules around common spammy patterns
Redesigned the security/account pages
Added the ability to filter comments by email or date
Finished cleaning up the docs
Improved the Archives marketing page
Fixed a remaining subset of CORS/preload issues
Retooled KYC messaging
Moved paid subscriptions to the sidebar if enabled
Added "other" fallback archive import for unbuilt importers
Fixed "alternatives" cards looking wonky
Slightly restyled comments
Fixed trivial timezone bug with Stripe subscriptions
Started rolling out Cloudflare Turnstile on custom domains to reduce bot signups
Added embedded checkout to upgrade flows for paid subscriptions
Renamed "Archive design" to "Archives" for clarity
Exposed a bunch more newsletter settings to the public API
Added a bunch of FAQs to feature pages
Fixed one last R2 issue with the portal list page
Fixed a mismatch in newer Stripe API version cadences for paid subscriptions
Rebuilt the snippet editor to allow naked mode and be full page
Standardized some buttons in the manage subscription view and added a backlink
Added a new dynamic drilldown component for nested data
Added initial backend support for further webwall customization
Emails that are scheduled rather than immediately sent now get hit with validators at schedule time rather than when they get published
Fixed bug where we were failing clientside to show a new paid subscription price after creating it
Added a better description for when you're missing your DMARC policy
Fixed a few benign API/validation bugs
Tweaked paid subscriptions behavior to just always mark the most recently created price as the default
Removed the duplicate email OutgoingEmailValidator and now just prompt for confirmation before sending
Improved OpenAPI schema for RSS feed endpoints
Bumped up css-inline which should fix some edge cases where inline styles were getting overridden
Fixed bug with updating email addresses in the manage subscription page
Fixed bug with going from PWYW to non-PWYW if you already had a dormant PWYW price
Started rejecting email bodies that look like they have frontmatter since it's probably a mistake
Fixed pagination bug with deliveries in the email analytics drilldown
Fixed bug with the CLI modifying irrelevant files
Fixed benign Unicode surrogate bug
Fixed benign bug in the automation analytics endpoint
Started vouching for email addresses that have old ESP suppressions if they complete double opt-in
Added subject line editing to Naked Mode
Added the ability to expand the subscriber import drawer to full width
Improved the timezone/locale input
Desensitized the RSS feed alerts
Fixed broken link in docs
Improved copy for empty state on /subscribers
Added auto-linking for type IDs in /requests
Added a generator meta tag for Simple Analytics
Added a confirmation step for deleting your account
Fixed bug with migrating your API version if you had many keys
Fixed bug with unsubscription events summary being different than the drilldown
Improved retry logic on emails which we had to backoff due to rate limiting
Cleaned up the "getting started" docs
Debounced the number of times we update RSS subscriber count for a newsletter
GA'd custom email templates via the whitelabeling entitlement
Fixed bug with TypeID on embedded forms
Started warning people about API keys in frontend places
Allowed X-Buttondown-Live-Dangerously to bypass CORS in /v1/images
Cleaned up more blog post descriptions
Cleaned up more docs
Fixed 500 when passing invalid parameters to send-draft endpoint
Removed the ability to unsubscribe directly from the "portal dashboard"
Fixed bug with the CSS editor's current-line highlighting
Fixed bug where we were incorrectly showing blockquotes as dark mode in the preview
Fixed bug where we were not sending out invitations to older accounts that already existed
Fixed bug with inconsistent image sync in the CLI
Fixed bug where naked mode welcome emails still showed frontmatter
Fixed bug where we failed to sync authors in RSS feed with very long names
Started flagging default/placeholder alt text in the email validator
Added Obsidian to the /stack
Started setting unsubscription_date for imported unsubscribers
Fixed bug where we threw a 500 if you tried to aggregate by click/open date
Started surfacing support threads in the /inbox
Improved the subscription experience on mobile by turning the CTA into a modal
Fixed bug with LinkedIn social icons not being set
Moved social links from Archives to general settings because they're used for emails, too
Fixed the Integrations marketing page looking janky
Fixed bug where we were failing to parse reply-to-replies in Postmark
Improved the /changelog layout
Fixed a bug where we weren't showing KYC questionnaire to users who hadn't finished/skipped onboarding
Removed paused subscriptions and merged them into cancellations
Fixed bug where whitelabeling was not toggleable from the general settings
Fixed bug where Markdown versions of docs weren't resolving correctly
Added Swedish as a supported locale for subscriber-facing content
Fixed bug with double-conversion from cents-dollars for PWYW prices in USD
Added the ability to filter and send to subscribers based on open/click rate
Improved process of keeping author's sending email in sync when they add a new sending domain
Started truncating API requests to the past month rather than the past year
Started prompting folks who were referred by a friend/colleague to select the username for referral's purposes
Fixed display issue when we show null percentages
Added a theme option to tweak size of blockquotes
Allowed passing in subscriber_id alongside POST /v1/comments
Fixed a bug where we missed a folder when uploading assets to R2
Exposed the per-subscriber open and click rates via the API
★ Started automatically parsing all Postmark and Mailgun emails for custom domains
Added X-Buttondown-Live-Dangerously to bypass SVG prohibitions in /v1/images
Added the ability to make certain images non-zoomable
Fixed bug with input validation on analytics endpoints
Started checking ESP suppressions in firewall
Fixed QR code visibility in dark mode
Added support for PWYW subscriptions with specific cadences
Added referral source autocompletion during onboarding
Fixed some jankiness with the test mode banner on emails
Removed the ability to unsubscribe unactivated subscribers
Polished and published /settings/data
Added syntax highlighting to code snippets in comments
Documented the X-Buttondown-Bypass-Firewall header
Cleaned up a few jank areas in Lovelace
Fix a broken doc and update a bunch more besides
Fix some broken images
Renamed css_tokens to theme_configuration
Fixed bug with double h1 on archive pages
★ Migrated our static assets to be hosted on Cloudflare R2, reducing failures during deploys
Added basic metadata extraction + application for folks migrating from Substack/Beehiiv
Fixed a race condition with clientside currency conversion when setting up paid subscriptions
Fixed bug where we incorrectly failed to parse valid URLs with unicode in them when rendering Markdown
Fixed bug where we were proxying all SimpleAnalytics data onto our account
Added some more onboarding todos
Fixed bug where we weren't showing images in tracked replies
Fixed bug where export → Markdown wasn't working for individual emails
Ported the new date widget to /analytics
Standardized and cleaned up our context menu component
Improved reply HTML sanitization even more
Started prompting disabled users to provide socials
Started rejecting SVGs for newsletter icons b/c they break in emails
Started stripping as_embed param from magic link redirects so people don't get stuck in a tiny box
Migrated /v1/bulk_actions to use TypeID
Fixed bug where we asked people to supply KYC info even if they already had
Fixed some more edge cases with HTML in the /inbox
Cleaned up the footer for emails we send to premium subscribers
Added a cross-platform date picker
Fixed tiny bug where the link checker was flagging template tags like [Click here]({{ manage_subscription_url }})
Fixed bug where we weren't sanitizing HTML from emails in the inbox/conversation views
Improved editor toolbar on mobile
Fixed bug where sending an email via bulk action right after sending a draft could send the draft variant of the email
Changed the date-based cutoff for tracking domains to a flag-based one
Cleaned up a whole bunch of Archives docs
Migrated even more forms to use Formisch and a slightly revised design system
Added a few new lifecycle emails and removed stale ones that were dead code
Fixed benign bug in /v1/emails
Started deleting stale ESPSuppressions
Fixed bug where announcement bar was showing even in embedded subscribe forms
Fixed (hopefully) some transient deadlock/DB race conditions that were slowing down our asynchronous action runner
Fixed bug where we were asking disabled newsletters to submit KYC information even if they already had
Improved the storybook: better routing, a keyboard shortcut menu, and a request pane
Start exposing reasons why a subscriber is blocked by the firewall to authors
Start to require/add a custom CNAME for tracking domains for larger senders to derisk our own deliverability
Cleaned up a whole bunch of docs
We now have an admin action for ESPSuppression to allow removing/purging that suppression from the backing ESP
Fixed some broken links in our KYC disablement emails
Completely migrated off of DNSimple in favor of Cloudflare
Deleted a lot of old code (removed old dependencies, unused ESPs, etc.)
Migrated most forms to use Formisch and a slightly revised design system
Migrated most forms to use Formisch and a slightly revised design system
Deleted a lot of old code (removed old dependencies, unused ESPs, etc.)
Completely migrated off of DNSimple in favor of Cloudflare
Fixed some broken links in our KYC disablement emails
We now have an admin action for ESPSuppression to allow removing/purging that suppression from the backing ESP
Cleaned up a whole bunch of docs
Start to require/add a custom CNAME for tracking domains for larger senders to derisk our own deliverability
Start exposing reasons why a subscriber is blocked by the firewall to authors
Removed redis requirement from demo to cut down on 500s
Fix bug where tags could not be programmatically set for certain weird billing cases
Fix bug where some automation actions had no label set for them
Fix bug where invoices were showing in $$$ regardless of currency
Fix bug where we allowed people to bypass the CSS billing constraints via API
Started running the email analytics cacher more often now that it's cheap
We now only see newsletters in the KYC queue if they've filled out the /home questionnaire after being disabled
Merged in a change to embedded checkout to allow better plexing between monthly/annual
Redesigned callouts to be less visually chaotic
Refactored firewall for improved functionality/productivity
Added initial (janky) support for surveys in the archives
Bumped up mypy + django-stubs pretty heavily to yield some performance benefits
The mobile variant of dialogs now triggers at a narrower viewport
Expanded the TTL for Cleantalk responses from 3 to 30 days
Moved QR code generation serverside to fix bug where icons weren't being embedded
Migrated from ImprovMX to Cloudflare email workers for routing @buttondown.com
Disabled users are now prompted in-app to answer questions about their newsletters to help out KYC
Migrated some straggling domains' NS servers (but not ownership) from DNSimple to Cloudflare