Thymeleaf
Ktor allows you to use Thymeleaf templates as views within your application by installing the Thymeleaf plugin.
Add dependencies
To use Thymeleaf, add the ktor-server-thymeleaf artifact to your build script:
implementation("io.ktor:ktor-server-thymeleaf:$ktor_version")
implementation "io.ktor:ktor-server-thymeleaf:$ktor_version"
<dependency>
<groupId>io.ktor</groupId>
<artifactId>ktor-server-thymeleaf-jvm</artifactId>
<version>${ktor_version}</version>
</dependency>
Install Thymeleaf
To install the Thymeleaf plugin to your application, pass it to the install function in the specified module. The following examples show how to install Thymeleaf:
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.application.*
import io.ktor.server.thymeleaf.*
fun main() {
embeddedServer(Netty, port = 8080) {
install(Thymeleaf)
// ...
}.start(wait = true)
}
import io.ktor.server.application.*
import io.ktor.server.thymeleaf.*
// ...
fun Application.module() {
install(Thymeleaf)
// ...
}
Configure template loading
Inside the install block, you can configure the ClassLoaderTemplateResolver. For example, the code snippet below enables Ktor to look up *.html templates in the templates package relative to the current classpath:
import io.ktor.server.application.*
import io.ktor.server.thymeleaf.*
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver
fun Application.module() {
install(Thymeleaf) {
setTemplateResolver(ClassLoaderTemplateResolver().apply {
prefix = "templates/"
suffix = ".html"
characterEncoding = "utf-8"
})
}
}
Send a template in response
Imagine you have the index.html template in resources/templates:
<html xmlns:th="http://www.thymeleaf.org">
<body>
<h1 th:text="'Hello, ' + ${user.name}"></h1>
</body>
</html>
A data model for a user looks as follows:
data class User(val id: Int, val name: String)
To use the template for the specified route, pass ThymeleafContent to the call.respond method in the following way:
get("/index") {
val sampleUser = User(1, "John")
call.respond(ThymeleafContent("index", mapOf("user" to sampleUser)))
}
Example: Auto reload Thymeleaf templates
The example below shows how to reload Thymeleaf templates automatically when development mode is used.
package com.example
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.thymeleaf.*
import org.thymeleaf.templateresolver.*
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
fun Application.module() {
install(Thymeleaf) {
setTemplateResolver((if (developmentMode) {
FileTemplateResolver().apply {
cacheManager = null
prefix = "src/main/resources/templates/"
}
} else {
ClassLoaderTemplateResolver().apply {
prefix = "templates/"
}
}).apply {
suffix = ".html"
characterEncoding = "utf-8"
})
}
routing {
get("/index") {
val sampleUser = User(1, "John")
call.respond(ThymeleafContent("index", mapOf("user" to sampleUser)))
}
}
}
data class User(val id: Int, val name: String)
You can find the complete example here: thymeleaf-auto-reload.
24 April 2026