Heimdall Docs

Configuration

Heimdall has two configuration surfaces: server registration settings and the browser runtime object exposed as window.Heimdall.

Use this page when you need the exact defaults, the mutable runtime properties, and the timing rules for when a setting must be applied.

1. Configuration Surfaces

Most application configuration happens on the server. Browser behavior that is intentionally runtime-tunable lives under Heimdall.config after the JavaScript bundle loads.

Server:
builder.Services.AddHeimdall(options => { ... });
app.UseHeimdall();

Browser:
window.Heimdall
window.Heimdall.config

2. Server Settings

AddHeimdall accepts HeimdallServiceSettings. These settings affect server endpoint behavior, error detail, and Bifrost topic authorization.

builder.Services.AddHeimdall(options =>
{
    options.EnableDetailedErrors = builder.Environment.IsDevelopment();
    options.BifrostTopicPolicy = "BifrostTopic";
    options.AuthorizeBifrostTopic = (ctx, topic) =>
        ValueTask.FromResult(topic.StartsWith("user:"));
    options.BifrostHeartbeatInterval = TimeSpan.FromSeconds(15);
});

3. Server Defaults

These are the framework defaults from HeimdallServiceSettings.

EnableDetailedErrors:
false

BifrostTopicPolicy:
null

AuthorizeBifrostTopic:
null

BifrostHeartbeatInterval:
15 seconds

4. Browser Runtime Object

After the bundle loads, Heimdall assigns a global runtime object to window.Heimdall. Its methods are the supported browser-side API surface.

Heimdall.apiVersion

Heimdall.invoke(actionId, payload, options)
Heimdall.boot(root)
Heimdall.onReady(callback)
Heimdall.clearCsrfToken()

Heimdall.sse.connect(topic, options)
Heimdall.sse.disconnect(element)
Heimdall.sse.disconnectAll()

Heimdall.config
Heimdall._observer

OOB Default

Out-of-band response directive processing is enabled by default. The runtime default is Heimdall.config.oobEnabled = true. Set it to false only when the application wants to ignore <invocation> directives returned by actions or SSE payloads.

5. Set Runtime Config

The runtime creates Heimdall.config when the script loads. Put configuration immediately after the runtime script, and put early-boot options before DOMContentLoaded or before any manual boot call.

<script src="/_content/HeimdallFramework.Web/heimdall-bundle.min.js"></script>
<script>
  Heimdall.config.debug = true;
  Heimdall.config.inputDebounceMs = 350;
  Heimdall.config.hoverDelayMs = 200;
  Heimdall.config.oobEnabled = true;
</script>

6. Runtime Config Defaults

These are the current browser runtime defaults from startup.js.

Heimdall.config = {
  basePath: "/__heimdall",
  apiVersion: 1,

  endpoints: {
    contentActions: "/__heimdall/v1/content/actions",
    csrf: "/__heimdall/v1/csrf",
    bifrostToken: "/__heimdall/v1/bifrost/token",
    bifrost: "/__heimdall/v1/bifrost"
  },

  observeDom: true,
  debug: false,

  inputDebounceMs: 250,
  hoverDelayMs: 150,
  scrollThresholdPx: 120,
  scrollMinIntervalMs: 250,

  visibleRootMargin: "0px",
  visibleThreshold: 0,

  oobEnabled: true,

  sseDefaultSwap: "none",
  sseEventName: "heimdall",
  sseReconnectDelayMs: 250,
  sseReconnectMaxDelayMs: 10000,
  sseReconnectBackoffFactor: 2,
  sseSweepIntervalMs: 5000,
  ssePauseWhenHidden: false
};

7. Endpoint Configuration

Endpoint values are read when the runtime makes a request. The default paths match app.UseHeimdall(). Only change them when the server has been mapped behind a matching path or proxy.

Heimdall.config.endpoints.contentActions = "/internal/heimdall/actions";
Heimdall.config.endpoints.csrf = "/internal/heimdall/csrf";
Heimdall.config.endpoints.bifrostToken = "/internal/heimdall/bifrost/token";
Heimdall.config.endpoints.bifrost = "/internal/heimdall/bifrost";

Content actions send POST requests with the action id in the query string and X-Heimdall-Content-Action header. CSRF and Bifrost token requests are same-origin GET requests.

8. Trigger Timing Defaults

These config values supply runtime defaults. Per-element attributes still win when they are present on the DOM element.

Heimdall.config.inputDebounceMs
-> default for heimdall-content-input
-> overridden by heimdall-debounce

Heimdall.config.hoverDelayMs
-> default for heimdall-content-hover
-> overridden by heimdall-hover-delay

Heimdall.config.scrollThresholdPx
-> near-end scroll distance
-> overridden by heimdall-scroll-threshold

Heimdall.config.scrollMinIntervalMs
-> minimum time between scroll-triggered actions

9. Boot and DOM Observation

The runtime boots document boundaries on ready. observeDom installs a MutationObserver so newly inserted Heimdall markup is activated automatically.

Heimdall.config.observeDom = true;

// Manual boot is useful when observeDom is false,
// or when an external renderer inserts markup.
Heimdall.boot(document.querySelector("#new-region"));

10. Visible Trigger Timing

visibleRootMargin and visibleThreshold are read once when the IntersectionObserver is first created. Set them before visible elements are booted.

<script src="/_content/HeimdallFramework.Web/heimdall-bundle.min.js"></script>
<script>
  Heimdall.config.visibleRootMargin = "200px 0px";
  Heimdall.config.visibleThreshold = 0.1;
</script>

11. OOB Configuration

OOB processing controls whether returned invocation directives can update other DOM regions outside the main target. Redirect and abort directives are still response directives, but invocation processing is gated by oobEnabled.

// Default: true
Heimdall.config.oobEnabled = true;

// Disable invocation directive processing.
Heimdall.config.oobEnabled = false;

12. SSE Configuration

Bifrost SSE uses global defaults for event name, default swap mode, reconnect behavior, sweep timing, and hidden-tab pause behavior. Subscriber attributes can override event, target, swap, and disable behavior per element.

Heimdall.config.sseDefaultSwap = "none";
Heimdall.config.sseEventName = "heimdall";
Heimdall.config.sseReconnectDelayMs = 250;
Heimdall.config.sseReconnectMaxDelayMs = 10000;
Heimdall.config.sseReconnectBackoffFactor = 2;
Heimdall.config.sseSweepIntervalMs = 5000;
Heimdall.config.ssePauseWhenHidden = false;

Per-subscriber HTML attributes:

heimdall-sse="orders"
heimdall-sse-topic="orders"
heimdall-sse-target="#orders"
heimdall-sse-swap="beforeend"
heimdall-sse-event="order.updated"
heimdall-sse-disable="true"

13. Programmatic Invocation

Use Heimdall.invoke when a browser script needs to run the same content-action request pipeline as a DOM trigger.

const result = await Heimdall.invoke(
  "orders.refresh",
  { page: 2 },
  {
    target: "#orders",
    swap: "inner",
    headers: { "X-Request-Source": "toolbar" },
    onSuccess: result => console.log(result.ms),
    onError: result => console.warn(result.status)
  });

14. Programmatic SSE

Use Heimdall.sse.connect when a script needs to subscribe without a declarative heimdall-sse attribute. The element anchors lifecycle validation for that subscription.

const subscription = Heimdall.sse.connect("orders", {
  element: document.querySelector("#orders-panel"),
  target: "#orders",
  swap: "beforeend",
  event: "order.updated"
});

subscription.close();

Heimdall.sse.disconnect("#orders-panel");
Heimdall.sse.disconnectAll();

15. Runtime Events

The runtime emits CustomEvent notifications on document. Turn on debug for console traces, and use events when application code needs observability around Heimdall work.

Heimdall.config.debug = true;

document.addEventListener("heimdall:before", e => {});
document.addEventListener("heimdall:after", e => {});
document.addEventListener("heimdall:error", e => {});
document.addEventListener("heimdall:abort", e => {});
document.addEventListener("heimdall:redirect", e => {});
document.addEventListener("heimdall:javascript-error", e => {});

document.addEventListener("heimdall:sse-open", e => {});
document.addEventListener("heimdall:sse-close", e => {});
document.addEventListener("heimdall:sse-message", e => {});
document.addEventListener("heimdall:sse-error", e => {});
document.addEventListener("heimdall:sse-pause", e => {});
document.addEventListener("heimdall:sse-resume", e => {});
document.addEventListener("heimdall:sse-reconnect-scheduled", e => {});
document.addEventListener("heimdall:sse-abort", e => {});
document.addEventListener("heimdall:sse-redirect", e => {});

16. When Changes Take Effect

Most values are read at the moment of use. A few bootstrapping values need to be set early because observers and sweep timers are created once.

Read on each request:
endpoints, debug, oobEnabled

Read from each trigger event:
inputDebounceMs, hoverDelayMs,
scrollThresholdPx, scrollMinIntervalMs

Set before first visible boot:
visibleRootMargin, visibleThreshold

Set before ready for automatic DOM observing:
observeDom

Set before SSE starts for initial sweeper interval:
sseSweepIntervalMs

Read during SSE reconnect/pause behavior:
sseReconnectDelayMs, sseReconnectMaxDelayMs,
sseReconnectBackoffFactor, ssePauseWhenHidden

17. Practical Defaults

For most apps, keep the default endpoints, keep observeDom on, keep OOB on, and tune only the user-experience timings that your UI actually needs.

Common application-level tweaks:

Heimdall.config.debug = builderEnvironmentIsDevelopment;
Heimdall.config.inputDebounceMs = 300;
Heimdall.config.hoverDelayMs = 250;
Heimdall.config.ssePauseWhenHidden = true;