Installation (Gradle)

// Dust: 
implementation group: "org.http4k", name: "http4k-template-dust", version: ""

// Freemarker: 
implementation group: "org.http4k", name: "http4k-template-freemarker", version: ""

// Handlebars: 
implementation group: "org.http4k", name: "http4k-template-handlebars", version: ""

// Jade4j: 
implementation group: "org.http4k", name: "http4k-template-jade4j", version: ""

// Pebble: 
implementation group: "org.http4k", name: "http4k-template-pebble", version: ""

// Thymeleaf: 
implementation group: "org.http4k", name: "http4k-template-thymeleaf", version: ""


The http4k templating API provides a standard mechanism for rendering using common templating libraries. Simply implement the ViewModel interface on a model class and pass it to the renderer to get a string. All of the implementations support view rendering using the following strategies:

  • Cached on the classpath
  • Cached from the filesystem
  • Hot-Reloading from the filesystem

The examples below are for Handlebars, but the others have the same APIs:


package guide.modules.templating

import org.http4k.core.Body
import org.http4k.core.ContentType.Companion.TEXT_HTML
import org.http4k.core.HttpHandler
import org.http4k.core.Method.GET
import org.http4k.core.Request
import org.http4k.core.Response
import org.http4k.core.Status.Companion.OK
import org.http4k.core.with
import org.http4k.template.HandlebarsTemplates
import org.http4k.template.ViewModel
import org.http4k.template.viewModel
import java.io.File

data class Person(val name: String, val age: Int) : ViewModel

fun main() {

    // first, create a Renderer - this can be a Caching instance or a HotReload for development
    val renderer = HandlebarsTemplates().HotReload("src/test/resources")

    // first example uses a renderer to create a string
    val app: HttpHandler = {
        val viewModel = Person("Bob", 45)
        val renderedView = renderer(viewModel)
    println(app(Request(GET, "/someUrl")))

    // the lens example uses the Body.viewModel to also set the content type, and avoid using Strings
    val viewLens = Body.viewModel(renderer, TEXT_HTML).toLens()

    val appUsingLens: HttpHandler = {
        Response(OK).with(viewLens of Person("Bob", 45))

    println(appUsingLens(Request(GET, "/someUrl")))

    // overwrite the content - this will prove the hot reload works!
        .use { it.write("{{name}} is not {{age}} years old") }

    println(appUsingLens(Request(GET, "/someUrl")))