Liquid Cheat Sheet
You can use Liquid syntax to personalise and style your email templates. This guide shows what’s available in our system - we use LiquidJS behind the scenes for rendering.
Available Filters
These are the built-in Liquid filters you can use:
abs, append, at_least, at_most, capitalize, ceil,
compact, concat, date, default, divided_by, downcase,
escape, escape_once, first, floor, join, last, lstrip,
map, minus, modulo, newline_to_br, plus, prepend, remove,
remove_first, remove_last, replace, replace_first, replace_last,
reverse, round, rstrip, size, slice, sort, sort_natural,
split, strip, strip_html, strip_newlines, sum, times,
truncate, truncatewords, uniq, upcase, url_decode, url_encode,
where
| Example | Output |
|---|---|
{{ "New Invoice" | upcase }} | NEW INVOICE |
{{ business.name | downcase }} | acme inc. |
{{ client.name | capitalize }} | John doe -> John Doe |
{{ invoice.terms | truncate: 25 }} | Payment is due in 30 days... -> Payment is due in 30 da... |
{{ client.billing_address_2 | default: "N/A" }} | N/A (if billing_address_2 is empty) |
Unknown filters will cause an error.
Available Tags
Below are the standard Liquid tags supported in LoveInvoice:
assign, capture, case, comment, cycle, decrement, echo,
else, elsif, endcapture, endcase, endcomment, endforeach,
endif, endfor, endunless, for, if, increment, layout,
liquid, raw, render, tablerow, unless, when, break, continue
LoveInvoice-Specific Tags
These tags are specific to our implementation of Liquid:
money
money Filter
This filter formats numbers as currency based on the user's locale:
{{ amount | money }}
It takes an optional argument for currency formatting:
{{ amount | money: "USD" }} {% # currency with a hard-coded value %}
{{ amount | money: invoice.currency }} {% # currency based on another variable %}
Tag uses
-
Variable assignment
Assigns a value to a variable:
{% assign total = 5 %} -
Capture blocks
Stores output in a variable:
{% capture greeting %}Hi {{ client.name }}!{% endcapture %}
{{ greeting }} {% # Outputs: Hi John Doe! %} -
Control flow
{% if invoice.status == 'paid' %}
Paid
{% elsif invoice.status == 'viewed' %}
Viewed
{% else %}
Unknown status
{% endif %} -
Switch-style logic
{% case invoice.status %}
{% when "paid" %} Paid
{% when "viewed" %} Viewed
{% else %} Unknown status
{% endcase %} -
Loops
{% for item in invoice.items %}
{{ item.name }}
{% else %}
No items.
{% endfor %}Loop helpers:
forloop.index,forloop.index0,forloop.rindex,forloop.rindex0,forloop.first,forloop.last
-
Increment/decrement, cycle
{% increment counter %} → increments each render
{% decrement counter %}
{% cycle "one", "two", "three" %} -
Raw blocks (no Liquid parsing)
{% raw %}
{{ not_a_variable }}
{% endraw %}
Disabled Features
For security and simplicity, these tags are disabled in our system:
{% include %}and{% render %}→ No file includes or partials{% layout %}→ Layouts not supported- Dynamic partials or file-based templates are disabled
- Any filesystem or external file access via Liquid
Raw (Unescaped) Output
By default, Liquid HTML-escapes {{ variable }} output. To output unescaped HTML:
{{{ variable }}}
Use this cautiously and only with trusted HTML content.
Example Template
<h1>Hello {{ client.name | capitalize }}</h1>
{% if client.has_overdue_invoices %}
<p>You have overdue invoices!</p>
{% else %}
<p>All your invoices are up to date.</p>
{% endif %}
{% for invoice in client.invoices %}
<div class="invoice">
<h2>Invoice #{{ invoice.number }}</h2>
<p>Status: {{ invoice.status | upcase }}</p>
<p>Total: {{ invoice.total | money: invoice.currency }}</p>
</div>
{% else %}
<p>No invoices found.</p>
{% endfor %}
{% assign total_due = client.invoices | map: "total" | sum %}
<p>Total Due: {{ total_due | money: client.currency }}</p>
{% capture footer_note %}Thank you for your business, {{ client.name }}!{% endcapture %}
{{ footer_note }}
Quick Reference Table
| Feature | Syntax | Notes |
|---|---|---|
| Variable | {{ user.name }} | HTML-escaped by default |
| Raw HTML | {{{ html }}} | Unescaped (use with caution) |
| Filter | {{ text | upcase }} | Many built-ins available |
| Assign | {% assign x = 5 %} | Sets a variable |
| Capture | {% capture x %}...{% endcapture %} | Capture block content |
| If / Elsif | {% if ... %} / {% elsif %} / {% endif %} | Standard conditions |
| Case / When | {% case var %} / {% when %} / {% endcase %} | Multi-way logic |
| For Loop | {% for x in xs %} | Loop with forloop helpers, optional else |
| Increment | {% increment x %} | Adds 1 each render |
| Decrement | {% decrement x %} | Subtracts 1 each render |
| Cycle | {% cycle "a", "b" %} | Rotates through given values |
| Raw Tag | {% raw %}…{% endraw %} | Prevents Liquid parsing |
Tip: Always preview before sending to catch unknown variables or filter errors.