Skip to main content

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
ExampleOutput
{{ "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 }}}
danger

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

FeatureSyntaxNotes
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.