DEV Community

Daniel Jonathan
Daniel Jonathan

Posted on

Debug DotLiquid Templates Locally with the VS Code DotLiquid Debugger

The Problem We Are Solving

Shopify’s Liquid preview is useful, but Logic Apps Standard runs DotLiquid, not Shopify Liquid.
That means behavior can differ, so a template that looks correct in Shopify preview can still fail in Logic Apps.

The default Logic App testing loop is slow: update template, execute, wait, inspect run history, repeat.
For real B2B transforms, that guesswork is costly.

This post shows how to debug DotLiquid locally in VS Code with fast feedback and runtime-accurate results.


The Core Idea: Local Preview with the Exact Same Engine

The DotLiquid Debugger VS Code extension runs your templates locally, using the exact same DotLiquid 2.0.361 engine that Azure Logic Apps Standard uses in production.

This is the critical part: it uses the exact same engine — not a simulation.

Not a compatible implementation. The same NuGet package, the same version, the same sentence-cased filters, the same content wrapping behaviour, the same integer division quirks.

If it works here, your DotLiquid behavior should match Logic Apps closely, with far fewer deployment surprises.


How It Works Under the Hood

At a high level, the extension is a thin VS Code UI over a real .NET renderer.

VS Code Extension (TypeScript)
  ├─ WebView panel (preview UI)
  ├─ Auto-refresh on save / keystroke
  └─ LiquidBackend ──► DotLiquidRenderer.dll (.NET 8)
                             NDJSON over stdin/stdout
Enter fullscreen mode Exit fullscreen mode

The .NET renderer is a long-running subprocess (kept alive for performance). It is compiled from source on first use and then kept alive for the session — so after the first warm-up, renders are nearly instant.

Communication uses NDJSON (one JSON request per line, one response per line) with id-paired responses, so the TypeScript side can handle concurrent requests without blocking.


What You Actually Get

1. Live Preview

Open any .liquid file and press Ctrl+Shift+L (or Cmd+Shift+L on macOS). A preview panel opens beside the editor showing the rendered output in real time.

The extension auto-refreshes on every save (or on every keystroke, debounced). The round-trip from editing to seeing the output is under 100ms for most templates. You still run after each change, but it happens locally and near-instantly instead of waiting on a Logic App execution.

This alone removes the biggest bottleneck in Liquid development.

Input data comes from a paired .liquid.json file in the same folder:

sales-order-transform.liquid
sales-order-transform.liquid.json   ← edit this with your test data
Enter fullscreen mode Exit fullscreen mode

If the input file doesn't exist, a banner offers to create a sample file for you.


2. Step Debugger

This is where everything changes.

Click the Debug button in the preview toolbar. The template replays step by step — every assign, loop iteration, if/elsif/else, and output chunk gets its own step.

At each step:

  • The source line is highlighted in the editor
  • The Variables panel shows every variable and its current value
  • Variables not yet assigned are dimmed, so you see exactly what exists at this point in execution

Use the slider or Prev/Next buttons to navigate. Jump to the first or last step with |◀ and ▶|.

You can finally see why a value is wrong — not just that it is wrong.

This turns "why is this variable wrong?" from a guessing game into a one-minute diagnosis.


3. Filter Chain Tracing

Every assign step that uses filters shows the full chain below the debug bar:

499.9 | Times:5 → 2499.5 | DividedBy:100 → 24.995 | Round:2 → 25.0
Enter fullscreen mode Exit fullscreen mode

31 filters are covered: all the math filters (Times, DividedBy, Plus, Minus, Modulo, Round, Ceil, Floor, Abs, AtLeast, AtMost), string filters (Upcase, Downcase, Capitalize, Append, Prepend, Strip, Replace, Truncate, etc.), and array filters (Split, Join, First, Last, Sort, Map, Reverse, Size).

This is something you simply cannot do in Azure Logic Apps.

Most calculation bugs live in filter chains — this feature isolates them instantly.

This is especially useful when a chain of four or five filters produces an unexpected result — you can see exactly where the value diverged.


4. Condition Evaluation

if, elsif, else, unless, and when steps show the condition that was evaluated and a ✓ taken indicator if the branch was taken:

? if: content.priority == "HIGH"   ✓ taken
Enter fullscreen mode Exit fullscreen mode

Un-taken branches produce no step at all — which matches DotLiquid's execution model exactly.

This makes it obvious why a branch did or did not execute.


5. Variable Panel and Line Map

The Variables panel lists every assign value with the line number where it was last set. Click any row to jump to that line in the source.

The Line Map links every output chunk back to the template line that produced it. Click any output region to jump to the source line. This is especially useful for templates that produce XML or JSON — you can click "grandTotal": 336.20 in the output and jump straight to the line that calculated it.

Both panels collapse independently. When one collapses, the other expands to fill the full sidebar height.

Together, these eliminate the need for "temporary debug output" hacks.


6. Output Formats: JSON, XML, HTML, Plain Text

Because the extension renders raw text output, it works equally well for all four output formats Logic Apps supports:

Template Output
invoice-flat.liquid Flat JSON for downstream API
sales-order-transform.liquid Complex JSON with B2B calculations
order-to-xml.liquid XML for EDI / ERP integration
customer-to-xml.liquid XML ERP customer import
email-notification.liquid HTML order confirmation email
shipping-label.liquid Plain text packing slip

Getting Started

Setup takes under 2 minutes.

Requirements

  • VS Code 1.85 or later
  • .NET 8 SDK (download)

Verify .NET:

dotnet --version   # should print 8.x.x or later
Enter fullscreen mode Exit fullscreen mode

Install

Install from the VS Code Marketplace:

code --install-extension danieljonathan.dotliquid-template-debugger
Enter fullscreen mode Exit fullscreen mode

Or download the latest .vsix from github.com/imdj360/VSCodeDotLiquidDebugger and install it:

code --install-extension ./dotliquid-template-debugger-0.5.0.vsix
Enter fullscreen mode Exit fullscreen mode

You can also search DotLiquid Template Debugger for Logic Apps in the VS Code Extensions panel.

Your First Preview

  1. Create a file hello.liquid:
{%- assign name = content.name -%}
{%- assign items = content.items -%}
{%- assign total = 0 -%}
{%- for item in items -%}
  {%- assign total = total | Plus: item.price -%}
{%- endfor -%}
{
  "greeting": "Hello, {{ name }}!",
  "itemCount": {{ items | Size }},
  "total": {{ total | Round: 2 }}
}
Enter fullscreen mode Exit fullscreen mode
  1. Create hello.liquid.json in the same folder:
{
  "name": "World",
  "items": [
    { "price": 9.99 },
    { "price": 14.50 },
    { "price": 4.00 }
  ]
}
Enter fullscreen mode Exit fullscreen mode
  1. Press Ctrl+Shift+L to open the preview. You should see:
{
  "greeting": "Hello, World!",
  "itemCount": 3,
  "total": 28.49
}
Enter fullscreen mode Exit fullscreen mode

At this point, each change can be validated with a quick local run instead of rerunning the Logic App each iteration.

  1. Press Debug and step through to watch total accumulate across the loop.

The F5 Launch Config Workflow

For a proper development workflow — especially when working with multiple templates — add a type: "dotliquid" launch configuration to your .vscode/launch.json:

{
  "type": "dotliquid",
  "request": "launch",
  "name": "My: sales-order-transform",
  "template": "${workspaceFolder}/templates/sales-order-transform.liquid"
}
Enter fullscreen mode Exit fullscreen mode

Now press F5 from the Run and Debug panel. The extension:

  1. Opens the template in the editor
  2. Auto-detects the paired .liquid.json input
  3. Opens the preview panel

No manual reload. No "Developer: Reload Window". Just F5.

This is the closest thing to a real development experience for Liquid templates.

The input field can be provided in launch config, but current preview execution reads the paired <template>.liquid.json file.


Sample Templates

Seven ready-to-use sample templates covering all output formats are available in a companion repository. Clone it and open it in VS Code:

GitHub: Xslt-Liquid-DebuggerTestFiles

Each template has a paired .liquid.json input file. Pick any Liquid: config from the Run and Debug dropdown and press F5.


A Typical Debugging Session

Here is a real example: grandTotal shows 0 instead of 336.20.

Without local debugging, you update the template, run the Logic App, wait, check output, and repeat.

With the extension:

  1. Press Debug.
  2. Go to assign grandTotal and check the filter chain.
  3. See couponAmt is 0.
  4. Step back to couponDiscount and confirm it is 0.
  5. Step back again and see if content.couponCode == "WINTER20" was not taken.
  6. Check input JSON: couponCode is "winter20" (lowercase).

Done in minutes, with local runs between changes.


Where Local Debugging Fits

Use local runs for fast iteration.
Use Logic App execution for final validation.


Recommended Workflow

  1. Write your template in VS Code.
  2. Run locally with .liquid.json input.
  3. Debug until correct.
  4. Deploy and validate in Logic Apps.

Local inner loop: update → run locally → inspect → repeat.


Liquid works best when you can see what it is doing.


Links


Also check out the XSLT Debugger — a sister extension for debugging XSLT transforms in Logic Apps Standard: macOS (arm64) · Windows

Top comments (0)