Files
supabase/apps/studio/components/interfaces/Auth/EmailTemplates/EmailTemplates.constants.test.ts
32d1bdd534 fix(studio): reduce doc link density in auth email template builder (#47250)
## I have read the CONTRIBUTING.md file.

YES

## What kind of change does this PR introduce?

- Studio UI update (auth email template builder)
- Docs update (hosted email templates guide + local dev cross-link)

Closes DOCS-1086.

## What is the current behavior?

- Linear item: Reduce link density in the template builder UI
- Page header shows a **Terminology** link and **Docs** button (local
development guide)
- Template variables footer shows **Terminology** · **Local
development**
- Local development editing is only mentioned in one sentence on the
hosted docs page; easy to miss once Studio no longer links there
directly

## What is the new behavior?

- Page header: **Docs** button only →
`/guides/auth/auth-email-templates`
- Template variables: single **Terminology** link → `#terminology`
(variable pills still have hover tooltips)
- Hosted docs: **Editing email templates** split into hosted vs
local/self-hosted, with a callout linking to the local development guide
- Local dev guide: opening paragraph links back to the hosted guide for
shared terminology and patterns

### Proof: Template builder has fewer outbound doc links

| Before | After |
|--------|-------|
| Header Terminology + Docs (local dev guide); footer Terminology ·
Local development <img width="1440" height="1100" alt="image"
src="https://github.com/user-attachments/assets/3325f43b-5830-4b85-ba56-2ba4c5b04bcd"
/> | Docs button only (hosted guide); single Terminology link above
variables <img width="1440" height="1100" alt="image"
src="https://github.com/user-attachments/assets/90c8cfff-89bd-46d5-b336-2f9dd50d37e3"
/> |

**Before (`origin/master`)**

- Header: **Terminology** link + **Docs** button → local development
guide
- Template variables: **Terminology** · **Local development**

**After (this PR)**

- Header: **Docs** button only → [Email
templates](https://docs-git-nikrichers-docs-1086-reduce-link-densi-bf6705-supabase.vercel.app/docs/guides/auth/auth-email-templates)
(preview)
- Template variables: single **Terminology** link →
[Terminology](https://supabase.com/docs/guides/auth/auth-email-templates#terminology)
- Local development path documented at [Editing email
templates](https://docs-git-nikrichers-docs-1086-reduce-link-densi-bf6705-supabase.vercel.app/docs/guides/auth/auth-email-templates#editing-email-templates)
(preview; replacing the in-builder Local development link)

**Capture notes:** Content-area screenshots were captured locally from
component markup because the template editor body requires platform auth
config in self-hosted Studio. Local files: worktree
`.pr-screenshots/template-builder-links-{before,after}.png`.

### Proof: Docs clarify local development path

**Verified:** Vercel docs preview (pass) · `supa-mdx-lint` (pass)

| Page | Before (production) | After (PR preview) |
|------|---------------------|--------------------|
| Email templates — Editing | [Editing email
templates](https://supabase.com/docs/guides/auth/auth-email-templates#editing-email-templates)
| [Editing email
templates](https://docs-git-nikrichers-docs-1086-reduce-link-densi-bf6705-supabase.vercel.app/docs/guides/auth/auth-email-templates#editing-email-templates)
|
| Customizing email templates | [Customizing email
templates](https://supabase.com/docs/guides/local-development/customizing-email-templates)
| [Customizing email
templates](https://docs-git-nikrichers-docs-1086-reduce-link-densi-bf6705-supabase.vercel.app/docs/guides/local-development/customizing-email-templates)
|

## Additional context

### Test plan

- [ ] Open **Authentication → Emails → Confirm sign up** on a hosted
project
- [ ] Confirm header has **Docs** only (no Terminology link)
- [ ] Confirm **Docs** opens `/docs/guides/auth/auth-email-templates`
- [ ] In source view, confirm template variables show one
**Terminology** link (no Local development)
- [ ] Hover variable pills — tooltips still explain each placeholder
- [ ] Compare [production Editing email
templates](https://supabase.com/docs/guides/auth/auth-email-templates#editing-email-templates)
vs
[preview](https://docs-git-nikrichers-docs-1086-reduce-link-densi-bf6705-supabase.vercel.app/docs/guides/auth/auth-email-templates#editing-email-templates)
— hosted vs local/self-hosted sections and local dev callout are clear
- [ ] Compare [production Customizing email
templates](https://supabase.com/docs/guides/local-development/customizing-email-templates)
vs
[preview](https://docs-git-nikrichers-docs-1086-reduce-link-densi-bf6705-supabase.vercel.app/docs/guides/local-development/customizing-email-templates)
— intro links back to hosted email templates guide

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

* **Documentation**
* Clarified how to edit authentication email templates for hosted vs.
self-hosted and local development setups.
* Added clearer navigation to template terminology and customization
guidance, with updated examples and notes.

* **New Features**
* Updated the email template UI to use centralized documentation links
for the terminology section.

* **Tests**
* Added coverage to ensure the “Terminology” docs anchor stays
consistent.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Nik Richers <nik@validmind.ai>
Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-25 08:50:05 +02:00

55 lines
2.2 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import {
AUTH_EMAIL_TEMPLATES_TERMINOLOGY_ANCHOR,
EMAIL_TEMPLATE_DOCS_ANCHORS,
} from './EmailTemplates.constants'
import { AUTH_TEMPLATE_TYPES, type AuthTemplateType } from './EmailTemplates.types'
/** Docs section headings from customizing-email-templates.mdx */
const DOCS_HEADINGS: Record<AuthTemplateType, string> = {
CONFIRMATION: 'auth.email.template.confirmation',
INVITE: 'auth.email.template.invite',
MAGIC_LINK: 'auth.email.template.magic_link',
EMAIL_CHANGE: 'auth.email.template.email_change',
RECOVERY: 'auth.email.template.recovery',
REAUTHENTICATION: 'auth.email.template.reauthentication',
PASSWORD_CHANGED_NOTIFICATION: 'auth.email.notification.password_changed',
EMAIL_CHANGED_NOTIFICATION: 'auth.email.notification.email_changed',
PHONE_CHANGED_NOTIFICATION: 'auth.email.notification.phone_changed',
IDENTITY_LINKED_NOTIFICATION: 'auth.email.notification.identity_linked',
IDENTITY_UNLINKED_NOTIFICATION: 'auth.email.notification.identity_unlinked',
MFA_FACTOR_ENROLLED_NOTIFICATION: 'auth.email.notification.mfa_factor_enrolled',
MFA_FACTOR_UNENROLLED_NOTIFICATION: 'auth.email.notification.mfa_factor_unenrolled',
}
/**
* Matches docs `Heading` anchor generation in
* packages/ui/src/components/CustomHTMLElements/CustomHTMLElements.utils.ts
*/
function docsHeadingToAnchor(heading: string) {
return heading
.toLowerCase()
.trim()
.replace(/[^a-z0-9- ]/g, '')
.replace(/[ ]/g, '-')
}
describe('EmailTemplates.constants: AUTH_EMAIL_TEMPLATES_TERMINOLOGY_ANCHOR', () => {
it('matches auth-email-templates.mdx heading slug', () => {
expect(AUTH_EMAIL_TEMPLATES_TERMINOLOGY_ANCHOR).toBe(docsHeadingToAnchor('Terminology'))
})
})
describe('EmailTemplates.constants: EMAIL_TEMPLATE_DOCS_ANCHORS', () => {
it('covers every auth template type', () => {
expect(Object.keys(EMAIL_TEMPLATE_DOCS_ANCHORS).sort()).toEqual([...AUTH_TEMPLATE_TYPES].sort())
})
it.each(AUTH_TEMPLATE_TYPES)('matches docs heading slug for %s', (templateType) => {
const expectedAnchor = docsHeadingToAnchor(DOCS_HEADINGS[templateType])
expect(EMAIL_TEMPLATE_DOCS_ANCHORS[templateType]).toBe(expectedAnchor)
})
})