Liquid Pages

June 23, 2026 · View on GitHub

CI NuGet Downloads GitHub commit activity GitHub last commit View - Documentation

App Dashboard

If you find this project helpful, please consider giving it a ⭐!

LiquidPages is an open-source C# library that brings a Razor Pages–style MVVM framework to Liquid templates. It uses Fluid under the hood and is designed to plug into virtually any .NET web server.

Why?

Most .NET templating solutions are tightly coupled to a specific web server or framework. LiquidPages was built to solve two problems:

  • Web-server agnostic — the middleware can hook into any web server (EmbedIO, a custom HTTP listener, or anything else you can hand a request to), so you aren't locked into a particular host.
  • Modular by design — Liquid templates and their page models can live in any C# project across a solution. Each route defines its own IFileProvider, making it straightforward to split pages across multiple projects and compose them at runtime.

The result is a lightweight, portable templating layer that stays out of your way regardless of how your application is structured.

Setup

1. Install the NuGet package

nuget add Kinetq.LiquidPages

2. Register services

services.AddLiquidPages();

3. Register routes, filters, and template file providers at startup

Inject ILiquidStartup and call the registration methods during your application's startup phase:

_liquidStartup.RegisterPageModels();
_liquidStartup.RegisterFilters();
_liquidStartup.RegisterFileProvider("/", fileProvider);

RegisterFileProvider is how template options are now registered for each route prefix. This is required so LiquidPages can resolve templates from the correct source (physical files, embedded files, etc.). It should always be AFTER RegisterPageModels so page model types are available when the provider is registered.

See the sample projects for concrete startup usage:

  • src/Kinetq.LiquidPages.AspNetCore.Sample/Program.cs
  • src/Kinetq.LiquidPages.EmbedIO.Sample/Program.cs
  • src/Kinetq.LiquidPages.GenHTTP.Sample/Program.cs
  • src/Kinetq.LiquidPages.SimpleW.Sample/Program.cs

4. Create a page model

Decorate your page model with [LiquidPage], providing a route regex and template path:

[LiquidPage("/", "Pages/Home.liquid")]
public class HomeModel : LiquidPageModel
{
    public string Title { get; set; } = "Welcome to Home";

    public override Task OnGetAsync(LiquidRequestModel request)
    {
        return Task.CompletedTask;
    }
}

5. Create the Liquid template

Properties on the page model are available in the template via the view_model object:

{% capture page_content %}
    <h1>{{ view_model.title }}</h1>
{% endcapture %}

{% include 'Layouts/default.liquid' %}

6. Wire up middleware

GenHTTP middleware

Install the GenHTTP companion package:

dotnet add package Kinetq.LiquidPages.GenHTTP

Resolve ILiquidStartup, ILiquidResponseMiddleware, and ILiquidRoutesManager from your container, register routes/file providers, then attach LiquidHandlerBuilder to your layout:

var middleware = serviceProvider.GetRequiredService<ILiquidResponseMiddleware>();
var routesManager = serviceProvider.GetRequiredService<ILiquidRoutesManager>();
var startup = serviceProvider.GetRequiredService<ILiquidStartup>();

startup.RegisterPageModels();
startup.RegisterFileProvider("/", new EmbeddedFileProvider(typeof(Program).Assembly));

var staticResources = Resources.From(ResourceTree.FromDirectory(Path.Join(AppDomain.CurrentDomain.BaseDirectory, "Static")));
var app = Layout.Create()
    .Add("Static", staticResources)
    .Add(new LiquidHandlerBuilder(middleware, routesManager));

await Host.Create()
          .Handler(app)
          .Bind(IPAddress.Any, 8080)
          .RunAsync();

LiquidHandlerBuilder implements IHandlerBuilder<LiquidHandlerBuilder>, so you can attach any GenHTTP concern (compression, caching, CORS, etc.) before the handler is built. See the full GenHTTP documentation for a complete walkthrough.

EmbedIO middleware

Install the EmbedIO companion package and attach LiquidPages to your WebServer:

dotnet add package Kinetq.LiquidPages.EmbedIO
var startup = serviceProvider.GetRequiredService<ILiquidStartup>();
startup.RegisterFileProvider("/", new EmbeddedFileProvider(typeof(Program).Assembly));
startup.RegisterPageModels();

var middleware = serviceProvider.GetRequiredService<ILiquidResponseMiddleware>();
var routesManager = serviceProvider.GetRequiredService<ILiquidRoutesManager>();

webServer.WithLiquidPages(middleware, routesManager);

If you need lower-level control, LiquidWebModule now takes ILiquidRoutesManager in its constructor:

webServer.WithModule(new LiquidWebModule("/", routesManager)
{
    LiquidResponseMiddleware = middleware
});

ASP.NET Core middleware

Install the ASP.NET Core companion package:

dotnet add package Kinetq.LiquidPages.AspNetCore

Register LiquidPages services, initialize startup registrations, and map LiquidPages middleware directly on the app:

using Kinetq.LiquidPages.AspNetCore;
using Kinetq.LiquidPages.Helpers;
using Kinetq.LiquidPages.Interfaces;
using Microsoft.Extensions.FileProviders;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddLiquidPages(typeof(Program).Assembly);

var app = builder.Build();

using (var scope = app.Services.CreateScope())
{
    var startup = scope.ServiceProvider.GetRequiredService<ILiquidStartup>();
    startup.RegisterPageModels();
    startup.RegisterFileProvider("/", new EmbeddedFileProvider(typeof(Program).Assembly));
}

app.UseLiquidPagesErrorHandling();
app.UseStaticFiles();
app.UseLiquidPages();

await app.RunAsync();

SimpleW middleware

Install the SimpleW companion package:

dotnet add package Kinetq.LiquidPages.SimpleW

Resolve ILiquidRoutesManager, ILiquidResponseMiddleware, and ILiquidStartup from your container, then register page models/file providers before attaching LiquidPagesModule:

using Kinetq.LiquidPages.Helpers;
using Kinetq.LiquidPages.Interfaces;
using Microsoft.Extensions.FileProviders;
using SimpleW;

var liquidRoutesManager = serviceProvider.GetRequiredService<ILiquidRoutesManager>();
var liquidResponseMiddleware = serviceProvider.GetRequiredService<ILiquidResponseMiddleware>();
var liquidStartup = serviceProvider.GetRequiredService<ILiquidStartup>();

liquidStartup.RegisterFileProvider("/", new EmbeddedFileProvider(typeof(Program).Assembly));
liquidStartup.RegisterPageModels();

var server = new SimpleWServer(IPAddress.Any, 2015);
server.UseStaticFilesModule(options => {
    options.Path = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "Static");
    options.Prefix = "/Static";
    options.CacheTimeout = TimeSpan.FromDays(1);
    options.AutoIndex = true;
});

server.UseModule(new LiquidPagesModule(liquidRoutesManager, liquidResponseMiddleware)
{
    MapFallback404 = true
});

await server.RunAsync();

For other web servers, call HandleRequestAsync on ILiquidResponseMiddleware from within your own request handler.

Visual Studio Extension

Install the Kinetq.LiquidPages.Extension from the Visual Studio Marketplace for syntax highlighting, a Prettier-based formatter (Ctrl+Shift+X), and quick commands to scaffold new pages.

Before using the Add LiquidPage command, install the templates package:

dotnet new install Kinetq.LiquidPages.Templates

The extension automatically adds a .filenesting.json to your project, which nests .liquid.cs code-behind files under their corresponding .liquid template in Solution Explorer.

Without the extension

If you choose not to use the extension, you will need to configure the following manually.

.filenesting.json — add this to your project root to nest .liquid.cs files under their .liquid counterparts:

{
  "root": true,
  "dependentFileProviders": {
    "add": {
      "extensionToExtension": {
        "add": {
          ".liquid": [ ".liquid.cs" ]
        }
      }
    }
  }
}

.vs/VSWorkspaceSettings.json — add this to suppress HTML validation warnings inside .liquid files and enable HTML syntax highlighting for them in Visual Studio:

{
  "HtmlValidation.IgnorePatterns": [
    "**/*.liquid"
  ]
}

Documentation

Full documentation: https://www.kinetq.com/docs/open-source-software/liquid-pages