Module behavior
What the module registers, its fixed conventions, and the opt-in codeBlock configuration.
Nuxt Email is a standard Nuxt module registered in modules. Discovery, preview routes, and the render API are fixed by convention. Syntax-highlighted blocks are the one opt-in feature.
export default defineNuxtConfig({
modules: ['@lupinum/nuxt-email'],
})What the module registers
- Components. Eighteen built-in
E*components are auto-imported for use inside email templates. ConfiguringcodeBlockaddsECodeBlock. renderEmail— a Nitro-only auto-import generated from the discovered templates, typed with each template's name and props.defineEmailentry point — import it from@lupinum/nuxt-email/define-emailinside a template to declare a subject.- Development preview — the
/__emailapplication and its endpoints, registered only whennuxt.options.devis true.
Package entry points
The package keeps one small entry point per concern:
| Import | Purpose |
|---|---|
@lupinum/nuxt-email | Register the Nuxt module; import the ModuleOptions and RenderedEmail types. |
@lupinum/nuxt-email/define-email | Declare a template subject and import its metadata errors. |
@lupinum/nuxt-email/testing | Render templates that use only the built-in components without Nuxt preparation. |
#nuxt-email/testing | Render with the application’s generated component configuration after nuxt prepare. |
@lupinum/nuxt-email/errors | Import supported runtime errors. |
There is no public renderEmail package export; its type is generated from each application's templates.
Template discovery
- Templates are
.vuefiles underapp/emails/. - Nested paths become slash-separated names (
app/emails/account/reset-password.vue→account/reset-password). app/emails/components/is reserved for your own supporting components and is not discovered.- Discovery follows the active Nuxt
srcDir: a customsrcDir: 'src/'usessrc/emails/. - Email templates from inherited Nuxt layers are not merged into the active application's registry. Keep the application-owned templates in its active
srcDir/emailstree. - Sibling
.fixtures.tsfiles supply deterministic preview props in development and are excluded from production output.
The registry is regenerated when templates are added, renamed, or deleted, which changes the generated server types. Run nuxt prepare after such changes.
Optional syntax highlighting
codeBlock is the only module option. It requires one Shiki theme and a non-empty, closed language allowlist:
export default defineNuxtConfig({
modules: ['@lupinum/nuxt-email'],
nuxtEmail: {
codeBlock: {
languages: ['typescript', 'vue'],
theme: 'github-dark',
},
},
})Only the configured language entrypoints and their required transitive grammars enter the server bundle. The highlighter is created on first use. Without this option, ECodeBlock is unregistered and Shiki performs no module-setup work or production-bundle work. Shiki remains an installation-time dependency. Unsupported top-level options fail during setup.
Production boundary
In a production build the module keeps templates that the server registry references (the Nitro handler needs them) while excluding them from the client bundle. The /__email application, its endpoints, and every discovered .fixtures.ts module are absent from production output entirely. See the preview workflow and the security boundary.