Template System
Outpost uses Markdown templates for all outgoing emails — team invitations, ticket notifications, SLA breach alerts, and more. Templates support variable interpolation and are sent via Resend.
How Templates Work
Templates live in the templates/ directory at the repository root.
Each template is a Markdown file with YAML frontmatter that defines metadata
(name, subject line, sender address) and a body that supports
{{variable}} interpolation.
When an email needs to be sent, Outpost loads the appropriate template, replaces
all {{variable}} placeholders with real values, renders the Markdown
to HTML, and delivers it through the Resend API.
Template Format
Every template follows this structure:
---
name: Team Member Invite
subject: "You've been invited to join {{org.name}}"
from: "{{org.name}} <{{org.email}}>"
---
Hi {{member.name}},
You've been invited to join **{{org.name}}** on Outpost.
{{member.invitedBy}} has added you as a **{{member.role}}**.
Click the link below to accept your invitation:
[Accept Invitation]({{invite.url}})
This invitation will expire in {{invite.expiresIn}}.
Frontmatter Fields
| Field | Description | Required |
|---|---|---|
| name | Human-readable template name (shown in the dashboard) | Yes |
| subject | Email subject line (supports {{variables}}) | Yes |
| from | Sender display name and address (supports {{variables}}) | Yes |
Variable Interpolation
Variables use double-brace syntax: {{namespace.field}}. The available
variables depend on the context in which the template is rendered.
Common Variable Namespaces
| Namespace | Fields | Available In |
|---|---|---|
| org | name, email | All templates |
| member | name, email, role, invitedBy | invite, welcome |
| invite | url, expiresIn | invite |
| ticket | displayId, title, url, status | ticket-created, ticket-resolved, escalation |
| customer | name, email | ticket-created, ticket-resolved |
| sla | target, elapsed, priority | sla-breach |
Built-in Templates
Outpost ships with these templates out of the box:
| File | Name | Purpose |
|---|---|---|
| invite.md | Team Member Invite | Sent when inviting a new team member |
| welcome.md | Welcome | Sent when a member accepts their invitation |
| ticket-created.md | Ticket Created | Acknowledgment to the customer when a ticket is opened |
| ticket-resolved.md | Ticket Resolved | Notification when a ticket is marked resolved |
| escalation.md | Escalation | Internal alert when a ticket is escalated |
| sla-breach.md | SLA Breach | Alert when an SLA target is about to be or has been breached |
| digest.md | Digest | Periodic summary of open tickets and activity |
Editing Templates in the Dashboard
Templates can be edited directly from the Outpost dashboard under Settings → Templates. The dashboard provides a live preview with sample data so you can see how the rendered email will look before saving. Changes made in the dashboard override the file-based defaults.
Resend Email Integration
Outpost uses Resend for email delivery. To enable email sending:
- Create a Resend account and generate an API key
- Set
RESEND_API_KEYin your.envfile - Optionally set
EMAIL_FROMto customize the sender address - Verify your sending domain in the Resend dashboard
Note: If RESEND_API_KEY is not set, Outpost will
log email contents to the console instead of sending them. This is useful during
local development.
Creating Custom Templates
To create a new template:
- Create a new
.mdfile in thetemplates/directory - Add the required YAML frontmatter (
name,subject,from) - Write the email body in Markdown with
{{variable}}placeholders - Register the template in your sending code by referencing the filename (without extension)
---
name: Custom Alert
subject: "[{{org.name}}] {{alert.title}}"
from: "{{org.name}} Alerts <{{org.email}}>"
---
**{{alert.title}}**
{{alert.message}}
[View Details]({{alert.url}})
— {{org.name}}
The Markdown body supports all standard Markdown features: bold, italic, links, lists, headings, and code blocks. The rendered HTML is automatically wrapped in a responsive email layout.