Ktor 3.2.1 Help

HTMX integration

HTMX is a lightweight JavaScript library that enables dynamic client-side behavior using HTML attributes. It supports features such as AJAX, CSS transitions, WebSockets, and Server-Sent Events — without writing JavaScript.

Ktor provides experimental, first-class support for HTMX through a set of shared modules that simplify integration in both server and client contexts. These modules offer tools for working with HTMX headers, defining HTML attributes using Kotlin DSLs, and handling HTMX-specific routing logic on the server.

Modules overview

Ktor’s HTMX support is available across three experimental modules:

Module

Description

ktor-htmx

Core definitions and header constants

ktor-htmx-html

Integration with the Kotlin HTML DSL

ktor-server-htmx

Routing support for HTMX-specific requests

All APIs are marked with @ExperimentalKtorApi and require opt-in via @OptIn(ExperimentalKtorApi::class).

HTMX Headers

You can use predefined constants from the core ktor-htmx module to access or set HTMX header in a type-safe way. These constants help you avoid magic strings when detecting HTMX behavior like triggers, history restoration, or content swapping.

Request headers

Use the HxRequestHeaders object to read or match HTMX request headers in your application:

HxRequestHeaders.Request

Always true for HTMX requests

HxRequestHeaders.Target

ID of the target element

HxRequestHeaders.Trigger

ID of the triggered element

HxRequestHeaders.TriggerName

Name of the triggered element

HxRequestHeaders.Boosted

Indicates request via hx-boost

HxRequestHeaders.CurrentUrl

Current browser URL

HxRequestHeaders.HistoryRestoreRequest

For history restoration

HxRequestHeaders.Prompt

User response to hx-prompt

Response headers

You can use the HxResponseHeaders object to access constants for HTMX response headers:

HxResponseHeaders.Location

Client-side redirect without page reload

HxResponseHeaders.PushUrl

Push URL to history stack

HxResponseHeaders.Redirect

Client-side redirect

HxResponseHeaders.Refresh

Force full page refresh

HxResponseHeaders.ReplaceUrl

Replace current URL

HxResponseHeaders.Reswap

Control how response is swapped

HxResponseHeaders.Retarget

Update target of content update

HxResponseHeaders.Reselect

Choose part of response to swap

HxResponseHeaders.Trigger

Trigger client-side events

HxResponseHeaders.TriggerAfterSettle

Trigger events after settle

HxResponseHeaders.TriggerAfterSwap

Trigger events after swap

Swap modes

You can use the HxSwap object from the core ktor-htmx module to access constants for different HTMX swap modes.

HxSwap.innerHtml

Replace inner HTML (default)

HxSwap.outerHtml

Replace entire element

HxSwap.textContent

Replace text content only

HxSwap.beforeBegin

Insert before target element

HxSwap.afterBegin

Insert as first child

HxSwap.beforeEnd

Insert as last child

HxSwap.afterEnd

Insert after target element

HxSwap.delete

Delete target element

HxSwap.none

No content append

HTML DSL extensions

The ktor-htmx-html module adds extension functions to Kotlin’s HTML DSL, allowing you to add HTMX attributes directly to HTML elements:

@OptIn(ExperimentalKtorApi::class) html { body { button { attributes.hx { get = "/data" target = "#result" swap = HxSwap.outerHtml trigger = "click" } +"Load Data" } } }

The above example generates HTML with HTMX attributes:

<button hx-get="/api/data" hx-target="#result-div" hx-swap="outerHTML" hx-trigger="click">Load Data</button>

Server-side routing

The ktor-server-htmx module provides HTMX-aware routing through the hx DSL block:

@OptIn(ExperimentalKtorApi::class) routing { route("api") { // Regular route (both HTMX and non-HTMX requests) get { call.respondText("Regular response") } // Only matches HTMX requests (HX-Request header is present) hx.get { call.respondText("HTMX response") } // Matches HTMX requests with specific target hx { target("#result-div") { get { call.respondText("Response for #result-div") } } // Matches HTMX requests with specific trigger trigger("#load-button") { get { call.respondText("Response for #load-button clicks") } } } } }

These features allow your application to respond differently depending on the HTMX headers sent by the client.

11 July 2025