Migrating to v4
Version 4 supports Nuxt 4.1 and newer only. The internals are simpler, and the API has one return type.
Nuxt 4.1 or newer
The module requires nuxt >= 4.1.0. Upgrade Nuxt before you upgrade the module.
With an older version, your package manager reports a peer dependency conflict on install. If the module is installed anyway, Nuxt disables it and logs Module nuxt-email-renderer is disabled due to incompatibility issues at startup. Errors such as renderEmailComponent is not defined follow from that.
Nuxt 5 and its experimental Nitro Vite environment (experimental.nitroViteEnvironment) are not supported in v4. Stay on v3 if you depend on them; a later major release will target Nuxt 5.
renderEmailComponent always returns an object
In v3, renderEmailComponent returned a string, or { html, subject } when the template used <ESubject>. With plainText: true, the plain text replaced the HTML.
In v4 it always returns { html, text?, subject? }:
- const result = await renderEmailComponent('Welcome', props)
- const html = typeof result === 'string' ? result : result.html
+ const { html, subject } = await renderEmailComponent('Welcome', props)
Plain text is now returned as text, next to the HTML:
- const text = await renderEmailComponent('Welcome', props, { plainText: true })
+ const { html, text } = await renderEmailComponent('Welcome', props, { plainText: true })
The RenderResult and RenderOptions types are exported from nuxt-email-renderer.
DevTools endpoints moved
The dev-only endpoints used by the DevTools tab moved under the module's own prefix, so they no longer collide with your /api/emails routes:
| v3 | v4 |
|---|---|
GET /api/emails | GET /__nuxt-email-renderer/api/templates |
POST /api/emails/render | POST /__nuxt-email-renderer/api/render |
POST /api/emails/source | POST /__nuxt-email-renderer/api/source |
The nuxt-email-renderer:devtools:resolveProps hook works as before and is now typed in server code.
Templates directory follows srcDir
Without emailsDir, the module looks for emails in each layer's srcDir (app/emails by default), then in the layer root. Projects with a custom srcDir such as src now get src/emails detected automatically.
i18n locale files
Locale files are read from <layer>/<restructureDir>/<langDir> only, which is where @nuxtjs/i18n v10 reads them (i18n/locales by default). The fallback to <layer>/<langDir> was removed. Set restructureDir: false if your locale files live in the layer root.
A vueI18n config wrapped in defineI18nConfig and placed in i18n/i18n.config.ts now works.
EMarkdown escapes code
EMarkdown now uses marked 18. HTML inside fenced code blocks is escaped and shown as code, as in inline code. Before, it was inserted into the email as markup. Image alt texts contain the plain text of the Markdown alt text, without formatting characters.
Typed email components
The built-in components are registered as global components with their real prop types instead of any. vue-tsc may report prop errors in email templates that went unnoticed before.