hypercerts-org / hypercerts-org/ePDS
Brand the password-reset email with a light 'Powered by Certified' style for all clients
@aspiers is already working on this.
Since Jul 1, 2026.
- Dominant language
- TypeScript
- Stars
- 8
- Forks
- 4
- Avg merge
- 5d 11h
- Merged PRs (30d)
- 3
Description
Summary
The password-reset email (com.atproto.server.requestPasswordReset) is the only
account email that still ships with the upstream @atproto/pds default styling
(Bluesky-branded). ePDS has re-styled its own auth-service emails, but the
reset email falls through to the inherited pds-core mailer template and so
arrives looking like stock Bluesky.
Request: give the reset email a light, neutral "Powered by Certified" style
that applies to all clients by default, consistent with the existing
auth-service email templates. Optionally — only if it's cheap — allow a client
to override it via client metadata, the way email_template_uri already brands
the OTP email.
Current behaviour
Two separate email systems exist today:
- auth-service emails —
packages/auth-service/src/email/templates.ts
(buildSignInCodeEmail,buildWelcomeCodeEmail,
buildBackupEmailVerificationEmail). These are ePDS-styled, and the OTP one
is additionally client-brandable viaemail_template_uri
(packages/auth-service/src/email/client-template.ts). - pds-core reset email —
com.atproto.server.requestPasswordResetis served
by pds-core (the forked atproto PDS).packages/pds-corecontains no
mailer/email/template files, and auth-service has no password-reset
builder, so the email is produced by the upstream@atproto/pdsServerMailer
resetPasswordtemplate — i.e. the Bluesky default.
A downstream client (Certified) confirmed the reset email arrives Bluesky-styled
while the OTP email is correctly Certified-branded.
Why it matters
For OTP-first clients the reset email is low-frequency (it only appears when a
user sets/changes a password for app-password / ATProto-client use), but it is
the one place the experience visibly breaks brand consistency and references
Bluesky, which is confusing for users of a non-Bluesky PDS.
Proposed change (primary): brand the default reset email
Override the pds-core resetPassword mailer template with a light, neutral
ePDS-styled email that matches the look of the auth-service templates
(system-font stack, generous spacing, the existing #0f1828 accent, a hairline
divider) and ends with a small "Powered by Certified" footer. No per-client
configuration — every client on the PDS gets the consistent, operator-branded
reset email out of the box.
Suggested approach (whichever fits the fork's structure best):
- supply a custom
resetPasswordtemplate to the pds-coreServerMailer, or - add a
buildPasswordResetEmail(...)builder to
packages/auth-service/src/email/templates.tsand route the reset email
through the same sender as the other ePDS emails, keeping all email styling in
one place.
Keeping it in templates.ts would also let it show up in the existing
/preview/emails/* routes for easy iteration.
Optional: per-client styling via client metadata
If it turns out to be easy, extend the existing client-metadata email-template
machinery (client-template.ts, email_template_uri) to also cover the reset
email — e.g. a reset_password_email_template_uri field, reusing the same
SSRF-hardened fetch, allowlist, caching, and {{...}} substitution.
Caveat that likely makes this hard: requestPasswordReset is initiated with
only an account identifier and carries no OAuth client_id, so the PDS has
no client context at send time to decide whose template to use. Unless the reset
is triggered through a client-aware path, per-client branding may not be
resolvable — which is exactly why the operator-level "Powered by Certified"
default above is the primary ask. Treat this section as nice-to-have only.
Acceptance criteria
-
requestPasswordResetemails are styled consistently with the other
ePDS emails (no Bluesky branding) and carry a light "Powered by Certified"
footer. - Applies to all clients with no per-client configuration.
- Plain-text alternative is updated to match (no Bluesky references).
- (Optional) reset email previewable via
/preview/emails/*. - (Optional, only if cheap) per-client override via client metadata, with the
no-client-context caveat resolved or documented.
Pointers
packages/auth-service/src/email/templates.ts— existing branded builderspackages/auth-service/src/email/client-template.ts—email_template_urimachinerypackages/auth-service/src/routes/preview-emails.ts— email preview routespackages/pds-core— currently no mailer override (inherits@atproto/pds)
Filed from the Certified app integration.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.