Preview workflow
Use the development-only /__email preview, add fixtures, and monitor exact rendered size without treating it as a client guarantee.
Nuxt Email exposes /__email relative to the application's configured Nuxt base URL while the development server is running. With the default base URL, open /__email; with app.baseURL: '/sub/', open /sub/__email. It lists every template discovered under app/emails/, marks templates without fixture data, and shows the selected template as rendered HTML, exact HTML source, or plain text. While the page is visible it polls the development endpoints once per second, so saved template and fixture changes appear without restarting Nuxt; polling pauses in a hidden tab.
The preview calls the same server-only registry and renderEmail() implementation your handlers use. It is a rendering and debugging tool — not a second rendering path and not an email-client compatibility guarantee.
Add a fixture
Place one exact sibling file beside a template. Only the .fixtures.ts suffix is recognized, and it must default-export one props object:
import type WelcomeEmail from './welcome.vue'
type WelcomeEmailProps = Omit<
InstanceType<typeof WelcomeEmail>['$props'],
keyof import('vue').PublicProps
>
export default {
firstName: 'Ada',
activationUrl: 'https://example.com/activate',
} satisfies WelcomeEmailPropsThe preview intentionally supports one fixed scenario per template and does not accept request-provided props or generate editing forms.
Inspect output
Preview
Loads the raw rendered HTML in a sandboxed iframe (no script permission).
HTML
Displays the exact html returned by renderEmail().
Plain text
Displays the exact text returned by renderEmail().
Copy / Open
Copy copies the active representation; Open opens the raw development render in a separate tab.
Render failures show the template name, the wrapped EmailRenderError stack, and its original cause. A template without a fixture stays visible in the list but cannot be rendered until its sibling fixture is added.
Mind the approximate Gmail clipping budget
Gmail is commonly observed clipping messages around 102 KB, but behavior can vary with the account, message, and delivery path. Nuxt Email reports the rendered HTML's exact UTF-8 byte count; the Gmail-specific interpretation is an approximate authoring warning, not a guarantee:
const { html } = await renderEmail('welcome', props)
console.log('bytes:', Buffer.byteLength(html, 'utf8'))Keep the rendered HTML comfortably below the warning area and test the delivered message in your target Gmail accounts. Inlined Tailwind utilities and repeated markup add up quickly, so measure your largest, most dynamic template.
The preview has no dark-mode simulation. Email clients transform dark-mode content differently, so test dark rendering in the real clients you support.
Production boundary
The preview page, list endpoint, render endpoint, and fixture imports are registered only in development. Production builds contain none of their routes or fixture data. The raw render endpoint uses a restrictive content security policy, and the page iframe is sandboxed without script permission. The development endpoints are deliberately not configurable production render or send APIs — use the typed server-only renderEmail in your handlers.