Fork me on GitHub
  1. What is Kweb?
  2. Features
  3. How does it work?
  4. What does it look like?

What is Kweb?

Kweb is a library for building web applications in the Kotlin programming language.

Kweb is fairly unusual in that, while your code runs on the server, Kweb allows you to interact to the browser DOM directly as if it was local to the web server.

For example, here we create a <p> element and set its text:

doc.body.p().text("this is an example HTML paragraph")

Kweb has plugins for JavaScript libraries like JQuery and others. It’s also surprisingly easy to build your own plugins for other JavaScript libraries, or extend those Kweb already supports.

status experimental

Kweb is currently experimental, please play with it, give us feedback, join our development effort, but remember that it is still a few months away (Mar 2018) from being suitable for non-experimental use.


  • Build websites in Kotlin
  • Makes the barrier between web-browser and web-server largely invisible to the programmer
  • Seamlessly integrates with powerful JavaScript libraries like JQuery, Semantic-UI, and others
  • Update your web browser instantly in response to code changes
  • Bind DOM elements in the browser directly to persistent state on the server and have them update automatically, through the observer and data mapper patterns, using the Shoebox persistent state store.
  • Easy to add to an existing project, Kweb is just a library, it doesn’t seek to tell you how your project should be organized

How does it work?

Kweb keeps all of the logic server-side, and uses efficient websockets to communicate to web browsers. We also take advantage of Kotlin’s powerful new coroutines mechanism to efficiently handle asynchronicity, largly invisibly to the programmer.

What does it look like?

Here is the main code for a simple to-do list app, find the full app here:

fun main(args: Array<String>) {
    // Starts a web server listening on port 8091
    Kweb(port = 8093, debug = true, plugins = listOf(semanticUIPlugin)) { {
            div(semantic.ui.three.column.centered.grid).new {
                div(semantic.column).new {
                    h1(Style.listHeadingStyle).text("Shopping list")

                    route(withGalimatiasUrlParser) { url ->
                        div(semantic.content).new {
                            render(url.path[0]) { entityType ->
                                when (entityType) {
                                    ROOT_PATH -> {
                                    "lists" -> {
                                        render(url.path[1]) { listUid ->
                                            try {
                                                val list = asBindable(State.lists, listUid)
                                            } catch (e : NoSuchElementException) {
                                                throw NotFoundException("Can't find list with id $listUid")
                                    else -> {
                                        throw NotFoundException("Unrecognized entity type '$entityType', path: ${url.path.value}")

Next: Setting Up »»