June 1, 2026Updated November 11, 202610 minute read

Supabase Email Templates (2026): Variables, Setup, Fixes

Supabase email templates explained: where they live, every template variable, the June 2026 free-plan change, custom SMTP setup, and fixes for common breakages.

Ajay Sohmshetty

Ajay Sohmshetty

Supabase Email Templates (2026): Variables, Setup, Fixes

Supabase email templates are the HTML emails Supabase Auth sends for signups, magic links, password resets, invites, email changes, and reauthentication. You edit them under Authentication > Emails in the dashboard, using Go template variables like {{ .ConfirmationURL }}. There's one catch from 2026: on new free-plan projects, you can only edit them after setting up custom SMTP.

Last validated: September 2026 against Supabase's email templates⁠, custom SMTP⁠, and rate limits⁠ docs.

Where do Supabase email templates live?

For hosted projects, they're in the dashboard under Authentication > Emails. The direct link is supabase.com/dashboard/project/_/auth/templates, where _ resolves to your project.

Each template has a subject line field and an HTML body editor. There's no drag-and-drop editor: you write raw HTML with template variables in it.

If the editor is locked: since June 3, 2026⁠, new free-plan projects using Supabase's default email provider can't modify their auth templates. Supabase made the change after attackers used free projects to send phishing through rewritten templates. Configure custom SMTP (below) and editing comes back. Projects created before the change keep their templates, and paid plans aren't affected.

If you develop locally or self-host, there's no dashboard editor. With the Supabase CLI, you set each template in supabase/config.toml, pointing it at an HTML file. Self-hosted Docker deployments use GOTRUE_MAILER_TEMPLATES_* environment variables, each pointing to a URL that serves the template's HTML. The variable syntax is the same.

Which email templates does Supabase have?

There are six auth templates, each tied to a moment in the auth flow:

TemplateSends whenMain variable
Confirm signupA user signs up with email and password (if Confirm Email is on){{ .ConfirmationURL }}
Invite userYou invite a user from the dashboard or admin API{{ .ConfirmationURL }}
Magic link or OTPA user requests passwordless sign-in{{ .ConfirmationURL }} or {{ .Token }}
Change email addressA user changes their email{{ .ConfirmationURL }}, {{ .NewEmail }}
Reset passwordA user requests a password reset{{ .ConfirmationURL }}
ReauthenticationA user confirms identity before a sensitive action{{ .Token }}

Supabase also has seven security notification templates you can edit and switch on or off: password changed, email address changed, phone number changed, sign-in method linked, sign-in method removed, verification method (MFA factor) added, and verification method removed.

That's the full list, and it's all account mail. There's no welcome email, receipt, or "your trial ends in 3 days" template. Those are transactional emails your app sends itself (more on that below).

Which variables can you use in Supabase email templates?

Templates use Go's text/template syntax, so every variable has a leading dot and exact casing: {{ .ConfirmationURL }}, not {{ .confirmationUrl }}. A wrong name renders as nothing, with no error.

VariableAvailable inWhat it contains
{{ .ConfirmationURL }}Auth templates except ReauthenticationThe full link the user clicks, with token and redirect
{{ .Token }}Auth templatesA 6-digit one-time code, usable instead of the link
{{ .TokenHash }}Auth templates except ReauthenticationA hashed token, for building your own link
{{ .SiteURL }}All templatesYour project's Site URL
{{ .RedirectTo }}Auth templates except ReauthenticationThe redirect URL passed to signUp, signInWithOtp, signInWithOAuth, resetPasswordForEmail, or inviteUserByEmail
{{ .Email }}All templatesThe user's current email address
{{ .Data }}All templatesThe user's auth.users.user_metadata
{{ .NewEmail }}Change email address onlyThe new address

Security notifications add event-specific variables: {{ .OldEmail }} (email changed), {{ .Phone }} and {{ .OldPhone }} (phone changed), {{ .Provider }} (sign-in method linked or removed), and {{ .FactorType }} (verification method added or removed).

{{ .Data }} is the underused one. If you save full_name in user metadata at signup, {{ .Data.full_name }} greets people by name.

When to use {{ .TokenHash }} instead of {{ .ConfirmationURL }}: the confirmation URL points at Supabase's verify endpoint, which then redirects to your app. That's fine for most apps. If you want the link to hit your app first, for example for server-side auth or a native app with a custom URL scheme, build the link yourself: {{ .SiteURL }}/auth/confirm?token_hash={{ .TokenHash }}&type=email, using the type Supabase documents for that flow. Your app then calls verifyOtp with the token hash and type.

How do you customize a Supabase email template?

The default confirm-signup template is roughly this:

html
<h2>Confirm your signup</h2>
<p>Follow this link to confirm your user:</p>
<p><a href="{{ .ConfirmationURL }}">Confirm your mail</a></p>

A production version adds a logo, a name greeting, a clear button, and a fallback link:

html
<table width="100%" cellpadding="0" cellspacing="0">
  <tr>
    <td align="center" style="padding: 24px 0;">
      <img src="https://yourapp.com/logo.png" alt="YourApp" width="120" />
    </td>
  </tr>
  <tr>
    <td style="font-family: -apple-system, sans-serif; color: #1a1a1a;">
      <h2>Confirm your email</h2>
      <p>Hi {{ .Data.full_name }}, thanks for signing up. Confirm your
      address to finish setting up your account.</p>
      <p>
        <a href="{{ .ConfirmationURL }}"
           style="background: #111; color: #fff; padding: 12px 20px;
                  border-radius: 6px; text-decoration: none;">
          Confirm email
        </a>
      </p>
      <p style="color: #777; font-size: 13px;">
        If the button doesn't work, paste this link into your browser:<br />
        {{ .ConfirmationURL }}
      </p>
    </td>
  </tr>
</table>

Rules that save debugging time:

  • Use tables and inline styles. Outlook renders tables more predictably than modern CSS, and some clients still strip <style> blocks.
  • Include the raw URL as text. Some corporate mail clients break button links. The plain URL is the fallback.
  • Write a specific subject. "Confirm your YourApp account" beats "Confirm your signup" for recognition and spam filtering.
  • Host images on your own domain and give each one alt text, so the email still reads with images blocked.
  • Test every variable with a real signup. Variables fail silently.

What is the Supabase email rate limit?

Supabase's built-in email service sends at most 2 emails per hour for your whole project, not per user. It only delivers to members of your Supabase organization, runs best-effort with no SLA, and Supabase's docs say it isn't meant for production.

So in development, with your own three addresses, everything works. The first real user who signs up gets an email_address_not_authorized error, and the third signup in an hour hits the rate limit.

The fix is custom SMTP. Once it's on, the limit starts at 30 emails per hour and you can raise it under Authentication > Rate Limits. The 30 is a starting safety value for a new sending domain, not a ceiling.

By the numbers

Hourly send cap: default vs custom SMTP

Default email service 2 Custom SMTP (starting) 30
Emails per hour for the whole project. The custom SMTP limit is a starting value you can raise.
Hourly send cap: default vs custom SMTP
ItemValue
Default email service2
Custom SMTP (starting)30

The guide to sending emails from Supabase covers the "email rate limit exceeded" error and the other ways to send, including the Send Email Hook.

How do you set up custom SMTP in Supabase?

Go to Authentication > Emails > SMTP Settings, turn on Enable Custom SMTP, and fill in the host, port, username, password, sender email, and sender name. The provider gives you the host, port, and credentials. The sender email must be one you've verified with that provider. Verify the whole domain with SPF and DKIM rather than a single address, so inbox providers can tie the mail to your domain.

Common choices, checked in September 2026:

ProviderFree optionNotes
Resend3,000 emails/month, max 100/daySimple SMTP setup; Pro from $20/month
Postmark100 emails/monthStrong transactional reputation; Basic from $15/month
Amazon SESNone beyond AWS Free Tier credits$0.10–$0.16 per 1,000 emails; more setup work
SendGrid60-day trial at 100 emails/dayPermanent free plan retired in 2025

Supabase's docs also list ZeptoMail and Brevo. For a deeper comparison, see best transactional email services. For the DNS side (SPF, DKIM, and DMARC), see the email deliverability guide.

Two field-level gotchas:

  • Port: 587 with STARTTLS is the safe default. 465 (implicit TLS) works with many providers. Avoid 25, which many hosts block. If test emails hang and never arrive, check the port first.
  • Username: it's often a fixed string like apikey (SendGrid) or resend (Resend), not your account email. A wrong username makes sends fail with a 500 error, and the Auth logs show the SMTP error. A rate limit returns a 429 instead.

How do you use Dreamlit for Supabase Auth emails?

Dreamlit can build and send the auth templates instead of Supabase's HTML editor plus SMTP. Follow the Supabase Auth setup guide⁠:

  1. Connect your Supabase project to Dreamlit.
  2. In Dreamlit, open Settings > Database Connections, select the connection, and click Setup Supabase Auth. During onboarding, the same setup is offered after connecting.
  3. Dreamlit configures a Supabase Auth Hook and creates six branded workflows: confirmation, magic link, password reset, invite, email change, and reauthentication.
  4. Configure your sending domain⁠, then trigger a password reset or sign-in from your app. Review the email and complete the link or code flow.

Edit these templates in Dreamlit. The Go variables above describe Supabase's own templates; don't paste them unchanged into Dreamlit's editor. Your app still calls Supabase Auth, allowlists redirects, and handles sessions. This setup covers email delivery and templates, not your entire auth implementation.

Common Supabase email template problems and fixes

Emails go to spam

First distinguish Supabase's team-only test sender from custom SMTP. For custom SMTP messages that arrive in spam, check SPF, DKIM, DMARC alignment, and your domain's sending history. Authentication helps receivers verify your mail; it doesn't guarantee inbox placement. After that, watch for image-only emails, lots of links, and a From address that doesn't match your sending domain. The full checklist is in why Supabase auth emails go to spam.

Check the redirect allowlist first. Every URL you pass as redirectTo or emailRedirectTo must be listed under Authentication > URL Configuration. If it isn't, Supabase falls back to the Site URL. Wildcards are supported for preview deployments with changing subdomains. If the allowlist is right, check that your Site URL is correct and that templates use {{ .RedirectTo }} rather than {{ .SiteURL }} when you pass a redirect.

Links expire, and they're single use. Supabase's docs call out email security scanners, such as Microsoft Defender's Safe Links, that open links before the user does and use up the token. If your users are at companies with strict email security, show the {{ .Token }} code as a fallback, or link to a page on your site where the user clicks a button to confirm.

Variables render empty

Check the casing first, then check the data. {{ .Data.full_name }} is blank if you never saved full_name in user metadata at signup.

If a link opens in an in-app browser (tapping it in the Gmail app, for example), the session can land in a browser your app can't read. Offering the 6-digit {{ .Token }} code lets the user type it in instead.

How do you send emails Supabase templates don't cover?

With your own code or a tool built for it. Welcome emails, receipts, trial reminders, and weekly digests aren't Supabase Auth templates. You send them from an Edge Function, a database webhook, or your backend through an email API, or on a schedule with Supabase Cron. The Supabase email guide walks through each option with code.

The emails that matter most in a user's first week are behavioral: a welcome email pointing at the one setup step that matters, then a nudge a day or two later if they haven't done it. See welcome email examples for the triggers and copy.

Supabase email setup checklist

If you're starting fresh, this order avoids the most rework:

  1. Choose your production sender: custom SMTP for Supabase-rendered templates, or the Dreamlit Auth Hook path above. Custom SMTP also unlocks Supabase template editing on new free projects.
  2. Set up SPF, DKIM, and DMARC on your sending domain right away.
  3. Customize the auth templates with your branding and a plain-text fallback link.
  4. Add your redirect URLs under Authentication > URL Configuration.
  5. Raise the email rate limit to fit your expected signups.
  6. Decide how you'll send non-auth emails before you need the first one.

Where Dreamlit fits

For Supabase templates, Dreamlit handles auth email delivery through the Auth Hook path above. For the lifecycle emails that follow, add Dreamlit to your AI agent and ask for a welcome sequence built from your Supabase tables. It shows a preview with real data, and lifecycle drafts stay drafts until you publish.

Start with one follow-up for people who signed up but haven't finished setup. Build it with your agent, keeping it separate from account-critical auth email.

Start a 7-day free trial⁠ or connect your agent. 7-day free trial. Card required. Cancel anytime.

References

  1. Supabase: Email templates⁠
  2. Supabase: Send emails with custom SMTP⁠
  3. Supabase: Auth rate limits⁠
  4. Supabase changelog: Email template customisation on the free tier⁠
  5. Supabase: Redirect URLs⁠
  6. Supabase: Send Email Hook⁠

Frequently asked questions

Where are the email templates in Supabase?

In the dashboard under Authentication > Emails (supabase.com/dashboard/project/_/auth/templates). There's one tab per auth email (Confirm signup, Invite user, Magic link or OTP, Change email address, Reset password, Reauthentication) plus a set of security notification templates. Local CLI projects set templates in supabase/config.toml instead, and self-hosted Docker setups use Auth environment variables that point to template URLs.

What template variables can I use in Supabase email templates?

The auth templates support {{ .ConfirmationURL }}, {{ .Token }} (a 6-digit code), {{ .TokenHash }}, {{ .SiteURL }}, {{ .RedirectTo }}, {{ .Email }}, and {{ .Data }} (the user's user_metadata). {{ .NewEmail }} only works in the Change email template, and Reauthentication gets the code but not the link variables. Security notifications add event variables like {{ .OldEmail }}, {{ .Provider }}, and {{ .FactorType }}.

Why can't I edit my Supabase email templates?

Since June 3, 2026, new free-plan projects that use Supabase's default email provider can't modify auth templates. Configure custom SMTP to turn editing back on. Projects created before that date and paid plans aren't affected.

What is the Supabase email rate limit?

The built-in email service sends at most 2 emails per hour, only to members of your Supabase organization, with no SLA. With custom SMTP the limit starts at 30 per hour, and you can raise it under Authentication > Rate Limits.

Can I send welcome or receipt emails from Supabase templates?

No. The templates cover Supabase Auth emails and account security notifications only. Welcome emails, receipts, and trial reminders need a separate workflow: your own code through an email API, or Dreamlit workflows driven by your Supabase database.

Can Dreamlit manage my Supabase Auth templates?

Yes. Connect your Supabase project to Dreamlit, open Settings > Database Connections, select the connection, and click Setup Supabase Auth. This configures an Auth Hook and creates six branded auth workflows. Your app still calls Supabase Auth and handles redirect URLs and sessions. Domain setup, tests, and ongoing template edits happen in Dreamlit.

Check the redirect allowlist first. Add every URL you pass as redirectTo or emailRedirectTo under Authentication > URL Configuration. If it isn't listed, Supabase falls back to your Site URL. Wildcards are supported for preview deployments. Also check your Site URL, and use {{ .RedirectTo }} instead of {{ .SiteURL }} in templates when you pass a redirect.

Often a corporate email scanner, such as Microsoft Defender Safe Links, opened the link before the user did and used up the one-time token. Show the 6-digit {{ .Token }} code as a fallback, or send users to a page where they click a button to confirm.

About the Author

Ajay Sohmshetty
Ajay Sohmshetty

Co-Founder & CEO

Ajay is Co-Founder and CEO of Dreamlit AI, which runs user activation for software companies. He was previously co-founder and CTO of Harmonic AI and a software engineer at Google. Full bio →

Other articles

Ajay Sohmshetty
Ajay Sohmshetty
May 23, 2025Guides

How to Send Emails from Supabase (Beyond the 2/Hour Limit)

Supabase's built-in email sender allows 2 emails per hour. How to send emails from Supabase in production: custom SMTP, Send Email Hook, webhooks, and cron.

Andrew Kim
Andrew Kim
Nov 11, 2026Guides

Build Lifecycle Email with Your AI Agent: A Supabase Tutorial

Build a Supabase welcome sequence through Dreamlit MCP: let your AI agent read the schema, draft emails, preview real data, send a test, and ask before publishing.