Migrating from Vue Email
Learn how to migrate your existing Vue Email project to Nuxt Email Renderer. This guide covers all the steps needed to transition smoothly while maintaining your existing email templates and functionality.
Why Migrate?
Nuxt Email Renderer offers several advantages over Vue Email:
- Native Nuxt 4+ Integration - Built specifically for Nuxt applications
- Better DevTools Support - Visual email template preview and debugging
- Simplified API - Server-side rendering endpoints built-in
- TypeScript First - Full TypeScript support out of the box
- Hot Module Replacement - Instant template updates during development
EMarkdown
and ETailwind
components available in Vue Email. They are also not part of the roadmap for future development because they require significant additional code and maintenance. Consider using alternative approaches for markdown rendering and utility-first CSS in your email templates.Migration Steps
Step 1: Remove Vue Email Dependencies
Remove the existing Vue Email packages from your project:
npm uninstall @vue-email/components @vue-email/render
yarn remove @vue-email/components @vue-email/render
pnpm remove @vue-email/components @vue-email/render
bun remove @vue-email/components @vue-email/render
Step 2: Install Nuxt Email Renderer
Install the Nuxt Email Renderer module:
npm install nuxt-email-renderer
yarn add nuxt-email-renderer
pnpm add nuxt-email-renderer
bun add nuxt-email-renderer
Add the module to your nuxt.config.ts
:
export default defineNuxtConfig({
modules: ["nuxt-email-renderer"],
});
For detailed installation instructions, see the Installation Guide.
Step 3: Move Email Templates
Move all your email templates to the /emails
directory in your project root:
Before (Vue Email):
your-project/
├── src/
│ └── emails/
│ ├── WelcomeEmail.vue
│ └── ResetPasswordEmail.vue
└── package.json
After (Nuxt Email Renderer):
your-project/
├── emails/ # 📧 Moved to root
│ ├── WelcomeEmail.vue
│ └── ResetPasswordEmail.vue
├── nuxt.config.ts
└── package.json
If you prefer to keep your templates in a different location, configure the emails directory:
export default defineNuxtConfig({
modules: ["nuxt-email-renderer"],
nuxtEmailRenderer: {
emailsDir: "/src/emails", // Custom directory
},
});
Step 4: Update Template Imports
Update your email templates to use Nuxt Email Renderer components:
Before (Vue Email):
<template>
<Html>
<Head />
<Body>
<Container>
<Heading>Welcome {{ userName }}!</Heading>
<Text>Thank you for joining us.</Text>
<Button :href="confirmUrl">Confirm Account</Button>
</Container>
</Body>
</Html>
</template>
<script setup>
import { Html, Head, Body, Container, Heading, Text, Button } from '@vue-email/components'
interface Props {
userName: string
confirmUrl: string
}
defineProps<Props>()
</script>
After (Nuxt Email Renderer):
<template>
<EHtml>
<EHead />
<EBody>
<EContainer>
<EHeading>Welcome {{ userName }}!</EHeading>
<EText>Thank you for joining us.</EText>
<EButton :href="confirmUrl">Confirm Account</EButton>
</EContainer>
</EBody>
</EHtml>
</template>
<script setup lang="ts">
// No imports needed - components are auto-imported!
interface Props {
userName: string
confirmUrl: string
}
defineProps<Props>()
</script>
Component Mapping
Here's how Vue Email components map to Nuxt Email Renderer components:
Vue Email | Nuxt Email Renderer | Notes |
---|---|---|
<Html> | <EHtml> | Same functionality |
<Head> | <EHead> | Same functionality |
<Body> | <EBody> | Same functionality |
<Container> | <EContainer> | Same functionality |
<Text> | <EText> | Same functionality |
<Heading> | <EHeading> | Same functionality |
<Button> | <EButton> | Same functionality |
<Img> | <EImg> | Same functionality |
<Link> | <ELink> | Same functionality |
<Hr> | <EHr> | Same functionality |
<Section> | <ESection> | Same functionality |
<Row> | <ERow> | Same functionality |
<Column> | <EColumn> | Same functionality |
<CodeBlock> | <ECodeBlock> | Same functionality |
<CodeInline> | <ECodeInline> | Same functionality |
<Font> | <EFont> | Same functionality |
<Preview> | <EPreview> | Same functionality |
<Style> | <EStyle> | Same functionality |
<EMarkdown> | ❌ | Not implemented |
<ETailwind> | ❌ | Not implemented |
Step 5: Update Rendering Logic
Replace your Vue Email rendering code with Nuxt Email Renderer API calls:
Before (Vue Email):
import { render } from '@vue-email/render'
import WelcomeEmail from './emails/WelcomeEmail.vue'
const html = await render(WelcomeEmail, {
userName: 'John Doe',
confirmUrl: 'https://example.com/confirm'
})
After (Nuxt Email Renderer):
// Use the built-in API endpoint
const html = await $fetch('/api/emails/render', {
method: 'POST',
body: {
template: 'WelcomeEmail',
props: {
userName: 'John Doe',
confirmUrl: 'https://example.com/confirm'
}
}
})
Verification
After migration, verify everything works:
- Start your development server:
npm run dev
- Check Nuxt DevTools:
- Open your browser's DevTools
- Navigate to the "Nuxt Email Renderer" tab
- Verify your templates are listed
- Test rendering:
curl -X POST http://localhost:3000/api/emails/render \ -H "Content-Type: application/json" \ -d '{"template":"WelcomeEmail","props":{"userName":"Test","confirmUrl":"https://example.com"}}'
Common Migration Issues
Template Not Found
Problem: Template 'WelcomeEmail' not found
Solution:
- Ensure templates are in the correct directory (
/emails
by default) - Check filename matches exactly (case-sensitive)
- Verify the template file extension is
.vue
Component Import Errors
Problem: Components not recognized in templates
Solution:
- Remove manual component imports from Vue Email
- Components are auto-imported in Nuxt Email Renderer
- Ensure you're using the
E
prefix (e.g.,EHtml
,EBody
)
Props Type Errors
Problem: TypeScript errors with template props
Solution:
- Ensure
defineProps<Props>()
is used correctly - Add
lang="ts"
to your script setup block - Verify interface definitions match your API calls
Need Help?
If you encounter issues during migration:
- 📖 Check the Installation Guide
- 🧩 Review Component Documentation
- 🐛 Report issues on GitHub
- 💬 Ask questions in Discussions