dotliquid/dotliquid: the Ruby Liquid template language running on .NET
.NET Port of Tobias Lütke's Liquid template language.
At a glance
- What is it?
- DotLiquid is a C# port of Shopify's Liquid templating language that keeps the original syntax while following .NET conventions, with a small API built around Template.Parse and Render. It is dual licensed under Apache-2.0 and Ms-PL, used inside Docfx and several web frameworks, and its maintainer is openly asking for more commit access.
- Who is it for?
- Adopt DotLiquid when you need a template language that a non-programmer can be handed safely, or when a template has to move between .NET and a Ruby, Node or Python stack without changing, since keeping the Liquid syntax is the project's whole purpose.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 11 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Same syntax, .NET conventions
DotLiquid is a .NET port of the Ruby Liquid templating language, and it is explicitly a separate project rather than a fork of anything. The stated aim is to retain the same template syntax as the original while using .NET coding conventions where possible.
That framing tells you what to expect when you compare the two implementations. The tag vocabulary, the filter syntax and the whitespace behaviour are Liquid's, because a template that works in one has to work in the other. The API, the type names and the object model are .NET's, because the code that renders the template is a .NET program.
The original is the Ruby Liquid project from Shopify, and the repository links to it for anyone who wants the reference semantics. DotLiquid's own documentation lives in the project wiki rather than in the README, and the quick start is deliberately short: download the latest release from NuGet, then read the wiki for how to write and use templates.
The package is on NuGet as `dotliquid`, and the repository carries AppVeyor and codecov badges, a Stack Overflow tag, a Gitter chat room and a `contributing.md` file. The licence is unusual in a good way, described in the README as dual licensed, with a choice of the Apache License 2.0 or the Microsoft Public License, the two being described as essentially identical, with the reader encouraged to evaluate both.
Parse, then render with a Hash
The API is small enough to see in full. Templates are compiled with `Template.Parse`, and rendering takes parameters in the form of a `Hash` object:
Template template = Template.Parse("hi {{name}}"); // Parses and compiles the template
template.Render(Hash.FromAnonymousObject(new { name = "tobi" })); // => "hi tobi"The design choice in that snippet is the `Hash`. A template receives a plain dictionary of values, not a view model, and the values are converted to the shape the template expects rather than the template knowing anything about your types. The README notes there are several ways to construct a `Hash` object, including from a `Dictionary` or with `Hash.FromAnonymousObject`.
The anonymous object form is what makes the quick start work, and it is also what makes the engine easy to test, since a test can render a template with a literal object and assert on the string that comes out. The alternative, building a `Dictionary`, is what you would do when the data comes from a database or a service.
The general pattern the README describes is to read the contents of a file into a template and then render it with parameters, which is the workflow for every use case below.
Five reasons the logic-less design exists
The README lists the reasons to choose this kind of engine, and they are more specific than a general preference for simple templates.
The first is keeping business logic in compiled controllers and out of templates, which is the classic argument for a logic-less engine. The second is that you want a logic-less template language that also exists for other platforms, naming node and python, and that is the DotLiquid reason to exist at all, since a team with a .NET storefront and a Python service can use one template syntax on both sides.
The third is the one that matters most for a product team: you want to allow your users to edit their own page templates while ensuring they do not run insecure code. A logic-less template language gives that property by construction, because the template has no way to call arbitrary code.
The fourth is rendering templates directly from the database, which is a real pattern for multi tenant products and for content managed by a CMS. The fifth is a template engine for emails, which is a case with different requirements from web pages, mainly around text rather than HTML, and DotLiquid.Mailer in the adoption list is the obvious example.
What a template looks like
The example in the README is a product list, and it shows the two features that carry most of the weight in a Liquid template, the loop and the filters.
<ul id="products">
{% for product in products %}
<li>
<h2>{{product.name}}</h2>
Only {{product.price | price }}
{{product.description | prettyprint | paragraph }}
</li>
{% endfor %}
</ul>The `{% for %}` block iterates the `products` collection, and `{{product.name}}` prints a property of the current item. The pipe syntax applies filters, and the pipe chains, with `product.description` passed through `prettyprint` and then `paragraph`, and that chaining is the idiom to keep in mind.
One thing to notice is what is missing. The example has no conditional and no arithmetic beyond simple output, and no way to reach outside the data you were given. That is the logic-less property doing its work, and it is the same property that lets you hand these files to someone who is not a programmer.
The filter names in the example, `price`, `prettyprint` and `paragraph`, are worth a second look when you adopt the library, because a filter that exists in Ruby Liquid does not automatically exist in a.NET port. Checking the available filters is the first thing to do with a template that was written elsewhere.
The adoption list tells you more than the feature list
The README keeps a list of projects that use DotLiquid, and it is a list with useful variety.
There are view engine integrations, including ones for ASP.NET MVC and for Nancy, which means the engine has been wired into more than one hosting model. There are framework-specific packages for Suave.IO and for Giraffe which is a decent signal that the library drops into non-ASP.NET stacks as well. There is DotLiquid.Mailer for the email case. There is Pretzel, the site generator. And there is Docfx, the.NET documentation tool, plus GrandNode 2.0, a commerce platform.
Two of those entries matter more than the others for an evaluation. Docfx means the engine renders documentation for a large body of.NET developers every day, on content that is not written by the tool's authors. GrandNode 2.0 means a storefront, where template rendering sits in the request path of a commercial system.
The list is maintained by pull request, with the README asking anyone using it in an open source project to say so, which is the cheapest possible signal of adoption and one you can verify by looking at the named projects rather than taking a number on faith.
Maintainers wanted, and a release line that has moved
The first section of the README is a recruitment notice. If you have sent a pull request to the repository, the maintainer asks you to get in touch, on Gitter or on GitHub, so that commit access can be granted.
That is a meaningful signal about the governance of the project, and it is worth weighing alongside the release history. The only release tag listed is v2.2.508, published on 2021-08-05, while the last push to the repository was on 2026-10-12. The repository is not archived, so work continues on the master branch, and the `CHANGELOG.markdown` file at the top level is where the movement is recorded.
The gap between the last tag and the last push describes the shape of the project. The NuGet package you install is the tagged release, not the head of master, so if a fix you need landed after v2.2.508, it is not in the package you get from NuGet. For most users that is fine, since a stable release is what you want, but for a team tracking a specific bug fix it means the release notes and the changelog are two different documents to read.
The dual licensing is the other practical point. Because the project is intended for use in both open source and commercial environments and offers a choice between Apache-2.0 and Ms-PL, the licensing question is settled for almost any adopter, and the `LICENSE-Apache` and `LICENSE-Ms-PL` files are both in the repository root.
Where DotLiquid is the wrong choice
The clearest wrong case is a new ASP.NET Core application. Razor is the framework's own template engine, it is integrated with the MVC pipeline, and it comes with the tooling and the debugging story that a .NET team expects. Choosing DotLiquid there means adding a second engine and a second set of conventions to a stack that already has one.
The second wrong case is a team that wants .NET only. The case for DotLiquid over Razor is the syntax and the cross platform story, and if your templates only ever run on .NET, that advantage is not there.
The third is a project that needs logic in templates. DotLiquid is logic-less by design and that is the point, but a template that needs a conditional on business data, a computed total or a loop over a derived collection is a sign that the logic belongs in code, and the engine will not help you put it there.
The fourth consideration is the release cadence. A project that has to track the newest .NET runtime and wants its template engine to move with it has to weigh a 2021 tag against a busy master branch, and the project's own request for more maintainers is a signal that the bus factor is one person.
None of this makes DotLiquid a bad choice where it fits. Where it fits, it fits well, and the list of projects above is a reasonable answer to the question of whether the engine works outside a toy.
Editorial conclusion
Adopt DotLiquid when you need a template language that a non-programmer can be handed safely, or when a template has to move between .NET and a Ruby, Node or Python stack without changing, since keeping the Liquid syntax is the project's whole purpose. Do not adopt it for a new ASP.NET Core application that already has a view engine, since Razor is the framework's own path and DotLiquid is a separate compatibility bet, and do not adopt it expecting a modern .NET release train, because the last tagged release is v2.2.508 from 2021 while the master branch has moved on. Verify first which target frameworks the current NuGet package supports for your runtime, and that the filters your templates rely on exist in the .NET port, since a Liquid filter in Ruby is not automatically a filter in DotLiquid.
Frequently asked questions
What is DotLiquid and how is it different from Razor?
DotLiquid is a .NET port of the Ruby Liquid templating language from Shopify, a separate project that keeps the original template syntax while using .NET coding conventions. Razor is the template engine built into ASP.NET Core, while DotLiquid is a standalone library that also runs in other .NET hosts such as Suave, Nancy and Giraffe.
How do I render a template with DotLiquid?
Compile the template with `Template.Parse` and render it with parameters in a `Hash` object, for example `template.Render(Hash.FromAnonymousObject(new { name = "tobi" }))`. A `Hash` can also be built from a `Dictionary`.
What licence can I use DotLiquid under?
DotLiquid is dual licensed, and you may choose either the Apache License 2.0 or the Microsoft Public License, which the README describes as essentially identical. Both licence files are in the repository.
Which projects use DotLiquid?
The README lists Suave.DotLiquid, Pretzel, Docfx, DotLiquid.Mailer, a Suave.IO template engine, a Giraffe template engine, view engines for ASP.NET MVC and for Nancy, and GrandNode 2.0. The list is maintained by pull request.
Is DotLiquid still being maintained?
The repository is not archived and the last push was on 2026-10-12, but the only listed release tag is v2.2.508 from 2021-08-05. The README also asks contributors who have sent pull requests to get in touch so they can be given commit access, which points to a single maintainer seeking help.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dotliquid-dotliquid)Was this useful?