This guide explains how to create HTML email templates using UIx components and send emails from your application.
Email Component System
The saas.common.ui.email
namespace provides a set of UIx components specifically designed for creating consistent HTML emails. These components are inspired by but implemented with ClojureScript and UIx.
Available Components
The email component library includes:
html
- Root wrapper for email content
head
- Contains head elements like styles and meta tags
body
- Wrapper for all email content
container
- Centers content with proper width constraints
heading
- A block of heading text (h1-h6)
text
- Paragraph text with consistent styling
button
- A link styled as a button
img
- Image component optimized for email clients
row
- Horizontal layout container
column
- Column within a row
section
- Content section
preview
- Sets inbox preview text
hr
- Horizontal rule divider
code-inline
- Displays code snippets with cross-client support
Creating Email Templates
To create an email template:
Import the necessary components:
Copy (ns your.namespace
(:require
[saas.common.ui.email :as email]
[uix.core :refer [$]]))
Define your email template using UIx components:
Copy (defn welcome-email [{:keys [user-name verification-url]}]
($ email/html
($ email/head)
($ email/preview "Welcome to Ship Clojure! Verify your account")
($ email/body
($ email/container
($ email/heading "Welcome to Ship Clojure!")
($ email/text (str "Hello " user-name ", thank you for signing up!"))
($ email/text "Please verify your account by clicking the button below:")
($ email/button {:href verification-url
:style {:background-color "#5881D8"
:color "#ffffff"
:padding "11px 23px"}}
"Verify Account")))))
Convert the UIx components to HTML:
Copy (def html-email (email/render-email
($ welcome-email
{:user-name "Jane Doe"
:verification-url "https://your-app.com/verify?token=abc123"})))
Styling Components
Components accept style maps similar to React's style prop:
Copy ($ email/text {:style {:color "#333333"
:font-size "16px"
:line-height "1.5"}}
"This is styled text")
For margin utilities, use :m
, :mt
, :mr
, :mb
, :ml
, :mx
, or :my
:
Copy ($ email/heading {:m 10 :mb 20} "Heading with margins")
Sending Emails
Use the saas.email
namespace to send emails:
Copy (require '[saas.email :as email]
'[saas.common.ui.email :as email-ui])
;; Generate the HTML for your email
(def html-email (email-ui/render-email
($ email-ui/verification-email
{:verification-url "https://your-app.com/verify?token=abc123"
:otp "123456"
:type "onboarding"})))
;; Send the email using the EmailSender protocol
(email/send-email email-sender
{:html html-email
:subject "Verify your account"
:to "user@example.com"
:from "Your App <noreply@your-app.com>"})
The email-sender
is typically injected via the system's dependency injection:
Copy ;; In a handler that receives the email-sender as dependency
(defn send-verification-email [{:keys [email-sender]} user verification-code]
(let [html (email-ui/render-email
($ email-ui/verification-email
{:verification-url (str "https://your-app.com/verify/" verification-code)
:otp verification-code
:type "onboarding"}))]
(email/send-email email-sender
{:html html
:subject "Verify your account"
:to (:email user)
:from "Your App <noreply@your-app.com>"})))
Email Configuration
Copy ;; In your system.edn
{:services/email
{:secrets #ig/ref :services/secrets
:api-url "https://api.resend.com/emails"}}
For local development, a mock email sender is used that logs email contents instead of sending actual emails.
For better deliverability, include both HTML and plain text versions of your email:
Copy (def html-email (email-ui/render-email your-email-component))
(def text-email (email/extract-text html-email))
(email/send-email email-sender
{:html html-email
:text text-email
:subject "Your Subject"
:to "user@example.com"
:from "Your App <noreply@your-app.com>"})
Example Email Templates
The library includes pre-built templates:
login-code-email
- For sending login verification codes with magic links
verification-email
- For account verification (onboarding, password reset)
Example usage:
Copy (email-ui/render-email
($ email-ui/login-code-email
{:code "123456"
:code-href "https://your-app.com/verify/123456"
:homepage "https://your-app.com"}))