Selmer is a fast, Django-inspired template system written in pure Clojure that compiles templates containing variable and tag expressions into functions and renders them against a context map.
What is Selmer?
Selmer is a fast, Django-inspired template system written in pure Clojure that compiles templates containing variable and tag expressions into functions and renders them against a context map. It takes a template string or file with embedded {{ variable }} expressions and {% tag %} statements plus a Clojure map of key-value data, and outputs rendered plain text or HTML. The project is maintained by Dmitri Sotnikov on GitHub, distributed under the Eclipse Public License, and installable via Leiningen or tools.deps. It caches compiled templates by default, recompiling only when a rendered file's last-modified timestamp changes.
Key Features
- Django-inspired syntax — Uses familiar
{{ variable }},{% for %},{% if %}, and{% block %}tags so developers coming from Django can start quickly. - Pure Clojure implementation — The library has no dependency on the Django Python runtime; everything runs on the JVM with Clojure.
- Template inheritance — Child templates extend parents with
{% extends "base.html" %}and override{% block %}sections, including{{ block.super }}to insert parent content. - 60+ built-in filters — Includes date formatting, currency-format with locale support, pluralize, hash (md5/sha256), json, sort, join, abbreviate, and many more, all chainable with
|. - Extensible tags and filters —
add-filter!andadd-tag!let you register custom functions; block tags can access their body content and support nested end tags. - Custom delimiters — You can change the tag and variable markers (for example to
[[ ]]) to avoid clashes with AngularJS or other client-side frameworks. - Template validation — By default templates are validated at compile time; errors throw
ExceptionInfowith line numbers, tag details, and a built-in error page middleware for Ring. - Configurable missing-value handling — Missing variables render as empty strings by default, but
set-missing-value-formatter!lets you substitute a custom string or throw an exception.
Who is it for?
- Clojure web developers building server-rendered HTML pages with Ring, Compojure, or other JVM web stacks who want Django-like templating without Python.
- Teams familiar with Django templates that are moving to Clojure and want a syntax they already know, including template inheritance and filters.
- Developers generating non-HTML text such as emails, configuration files, or code snippets, using
without-escapingto disable HTML escaping.
What can you do with Selmer?
- Render dynamic HTML views — Compose pages from base templates with
extendsand reusableblocksections, inject model data, and loop over collections with thefortag. - Generate internationalized content — Although i18n isn't built in, the documentation shows how to create an
i18ncustom tag using the tongue library to translate keys based on the context map. - Customize output via filters — Apply chainable transformations such as
{{ value|date:"yyyy-MM-dd"|default:"now" }}for precise text formatting. - Build reusable snippets — Use
{% include "partial.html" with name="Jane" %}to inject params into included templates.
How does Selmer work?
Add the dependency (selmer/selmer on Clojars), require selmer.parser, then call render with a template string and a context map, or render-file with a path. The parser compiles the template once, caching it, and rendering replaces tags and variables with values from the map. If a template file changes, Selmer recompiles unless the change happens in an extends or include dependency — touching the rendered file is needed then, or cache control can be toggled with cache-on!/cache-off!.
Pros and cons
Pros:
- Pure Clojure library with no external runtime dependencies, easy to add to any JVM project.
- The full Django-style tag set (
if,for,cycle,firstof,with,verbatim) covers most templating needs. - Custom delimiters and custom filters/tags make it adaptable to many output formats.
Cons:
- No built-in internationalization; the README recommends implementing a custom tag (e.g., with tongue) which requires extra code.
- Changes to
included orextendsd templates do not automatically trigger recompilation — the file being rendered must be touched. - HTML escaping is on by default and must be disabled (per-render or globally) for non-HTML output, which is easy to forget.
FAQ
Is Selmer free and open source?
Yes. Selmer is distributed under the Eclipse Public License 1.0, the same license as Clojure, and its source is on GitHub. There is no paid tier or commercial license.
Does Selmer support template inheritance?
Yes. Use {% extends "base.html" %} in a child template and define {% block name %} sections. Child blocks override parent blocks, and {{ block.super }} inserts the parent block's content at that point.
Can I change the {{ }} delimiters?
Yes. Pass a map with keys like :tag-open and :tag-close to the render function to set custom markers. This is useful when using client-side frameworks such as AngularJS that also use curly braces.
How are missing variables handled?
By default a missing variable renders as an empty string, and a for loop over a missing sequence renders nothing. You can override this globally with selmer.util/set-missing-value-formatter! to output a custom string or throw an exception.
Does Selmer work for non-HTML output?
Yes. Selmer templates are plain text. You can disable HTML escaping for a single render with selmer.util/without-escaping or turn it off permanently in all threads with turn-off-escaping!.




