diff --git a/db/migrations/000066_email_templates.up.sql b/db/migrations/000066_email_templates.up.sql
index 370cd13..0055b76 100644
--- a/db/migrations/000066_email_templates.up.sql
+++ b/db/migrations/000066_email_templates.up.sql
@@ -20,9 +20,38 @@ VALUES
(
'otp',
'One-Time Password',
- 'Yimaru - One Time Password',
- 'Welcome to Yimaru Online Learning Platform{{if .FirstName}}, {{.FirstName}}{{end}}. Your OTP is {{.OTP}}. It expires in {{.ExpiresMinutes}} minutes. Please do not share it with anyone.',
- '
Welcome to Yimaru Online Learning Platform{{if .FirstName}}, {{.FirstName}}{{end}}.
Your one-time password is {{.OTP}}.
It expires in {{.ExpiresMinutes}} minutes. Please do not share it with anyone.
',
+ 'Yimaru Academy — Your verification code',
+ 'Yimaru Academy{{if .FirstName}}, {{.FirstName}}{{end}}
+
+Your verification code is {{.OTP}}.
+It expires in {{.ExpiresMinutes}} minutes.
+
+Please do not share this code with anyone.',
+ $otp_html$
+
+Yimaru Academy
+
+
+
+
+|
+ Yimaru Academy
+Online Learning Platform
+ |
+
+Your verification code
+{{if .FirstName}}Hi {{.FirstName}}, {{end}}use the code below to continue signing in to Yimaru Academy.
+|
+ One-time password
+{{.OTP}}
+Expires in {{.ExpiresMinutes}} minutes
+ |
+If you did not request this code, you can safely ignore this email.
+ |
+|
+ © 2026 Yimaru Academy · All rights reserved
+ |
+ |
$otp_html$,
'["OTP", "FirstName", "ExpiresMinutes"]'::jsonb,
TRUE,
'ACTIVE'
@@ -30,9 +59,33 @@ VALUES
(
'invitation',
'User Invitation',
- 'You are invited to join Yimaru',
- 'Hi{{if .FirstName}} {{.FirstName}}{{end}}, you have been invited{{if .InviterName}} by {{.InviterName}}{{end}} to join Yimaru Online Learning Platform. Accept your invitation: {{.InviteLink}}',
- 'Hi{{if .FirstName}} {{.FirstName}}{{end}},
You have been invited{{if .InviterName}} by {{.InviterName}}{{end}} to join Yimaru Online Learning Platform.
Accept your invitation
',
+ 'You are invited to Yimaru Academy',
+ 'Hi{{if .FirstName}} {{.FirstName}}{{end}},
+
+You have been invited{{if .InviterName}} by {{.InviterName}}{{end}} to join Yimaru Academy.
+
+Accept your invitation: {{.InviteLink}}',
+ $invite_html$
+
+Yimaru Academy
+
+
+
+
+|
+ Yimaru Academy
+Online Learning Platform
+ |
+
+You’re invited
+{{if .FirstName}}Hi {{.FirstName}}, {{end}}you have been invited{{if .InviterName}} by {{.InviterName}}{{end}} to join Yimaru Academy.
+Accept invitation
+Or copy this link: {{.InviteLink}}
+ |
+|
+ © 2026 Yimaru Academy · All rights reserved
+ |
+ |
$invite_html$,
'["FirstName", "InviterName", "InviteLink"]'::jsonb,
TRUE,
'ACTIVE'
@@ -40,9 +93,33 @@ VALUES
(
'password_reset',
'Password Reset',
- 'Reset your Yimaru password',
- 'Hi{{if .FirstName}} {{.FirstName}}{{end}}, use this link to reset your password: {{.ResetLink}}. The link expires in {{.ExpiresMinutes}} minutes.',
- 'Hi{{if .FirstName}} {{.FirstName}}{{end}},
Use the link below to reset your password. It expires in {{.ExpiresMinutes}} minutes.
Reset your password
',
+ 'Reset your Yimaru Academy password',
+ 'Hi{{if .FirstName}} {{.FirstName}}{{end}},
+
+Reset your password: {{.ResetLink}}
+
+This link expires in {{.ExpiresMinutes}} minutes.',
+ $reset_html$
+
+Yimaru Academy
+
+
+
+
+|
+ Yimaru Academy
+Online Learning Platform
+ |
+
+Reset your password
+{{if .FirstName}}Hi {{.FirstName}}, {{end}}we received a request to reset your Yimaru Academy password. The link below expires in {{.ExpiresMinutes}} minutes.
+Reset password
+If you did not request a reset, ignore this email.
+ |
+|
+ © 2026 Yimaru Academy · All rights reserved
+ |
+ |
$reset_html$,
'["FirstName", "ResetLink", "ExpiresMinutes"]'::jsonb,
TRUE,
'ACTIVE'
@@ -50,9 +127,30 @@ VALUES
(
'welcome',
'Welcome Email',
- 'Welcome to Yimaru',
- 'Hi{{if .FirstName}} {{.FirstName}}{{end}}, welcome to Yimaru Online Learning Platform! Sign in at {{.LoginURL}} to get started.',
- 'Hi{{if .FirstName}} {{.FirstName}}{{end}},
Welcome to Yimaru Online Learning Platform!
Sign in to get started
',
+ 'Welcome to Yimaru Academy',
+ 'Hi{{if .FirstName}} {{.FirstName}}{{end}},
+
+Welcome to Yimaru Academy! Sign in to get started: {{.LoginURL}}',
+ $welcome_html$
+
+Yimaru Academy
+
+
+
+
+|
+ Yimaru Academy
+Online Learning Platform
+ |
+
+Welcome aboard
+{{if .FirstName}}Hi {{.FirstName}}, {{end}}your Yimaru Academy account is ready. Start learning at your own pace.
+Sign in to Yimaru Academy
+ |
+|
+ © 2026 Yimaru Academy · All rights reserved
+ |
+ |
$welcome_html$,
'["FirstName", "LoginURL"]'::jsonb,
TRUE,
'ACTIVE'
@@ -62,7 +160,25 @@ VALUES
'Custom Message',
'{{.Subject}}',
'{{.Message}}',
- '{{.Message}}
',
+ $custom_html$
+
+Yimaru Academy
+
+
+
+
+|
+ Yimaru Academy
+Online Learning Platform
+ |
+
+{{.Subject}}
+{{.Message}}
+ |
+|
+ © 2026 Yimaru Academy · All rights reserved
+ |
+ |
$custom_html$,
'["Subject", "Message"]'::jsonb,
TRUE,
'ACTIVE'
diff --git a/db/migrations/000067_branded_email_template_seeds.down.sql b/db/migrations/000067_branded_email_template_seeds.down.sql
new file mode 100644
index 0000000..7bd852d
--- /dev/null
+++ b/db/migrations/000067_branded_email_template_seeds.down.sql
@@ -0,0 +1 @@
+-- No-op: branded template content is not reverted automatically.
diff --git a/db/migrations/000067_branded_email_template_seeds.up.sql b/db/migrations/000067_branded_email_template_seeds.up.sql
new file mode 100644
index 0000000..c14e343
--- /dev/null
+++ b/db/migrations/000067_branded_email_template_seeds.up.sql
@@ -0,0 +1,156 @@
+-- Refresh system email templates with Yimaru Academy branded HTML (admin portal colors).
+-- Safe to run after 000066 when seeds used the original plain layout.
+
+UPDATE email_templates SET
+ name = 'One-Time Password',
+ subject = 'Yimaru Academy — Your verification code',
+ body_text = 'Yimaru Academy{{if .FirstName}}, {{.FirstName}}{{end}}
+
+Your verification code is {{.OTP}}.
+It expires in {{.ExpiresMinutes}} minutes.
+
+Please do not share this code with anyone.',
+ body_html = $otp_html$
+
+Yimaru Academy
+
+
+
+
+|
+ Yimaru Academy
+Online Learning Platform
+ |
+
+Your verification code
+{{if .FirstName}}Hi {{.FirstName}}, {{end}}use the code below to continue signing in to Yimaru Academy.
+|
+ One-time password
+{{.OTP}}
+Expires in {{.ExpiresMinutes}} minutes
+ |
+If you did not request this code, you can safely ignore this email.
+ |
+|
+ © 2026 Yimaru Academy · All rights reserved
+ |
+ |
$otp_html$,
+ updated_at = NOW()
+WHERE slug = 'otp';
+
+UPDATE email_templates SET
+ name = 'User Invitation',
+ subject = 'You are invited to Yimaru Academy',
+ body_text = 'Hi{{if .FirstName}} {{.FirstName}}{{end}},
+
+You have been invited{{if .InviterName}} by {{.InviterName}}{{end}} to join Yimaru Academy.
+
+Accept your invitation: {{.InviteLink}}',
+ body_html = $invite_html$
+
+Yimaru Academy
+
+
+
+
+|
+ Yimaru Academy
+Online Learning Platform
+ |
+
+You’re invited
+{{if .FirstName}}Hi {{.FirstName}}, {{end}}you have been invited{{if .InviterName}} by {{.InviterName}}{{end}} to join Yimaru Academy.
+Accept invitation
+Or copy this link: {{.InviteLink}}
+ |
+|
+ © 2026 Yimaru Academy · All rights reserved
+ |
+ |
$invite_html$,
+ updated_at = NOW()
+WHERE slug = 'invitation';
+
+UPDATE email_templates SET
+ name = 'Password Reset',
+ subject = 'Reset your Yimaru Academy password',
+ body_text = 'Hi{{if .FirstName}} {{.FirstName}}{{end}},
+
+Reset your password: {{.ResetLink}}
+
+This link expires in {{.ExpiresMinutes}} minutes.',
+ body_html = $reset_html$
+
+Yimaru Academy
+
+
+
+
+|
+ Yimaru Academy
+Online Learning Platform
+ |
+
+Reset your password
+{{if .FirstName}}Hi {{.FirstName}}, {{end}}we received a request to reset your Yimaru Academy password. The link below expires in {{.ExpiresMinutes}} minutes.
+Reset password
+If you did not request a reset, ignore this email.
+ |
+|
+ © 2026 Yimaru Academy · All rights reserved
+ |
+ |
$reset_html$,
+ updated_at = NOW()
+WHERE slug = 'password_reset';
+
+UPDATE email_templates SET
+ name = 'Welcome Email',
+ subject = 'Welcome to Yimaru Academy',
+ body_text = 'Hi{{if .FirstName}} {{.FirstName}}{{end}},
+
+Welcome to Yimaru Academy! Sign in to get started: {{.LoginURL}}',
+ body_html = $welcome_html$
+
+Yimaru Academy
+
+
+
+
+|
+ Yimaru Academy
+Online Learning Platform
+ |
+
+Welcome aboard
+{{if .FirstName}}Hi {{.FirstName}}, {{end}}your Yimaru Academy account is ready. Start learning at your own pace.
+Sign in to Yimaru Academy
+ |
+|
+ © 2026 Yimaru Academy · All rights reserved
+ |
+ |
$welcome_html$,
+ updated_at = NOW()
+WHERE slug = 'welcome';
+
+UPDATE email_templates SET
+ name = 'Custom Message',
+ body_html = $custom_html$
+
+Yimaru Academy
+
+
+
+
+|
+ Yimaru Academy
+Online Learning Platform
+ |
+
+{{.Subject}}
+{{.Message}}
+ |
+|
+ © 2026 Yimaru Academy · All rights reserved
+ |
+ |
$custom_html$,
+ updated_at = NOW()
+WHERE slug = 'custom_message';
diff --git a/internal/services/emailtemplates/brand_templates.go b/internal/services/emailtemplates/brand_templates.go
new file mode 100644
index 0000000..deead36
--- /dev/null
+++ b/internal/services/emailtemplates/brand_templates.go
@@ -0,0 +1,78 @@
+package emailtemplates
+
+// Yimaru Academy brand colors (aligned with admin portal):
+// Primary #9d2a83, gradient #7b1f6e → #c43a9a, surface #eef4ff, text #333 / #666.
+
+const (
+ brandEmailHeader = `
+
+Yimaru Academy
+
+
+
+
+|
+ Yimaru Academy
+Online Learning Platform
+ |
+| `
+
+ brandEmailFooter = ` |
+|
+ © 2026 Yimaru Academy · All rights reserved
+ |
+ |
`
+
+ brandButtonPrimary = `display:inline-block;background-color:#9d2a83;color:#ffffff !important;text-decoration:none;padding:14px 28px;border-radius:8px;font-weight:600;font-size:15px;line-height:1.2;`
+
+ brandHeadingStyle = `margin:0 0 8px;color:#333333;font-size:24px;font-weight:700;line-height:1.3;`
+ brandBodyStyle = `margin:0 0 20px;color:#666666;font-size:15px;line-height:1.6;`
+ brandMutedStyle = `margin:24px 0 0;color:#666666;font-size:14px;line-height:1.6;`
+ brandAccentBox = `background-color:#eef4ff;border-radius:8px;padding:20px;border:1px solid #e0e8f5;text-align:center;`
+)
+
+const (
+ defaultOTPSubject = "Yimaru Academy — Your verification code"
+ defaultOTPText = "Yimaru Academy{{if .FirstName}}, {{.FirstName}}{{end}}\n\nYour verification code is {{.OTP}}.\nIt expires in {{.ExpiresMinutes}} minutes.\n\nPlease do not share this code with anyone."
+ defaultOTPHTML = brandEmailHeader + `
+Your verification code
+{{if .FirstName}}Hi {{.FirstName}}, {{end}}use the code below to continue signing in to Yimaru Academy.
+|
+ One-time password
+{{.OTP}}
+Expires in {{.ExpiresMinutes}} minutes
+ |
+If you did not request this code, you can safely ignore this email.
+` + brandEmailFooter
+
+ defaultInvitationSubject = "You are invited to Yimaru Academy"
+ defaultInvitationText = "Hi{{if .FirstName}} {{.FirstName}}{{end}},\n\nYou have been invited{{if .InviterName}} by {{.InviterName}}{{end}} to join Yimaru Academy.\n\nAccept your invitation: {{.InviteLink}}"
+ defaultInvitationHTML = brandEmailHeader + `
+You’re invited
+{{if .FirstName}}Hi {{.FirstName}}, {{end}}you have been invited{{if .InviterName}} by {{.InviterName}}{{end}} to join Yimaru Academy.
+Accept invitation
+Or copy this link: {{.InviteLink}}
+` + brandEmailFooter
+
+ defaultPasswordResetSubject = "Reset your Yimaru Academy password"
+ defaultPasswordResetText = "Hi{{if .FirstName}} {{.FirstName}}{{end}},\n\nReset your password: {{.ResetLink}}\n\nThis link expires in {{.ExpiresMinutes}} minutes."
+ defaultPasswordResetHTML = brandEmailHeader + `
+Reset your password
+{{if .FirstName}}Hi {{.FirstName}}, {{end}}we received a request to reset your Yimaru Academy password. The link below expires in {{.ExpiresMinutes}} minutes.
+Reset password
+If you did not request a reset, ignore this email.
+` + brandEmailFooter
+
+ defaultWelcomeSubject = "Welcome to Yimaru Academy"
+ defaultWelcomeText = "Hi{{if .FirstName}} {{.FirstName}}{{end}},\n\nWelcome to Yimaru Academy! Sign in to get started: {{.LoginURL}}"
+ defaultWelcomeHTML = brandEmailHeader + `
+Welcome aboard
+{{if .FirstName}}Hi {{.FirstName}}, {{end}}your Yimaru Academy account is ready. Start learning at your own pace.
+Sign in to Yimaru Academy
+` + brandEmailFooter
+
+ defaultCustomMessageHTML = brandEmailHeader + `
+{{.Subject}}
+{{.Message}}
+` + brandEmailFooter
+)
diff --git a/internal/services/emailtemplates/defaults.go b/internal/services/emailtemplates/defaults.go
index 4551646..1ce84a6 100644
--- a/internal/services/emailtemplates/defaults.go
+++ b/internal/services/emailtemplates/defaults.go
@@ -7,49 +7,49 @@ import (
var defaultTemplates = map[string]domain.EmailTemplate{
domain.EmailTemplateSlugOTP: {
- Slug: domain.EmailTemplateSlugOTP,
- Name: "One-Time Password",
- Subject: "Yimaru - One Time Password",
- BodyText: "Welcome to Yimaru Online Learning Platform{{if .FirstName}}, {{.FirstName}}{{end}}. Your OTP is {{.OTP}}. It expires in {{.ExpiresMinutes}} minutes. Please do not share it with anyone.",
- BodyHTML: "Welcome to Yimaru Online Learning Platform{{if .FirstName}}, {{.FirstName}}{{end}}.
Your one-time password is {{.OTP}}.
It expires in {{.ExpiresMinutes}} minutes. Please do not share it with anyone.
",
+ Slug: domain.EmailTemplateSlugOTP,
+ Name: "One-Time Password",
+ Subject: defaultOTPSubject,
+ BodyText: defaultOTPText,
+ BodyHTML: defaultOTPHTML,
Variables: []string{"OTP", "FirstName", "ExpiresMinutes"},
- Status: domain.EmailTemplateStatusActive,
+ Status: domain.EmailTemplateStatusActive,
},
domain.EmailTemplateSlugInvitation: {
- Slug: domain.EmailTemplateSlugInvitation,
- Name: "User Invitation",
- Subject: "You are invited to join Yimaru",
- BodyText: "Hi{{if .FirstName}} {{.FirstName}}{{end}}, you have been invited{{if .InviterName}} by {{.InviterName}}{{end}} to join Yimaru Online Learning Platform. Accept your invitation: {{.InviteLink}}",
- BodyHTML: "Hi{{if .FirstName}} {{.FirstName}}{{end}},
You have been invited{{if .InviterName}} by {{.InviterName}}{{end}} to join Yimaru Online Learning Platform.
Accept your invitation
",
+ Slug: domain.EmailTemplateSlugInvitation,
+ Name: "User Invitation",
+ Subject: defaultInvitationSubject,
+ BodyText: defaultInvitationText,
+ BodyHTML: defaultInvitationHTML,
Variables: []string{"FirstName", "InviterName", "InviteLink"},
- Status: domain.EmailTemplateStatusActive,
+ Status: domain.EmailTemplateStatusActive,
},
domain.EmailTemplateSlugPasswordReset: {
- Slug: domain.EmailTemplateSlugPasswordReset,
- Name: "Password Reset",
- Subject: "Reset your Yimaru password",
- BodyText: "Hi{{if .FirstName}} {{.FirstName}}{{end}}, use this link to reset your password: {{.ResetLink}}. The link expires in {{.ExpiresMinutes}} minutes.",
- BodyHTML: "Hi{{if .FirstName}} {{.FirstName}}{{end}},
Use the link below to reset your password. It expires in {{.ExpiresMinutes}} minutes.
Reset your password
",
+ Slug: domain.EmailTemplateSlugPasswordReset,
+ Name: "Password Reset",
+ Subject: defaultPasswordResetSubject,
+ BodyText: defaultPasswordResetText,
+ BodyHTML: defaultPasswordResetHTML,
Variables: []string{"FirstName", "ResetLink", "ExpiresMinutes"},
- Status: domain.EmailTemplateStatusActive,
+ Status: domain.EmailTemplateStatusActive,
},
domain.EmailTemplateSlugWelcome: {
- Slug: domain.EmailTemplateSlugWelcome,
- Name: "Welcome Email",
- Subject: "Welcome to Yimaru",
- BodyText: "Hi{{if .FirstName}} {{.FirstName}}{{end}}, welcome to Yimaru Online Learning Platform! Sign in at {{.LoginURL}} to get started.",
- BodyHTML: "Hi{{if .FirstName}} {{.FirstName}}{{end}},
Welcome to Yimaru Online Learning Platform!
Sign in to get started
",
+ Slug: domain.EmailTemplateSlugWelcome,
+ Name: "Welcome Email",
+ Subject: defaultWelcomeSubject,
+ BodyText: defaultWelcomeText,
+ BodyHTML: defaultWelcomeHTML,
Variables: []string{"FirstName", "LoginURL"},
- Status: domain.EmailTemplateStatusActive,
+ Status: domain.EmailTemplateStatusActive,
},
domain.EmailTemplateSlugCustomMessage: {
- Slug: domain.EmailTemplateSlugCustomMessage,
- Name: "Custom Message",
- Subject: "{{.Subject}}",
- BodyText: "{{.Message}}",
- BodyHTML: "{{.Message}}
",
+ Slug: domain.EmailTemplateSlugCustomMessage,
+ Name: "Custom Message",
+ Subject: "{{.Subject}}",
+ BodyText: "{{.Message}}",
+ BodyHTML: defaultCustomMessageHTML,
Variables: []string{"Subject", "Message"},
- Status: domain.EmailTemplateStatusActive,
+ Status: domain.EmailTemplateStatusActive,
},
}