Heimdall Docs

The Heimdall Framework

Heimdall is an HTML-first, server-driven UI framework for ASP.NET Core. It keeps the browser simple, the server in control, and removes the need for a separate client-side application layer in many cases.

This page explains what Heimdall is, what problems it solves, and then gets you from zero to your first working page and interaction.

1. Why Heimdall Exists

Modern web apps often split UI across multiple layers: APIs, client state, and rendering frameworks. That split introduces complexity, duplication, and synchronization problems. Heimdall reduces that surface area by letting the server remain the source of truth and using HTML as the interaction boundary.

Traditional stack:
UI -> JSON API -> client state -> DOM updates

Heimdall:
UI -> HTML -> DOM updates

2. What Heimdall Solves

Removes the need for a separate JSON API layer for most UI interactions.
Eliminates client-side state synchronization problems.
Keeps UI rendering and business logic together on the server.
Supports modern UX patterns (partial updates, live updates, streaming) without a SPA.

3. What Heimdall Is Not

Not a SPA framework.
Not a client-side state manager.
Not a replacement for APIs in all scenarios.
Not a virtual DOM or component runtime.

4. The Mental Model

Heimdall is built around a simple rule: the server owns the UI, and the browser applies updates.

Pages -> return HTML

Actions -> return HTML

Browser -> swaps HTML into the DOM

No client-side state required

5. Install

Create a new Heimdall app and start the server.

dotnet new install HeimdallFramework.Templates.WebApp

6. Your First Page

A Heimdall page is just a route that returns HTML. No Razor is required.

app.MapHeimdallPage("/", ctx =>
{
    return Html.Div(d =>
    {
        d.Text("Hello from Heimdall");
    });
});

7. Your First Interaction

A Heimdall interaction sends a request to a server action, gets HTML back, and swaps that HTML into the DOM.

Strongly Typed Markup

button.Text("Click Me");
button.Heimdall()
    .Click("Example.Increment")
    .Target("#result")
    .SwapInner();

Rendered HTML

<button
  heimdall-click="Example.Increment"
  heimdall-target="#result"
  heimdall-swap="inner">
  Click Me
</button>

<div id="result"></div>

Action

[ContentInvocation]
public static IHtmlContent Increment()
{
    return Html.Div(d =>
    {
        d.Text("Updated from the server.");
    });
}

8. What Just Happened

1. The button click triggered a Heimdall request.
2. The server action returned fresh HTML.
3. Heimdall swapped that HTML into the target element.