Transactional email templates
Supacharger uses Supabase Auth templates for account confirmation, OTP and magic-link sign-in, recovery, invitations, email changes, reauthentication, and security notifications.
Install hosted templates under Supabase → Authentication → Email Templates. Files referenced by supabase/config.toml configure only the local CLI stack; editing one environment does not update the other.
Before customizing
Configure production SMTP first. New Free plan projects cannot customize Auth templates while using Supabase's default SMTP service.
Then confirm these settings:
- the canonical Site URL and allowed redirects;
PASSWORDLESS_EMAILmode andOTP_LENGTHinsrc/supacharger.config.ts;SIGN_UP_EMAIL_VERIFICATIONinsrc/supacharger.config.ts;- hosted Confirm Email policy;
- Email OTP Expiration; and
- whether secure email change is enabled.
Template URLs and copy must match those settings.
Template set
Review every enabled authentication template:
- Confirm signup
- Magic link or OTP
- Reset password
- Invite user
- Change email address
- Reauthentication
Also enable appropriate notifications for password, email, phone, sign-in-method, and verification-method changes.
The Supabase Auth template examples provide small, auditable OTP and link examples. Apply product branding only after the destinations and token variables work.
Which template Supabase sends
The API method does not select a template by name. Supabase combines the requested operation with the account's current state and the hosted Confirm Email policy. In particular, shouldCreateUser: false prevents an unknown address from being registered; it does not force the Magic link or OTP template for an account that exists but is still unconfirmed.
| Request | Account state | Relevant option or policy | Result | Hosted template |
|---|---|---|---|---|
| Email-and-password signup | Unknown address | Confirm Email enabled | Creates an unconfirmed user and sends signup verification | Confirm signup |
| Email-and-password signup | Unknown address | Confirm Email disabled | Creates and confirms the user immediately; no verification message is needed | None |
| Email-and-password signup | Existing, unconfirmed account | Confirm Email enabled | Treats the request as another attempt to complete signup, subject to email rate limits | Confirm signup |
| Email-and-password signup | Existing, confirmed account | Confirm Email enabled | Returns an obfuscated existing-account response to avoid disclosing registration state | None |
Passwordless signInWithOtp() | Unknown address | shouldCreateUser: true and Confirm Email enabled | Creates an unconfirmed user and starts signup verification | Confirm signup |
Passwordless signInWithOtp() | Unknown address | shouldCreateUser: true and Confirm Email disabled | Creates and confirms the user, then sends the passwordless credential | Magic link or OTP |
Passwordless signInWithOtp() | Unknown address | shouldCreateUser: false | Rejects the request with otp_disabled; no user is created | None |
Passwordless signInWithOtp() | Existing, unconfirmed account | Either shouldCreateUser value | Treats the account as an incomplete signup | Confirm signup |
Passwordless signInWithOtp() | Existing, confirmed account | Either shouldCreateUser value | Starts passwordless sign-in | Magic link or OTP |
| Resend signup verification | Existing, unconfirmed account | Resend type signup | Sends another signup credential, subject to email rate limits | Confirm signup |
| Password recovery | Existing account | Recovery request | Sends the password-reset credential | Reset password |
| Password recovery | Unknown address | Recovery request | Does not deliver a message; the public response may remain deliberately non-enumerating | None |
| Administrator invitation | Invited address | Admin invite request | Sends the invitation credential | Invite user |
| Email-address change | Authenticated user | Email update request | Sends the address-change credential according to secure email-change policy | Change email address |
| Reauthentication | Authenticated user | Reauthentication request | Sends the verification code | Reauthentication |
The Magic link or OTP name describes one template whose content chooses the passwordless experience. Passwordless mode is exclusive: include only {{ .Token }} for otp, or only the application-owned {{ .TokenHash }} link for link. The Confirm signup template is separate and follows SIGN_UP_EMAIL_VERIFICATION; it may include both alternatives only for otp-and-link. Supacharger's SSR flow supplies /auth/confirm?next=... as the complete .RedirectTo for link mode. Use this HTML link where a link is configured:
<a href="{{ .RedirectTo }}&token_hash={{ .TokenHash }}&type=email">...</a>
Do not append another /auth/confirm path. Do not place the token hash on /auth/callback or /account/login.
An unconfirmed Auth row therefore does not behave like a confirmed existing account. Supabase Auth explicitly treats a missing or unconfirmed user as someone who has not completed signup before it chooses the confirmation path. See the passwordless email guide, signInWithOtp() reference, and Auth template reference.
All confirmation links and email OTPs are one-time credentials. If a template exposes both forms for one request, successfully using either consumes that request and makes the other form invalid. Disable SMTP-provider click tracking and automated link rewriting so scanners or relay redirects do not consume or deform the credential before the user opens it.
Important variables
| Variable | Use |
|---|---|
{{ .Token }} | Configured-length email OTP or reauthentication code |
{{ .TokenHash }} | Hashed token used to construct an application-owned confirmation link |
{{ .ConfirmationURL }} | Supabase-generated verification URL |
{{ .RedirectTo }} | Per-request allowed redirect supplied by the application |
{{ .SiteURL }} | Fixed fallback Site URL configured in Supabase |
Use {{ .RedirectTo }} when Supacharger supplies the destination for a request. Do not replace it with {{ .SiteURL }} merely because both happen to share the same origin in production.
Operating rules
- Use only the configured OTP or link method in a passwordless email.
- Include both signup alternatives only when
SIGN_UP_EMAIL_VERIFICATIONisotp-and-link. - Do not hard-code an expiry that differs from Email OTP Expiration.
- Disable provider click tracking that rewrites one-time URLs.
- Avoid tracking pixels in security-sensitive messages.
- Never use user-editable metadata for authorization decisions.
- Test each template in real desktop and mobile mail clients.
The complete installation sequence is in Install email templates.