Installation
SKILL.md
Emails are classes that extend @adonisjs/mail's BaseMail. The prepare() method sets recipients, subject, and calls this.message.htmlView('<mod>::emails/<template>', {...}). Templates are .edge files at app/<mod>/ui/emails/<name>.edge that consume a shared @email.layout component. The layout owns fonts, colors, button styles, header, and footer; each template only fills the body slot. Raw <html><head><style> blocks are never authored — MJML with the shared layout is mandatory. Emails are always dispatched from event listeners, not from actions directly (see [[actions-events]]), so unit tests can fake the emitter and end-to-end tests can fake the mail transport.
Rules
- Mail class location:
app/<mod>/mails/<name>_notification.ts— one file per email. - Class shape: extends
BaseMail, declaresfrom = env.get('EMAIL_FROM'), setssubjecteither as a class field or dynamically inprepare()from atranslationsfield. prepare()does all the work: build any URL (viasignedUrlForfor time-limited links), callthis.message.to(recipient).subject(...), then render withhtmlView('<mod>::emails/<template>', props). Always spread...mailContext()into props so the layout hasappName+appUrl.- Templates live at
app/<mod>/ui/emails/<name>.edge. Every template opens with@email.layout({ title, preview: subtitle })and closes with@end. Between them, only<mj-section>markup — body, button, text. - Shared MJML layout is the single source of truth for typography, colors, header, footer. Change once, all emails update.
mailContext()returns{ appName, appUrl }from env with a fallback name. Every mail class spreads it intohtmlViewprops so the layout can render brand chrome.- Env:
EMAIL_FROMrequired;APP_NAMEoptional (has a fallback);APP_URLrequired. SMTP vars for local dev (typically Mailpit) and the prod driver's API key (e.g.RESEND_API_KEY). - i18n: the translation shape is a plain interface (
subject,title,subtitle,actionBtn,defaultMessage). Passed from the caller. Keys live per module underemails.<name>.*in the locale JSON — see [[i18n]].