Kobweb is an opinionated Kotlin framework for creating websites and web apps, built on top of Compose HTML and inspired by Next.js and Chakra UI.
@Page
@Composable
fun HomePage() {
Column(
Modifier.fillMaxWidth().whiteSpace(WhiteSpace.PreWrap).textAlign(TextAlign.Center),
horizontalAlignment = Alignment.CenterHorizontally
) {
var colorMode by ColorMode.currentState
Button(
onClick = { colorMode = colorMode.opposite },
Modifier.borderRadius(50.percent).padding(0.px).align(Alignment.End)
) {
// Includes support for Font Awesome icons
if (colorMode.isLight) FaMoon() else FaSun()
}
H1 {
Text("Welcome to Kobweb!")
}
Span {
Text("Create rich, dynamic web apps with ease, leveraging ")
Link("https://kotlinlang.org/", "Kotlin")
Text(" and ")
Link(
"https://github.com/JetBrains/compose-multiplatform/#compose-html",
"Compose HTML"
)
}
}
}
While Kobweb is still pre-1.0, it has been usable for a while now. It provides escape hatches to lower-level APIs, so you can accomplish anything even if Kobweb doesn't support it yet. Please consider starring the project to indicate interest, so we know we're creating something the community wants. How ready is it?โผ
Our goal is to provide:
- an intuitive structure for organizing your Kotlin website or web app
- automatic handling of routing between pages
- a collection of useful batteries included widgets built on top of Compose HTML
- an environment built from the ground up around live reloading
- static site exports for improved SEO
- support for responsive (i.e. mobile and desktop) design
- out-of-the-box Markdown support
- a way to easily define server API routes and persistent API streams
- support for creating and using web workers
- a growing collection of general purpose utilities added on top of Compose HTML and Kotlin/JS (learn moreโผ)
- an open source foundation that the community can extend
- and much, much more!
๐ You can find a detailed guide at https://kobweb.varabyte.com/docs
You can also check out my talk at Droidcon SF 24 for a high level overview of Kobweb. The talk showcases what Kobweb can do, introduces Compose HTML (which it builds on top of), and covers a wide range of frontend and backend functionality. It is light on code but heavy on understanding the structure and capabilities of the framework.
Here's a demo where we create a Compose HTML project from scratch with Markdown support and live reloading, in under 10 seconds:
kobweb-demo.mp4
The first step is to get the Kobweb binary. You can install it, download it, and/or build it, so we'll include instructions for all these approaches.
Major thanks to aalmiray and helpermethod to helping me get these installation options working. Check out JReleaser if you ever need to do this in your own project!
OS: Mac and Linux
$ brew install varabyte/tap/kobweb
OS: Windows
# Note: Adding buckets only has to be done once.
# Feel free to skip java if you already have it
> scoop bucket add java
> scoop install java/openjdk
# Install kobweb
> scoop bucket add varabyte https://github.com/varabyte/scoop-varabyte.git
> scoop install varabyte/kobweb
OS: Windows, Mac, and *nix
$ sdk install kobweb
Thanks a ton to aksh1618 for adding support for this target!
With an AUR helper, e.g.:
$ yay -S kobweb
$ paru -S kobweb
$ trizen -S kobweb
# etc.
Without an AUR helper:
$ git clone https://aur.archlinux.org/kobweb.git
$ cd kobweb
$ makepkg -si
Please see: varabyte/kobweb-cli#11 and consider leaving a comment!
Our binary artifact is hosted on GitHub. To download the latest, you can either grab the zip or tar file from GitHub or you can fetch it from your terminal:
$ cd /path/to/applications
# You can either pull down the zip file
$ wget https://github.com/varabyte/kobweb-cli/releases/download/v0.9.18/kobweb-0.9.18.zip
$ unzip kobweb-0.9.18.zip
# ... or the tar file
$ wget https://github.com/varabyte/kobweb-cli/releases/download/v0.9.18/kobweb-0.9.18.tar
$ tar -xvf kobweb-0.9.18.tar
and I recommend adding it to your path, either directly:
$ PATH=$PATH:/path/to/applications/kobweb-0.9.18/bin
$ kobweb version # to check it's working
or via symbolic link:
$ cd /path/to/bin # some folder you've created that's in your PATH
$ ln -s /path/to/applications/kobweb-0.9.18/bin/kobweb kobweb
Although we host Kobweb artifacts on GitHub, it's easy enough to build your own.
Building Kobweb requires JDK11 or newer. We'll first discuss how to add it.
If you want full control over your JDK install, manually downloading is a good option.
- Download a JDK for your OS
- Unzip it somewhere
- Update your
JAVA_HOME
variable to point at it.
JAVA_HOME=/path/to/jdks/corretto-11.0.12
# ... or whatever version or path you chose
For a more automated approach, you can request IntelliJ install a JDK for you.
Follow their instructions here: https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk
The Kobweb CLI is actually maintained in a separate GitHub repo. Once you have the JDK set up, it should be easy to clone and build it:
$ cd /path/to/src/root # some folder you've created for storing src code
$ git clone https://github.com/varabyte/kobweb-cli
$ cd kobweb-cli
$ ./gradlew :kobweb:installDist
Finally, update your PATH:
$ PATH=$PATH:/path/to/src/root/kobweb-cli/kobweb/build/install/kobweb/bin
$ kobweb version # to check it's working
If you previously installed Kobweb and are aware that a new version is available, the way you update it depends on how you installed it.
Method | Instructions |
---|---|
Homebrew | brew update brew upgrade kobweb |
Scoop | scoop update kobweb |
SDKMAN! | sdk upgrade kobweb |
Arch Linux | Rerunning install steps should work. If using an AUR helper, you may need to review its manual. |
Downloaded from Github |
Visit the latest release. You can find both a zip and tar file there. |
$ cd /path/to/projects/
$ kobweb create app
You'll be asked a few questions required for setting up your project.
You don't need to create a root folder for your project ahead of time - the setup process will prompt you for one to create. For the remaining parts of this section, let's say you choose the folder "my-project" when asked.
When finished, you'll have a basic project with two pages - a home page and an about page (with the about page written in markdown) - and some components (which are collections of reusable, composable pieces). Your own directory structure should look something like this:
my-project
โโโ site/src/jsMain
โโโ kotlin.org.example.myproject
โ โโโ components
โ โ โโโ layouts
โ โ โ โโโ MarkdownLayout.kt
โ โ โ โโโ PageLayout.kt
โ โ โโโ sections
โ โ โ โโโ Footer.kt
โ โ โ โโโ NavHeader.kt
โ โ โโโ widgets
โ โ โโโ IconButton.kt
โ โโโ pages
โ โ โโโ Index.kt
โ โโโ AppEntry.kt
โโโ resources/markdown
โโโ About.md
Note that there's no index.html or routing logic anywhere! We generate that for you automatically when you run Kobweb. This brings us to the next section...
$ cd your-project/site
$ kobweb run
This command spins up a web server at http://localhost:8080. If you want to configure the port, you can do so by editing
your project's .kobweb/conf.yaml
file.
You can open your project in IntelliJ and start editing it. While Kobweb is running, it will detect changes, recompile, and deploy updates to your site automatically.
If you don't want to keep a separate terminal window open beside your IDE window, you may prefer alternate solutions.
You can use the IntelliJ terminal tool window to run
kobweb
within it. If you run into a compile error, the stack trace lines will get decorated with
links, making it easy to navigate to the relevant source.
kobweb
itself delegates to Gradle, but nothing is stopping you from calling the commands yourself. You can create
Gradle run configurations for each of the Kobweb commands.
Tip
When you run a Kobweb CLI command that delegates to Gradle, it will log the Gradle command to the console. This is how you can discover the Gradle commands discussed in this section.
- To start a Kobweb server, use the
kobwebStart -t
command.- The
-t
argument (or,--continuous
) tells Gradle to watch for file changes, which gives you live loading behavior.
- The
- To stop a running Kobweb server, use the
kobwebStop
command. - To export a site, use
kobwebExport -PkobwebReuseServer=false -PkobwebEnv=DEV -PkobwebRunLayout=FULLSTACK -PkobwebBuildTarget=RELEASE -PkobwebExportLayout=FULLSTACK
- If you want to export a static layout instead, change the last argument to
-PkobwebExportLayout=STATIC
.
- If you want to export a static layout instead, change the last argument to
- To run an exported site, use
kobwebStart -PkobwebEnv=PROD -PkobwebRunLayout=FULLSTACK
- If your site was exported using a static layout, change the last argument to
-PkobwebRunLayout=STATIC
.
- If your site was exported using a static layout, change the last argument to
You can read all about IntelliJ's Gradle integration here. Or to just jump straight into how to create run configurations for any of the commands discussed above, read these instructions.
Kobweb will provide a growing collection of samples for you to learn from. To see what's available, run:
$ kobweb list
You can create the following Kobweb projects by typing `kobweb create ...`
โข app: A template for a minimal site that demonstrates the basic features of Kobweb
โข examples/jb/counter: A very minimal site with just a counter (based on the Jetbrains tutorial)
โข examples/todo: An example TODO app, showcasing client / server interactions
For example, kobweb create examples/todo
will instantiate a TODO app locally.
Kobweb publishes its libraries to Maven Central and its plugins to the Gradle Plugin Portal. Therefore, Kobweb
recommends setting up your project's settings.gradle.kts
like so:
pluginManagement {
repositories {
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositories {
mavenCentral()
google()
}
}
Tip
All Kobweb templates embrace this pattern, so if you start your own project by building on top of any of them, then this will already be done for you.
Dependencies on Maven Central and the Gradle Plugin Portal are so standard, it's hard to imagine a project that isn't already using them, so in most cases, you won't have to do anything.
Occasionally, especially if you file an issue for a bug fix or a feature request, our team may ask you if you're willing to try using a snapshot build (a dev build, essentially).
Snapshots are, by design, not supported in either Maven Central nor the Gradle Plugin Portal. Therefore, we host all
plugin and library artifacts in a separate official snapshot repository (at
https://s01.oss.sonatype.org/content/repositories/snapshots/
). As a result, you will have to declare this repository
for both plugin and library blocks.
An easy way to enable this is by adding the following block of code into your settings.gradle.kts
file:
pluginManagement {
repositories {
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositories {
mavenCentral()
google()
}
}
+ // The following block registers dependencies to enable Kobweb snapshot support. It is safe to delete or comment out
+ // this block if you never plan to use them.
+ gradle.settingsEvaluated {
+ fun RepositoryHandler.kobwebSnapshots() {
+ maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") {
+ content { includeGroupByRegex("com\\.varabyte\\.kobweb.*") }
+ mavenContent { snapshotsOnly() }
+ }
+ }
+
+ pluginManagement.repositories { kobwebSnapshots() }
+ dependencyResolutionManagement.repositories { kobwebSnapshots() }
+ }
Caution
The above code, adding repositories inside the settingsEvaluated
block, is actually not Gradle idiomatic -- that
approach would be to create a settings plugin or just copy/paste the repository declaration in all relevant places --
but at the moment we are suggesting this approach for its simplicity:
- If we could have declared a top level method in the settings file that both blocks could have called, that would
have been a nice option to recommend. However, the
pluginManagement
block is "magic" and you cannot share code with it. This approach lets us at least mimic that kind of solution. - Keeping the snapshot declaration logic separated in its own block makes it easy to remove it later if you decide you don't want to keep it anymore.
- This approach is isolated inside a single file, while a settings plugin would be a lot of work that would require touching several files, which is probably not worth it just for enabling snapshots.
The project templates created by Kobweb all embrace Gradle version catalogs.
If you're not aware of it, it's a file that exists at gradle/libs.versions.toml
. If you find yourself wanting to tweak
or add new versions to projects you originally created via kobweb create
, that's where you'll find them.
For example, here's the libs.versions.toml we use for our own landing site.
To read more about the feature, please check out the official docs.
The latest available version of Kobweb is declared at the top of this README. If a new version has come out, you can
update your own project by editing gradle/libs.version.toml
and updating the kobweb
version there.
Important
You should double-check COMPATIBILITY.md to see if you also need to update your kotlin
and
jetbrains-compose
versions as well.
Caution
It can be confusing, but Kobweb has two versions -- the version for the library itself (the one that is applicable in this situation), and the one for the command line tool.
If you got this far, it is time to start reading the manual!
๐ https://kobweb.varabyte.com/docs
The guide walks you through all Kobweb concepts, organized into sections to make it easier to read as well as later continue where you left off.
Important
All the documentation for Kobweb used to live in this README, but it was getting so long as to be unwieldy. You may have ended up at this section after following an old link found in the wild. We apologize for the inconvenience, but you should be able to find the relevant information by visiting the guide and using the search bar found in the top right of the page.
In the beginning, Kobweb was only intended to be a thin layer on top of Compose HTML, but the more we worked on it, the more we ran into features that were simply not yet implemented in Compose HTML. In other cases, we found ourselves reaching for utilities that we wished existed in Kotlin/JS browser APIs. As we began adding these features, we realized it would have been a shame to bury them deep inside our framework.
As a result, we created two modules:
compose-html-ext
, where we put code that we would be more than happy for the Compose HTML team to fork and migrate over to Compose HTML someday.browser-ext
, a collection of general purpose utilities that we think could be useful to any Kotlin/JS project targeting the browser.
The features across these modules include (not comprehensive):
- a ton of missing type-safe wrappers around many, many CSS properties
- type-safe wrappers around CSS functions, like gradients, filters,
calc
(especially useful when working with CSS variables), etc. - rich SVG support
- utility methods around saving files to / loading files from the disk
- utility methods and classes built on top
of
window.fetch
(for example, making it easier to use the most common HTTP verbs like GET, POST, etc., as well as providingsuspend fun
versions of fetch) - additions for the missing transition events
- implementations of resize and intersection observers
- utility methods for getting a sequence of descendant/ancestor HTML elements, useful for walking the DOM tree in a Kotlin-idiomatic way
- a utility composable,
GenericTag
, which is an easy-to-use API wrapping Compose HTML'sTagElement
composable, with additional namespacing support if needed (for example, required when implementing SVG elements) - a utility class for working with CSS variables,
StyleVariable
, allows specifying a default value, provides first-class number/string variable support, and fixes a bug in Compose HTML'sCSSStyleVariable
class where it can accept invalid values. setTimeout
andsetInterval
methods that are more Kotlin-idiomatic (e.g. the lambdas are the last parameter)
Note
Some users have mentioned we should have opened PRs for the Compose HTML team instead of maintaining a separate codebase. However, after observing that JetBrains was focusing more and more of its energy on Compose Multiplatform for Web, we decided to implement the features we needed in our own project. This way, we could maintain our velocity while allowing their team to pick and choose what they agreed with at some point in the future at their leisure. There's so much code here, especially around CSS APIs, that getting mired down in PR discussions would have ground our progress to a halt.
If you want to use Compose HTML but not Kobweb, or Kotlin/JS but not Compose HTML, you can still use and benefit
from compose-html-ext
or browser-ext
in your own project. An example build script could look like this (here, for a
non-Kobweb Compose HTML project):
// build.gradle.kts
plugins {
kotlin("multiplatform") version "..."
}
repositories {
mavenCentral()
google()
}
kotlin {
js().browser()
sourceSets {
jsMain.dependencies {
implementation(compose.html.core)
implementation(compose.runtime)
implementation("com.varabyte.kobweb:compose-html-ext:...") // IMPORTANT!!!
}
}
}
Note
The compose-html-ext
dependency automatically provides the browser-ext
dependency.
And of course, if you use Kobweb, it provides both.
Jetbrains is working on the "Compose Multiplatform UI Framework", which allows developers to use the same codebase across Android, iOS, Desktop, and the Web. And it may seem like the Kobweb + Silk approach is obsoleted by it.
It's first worth understanding the core difference between the two approaches. With Compose Multiplatform, the framework owns its own rendering pipeline, drawing to a buffer. In contrast, Compose HTML modifies an HTML / CSS DOM tree and leaves it up to the browser to do the final rendering.
This has major implications on how similar the two APIs can get. For example, in Compose Multiplatform, the order you apply modifiers matters. However, in Compose HTML, this action simply sets html style properties under the hood, where order does not matter.
Due to its reputation, ditching HTML / CSS entirely at first can seem like a total win, but this approach has several limitations:
- robots would lose the ability to crawl and index your site, hurting SEO.
- your initial render may take longer (as nothing will be rendered until your site's logic is downloaded and run for one frame).
- your site will need to allocate a large canvas buffer, which could be very expensive on high-res, wide-screen desktops.
- your UI will be opaque to the powerful suite of devtools that come bundled with browsers.
- you won't have the ability to style unvisited vs visited links differently (this information is hidden from you by the browser for security reasons and can only be set through HTML / CSS).
- you won't have the ability to turn elements on / off when printing the page.
- accessibility tools for browsers might not work.
- the download size of the rendering components is not insignificant and apparently not very compressible, often resulting in a site's basic footprint being 4-6x larger total (e.g. 200-400K vs. 2-3MB for small sites).
It would also prevent a developer from making use of the rich ecosystem of Javascript libraries out there.
Finally, Kobweb is more than just Kotlin-ifying HTML / CSS. It also provides rich integration with powerful web technologies like web workers and websockets.
For now, I am making a bet that there will always be value in embracing the web, providing a framework that sticks to HTML / CSS but offers a growing suite of UI widgets, layouts, and other features that make it a more comfortable experience for the Kotlin developer.
For example, the flexbox layout is a very powerful concept,
but it can be very tricky to use. In most cases, you'll find it's much easier to compose Row
s and Column
s together
than trying to remember if you should be justifying your items or aligning your content, even if Row
s and Column
s
are just configuring the correct HTML / CSS for you behind the scenes.
Ultimately, I believe there is room for both Compose Multiplatform and Kobweb. If you want to make an app experience that feels the same on Android, iOS, Desktop, and Web, then Compose Multiplatform could be the right choice for you. However, if you just want to make a traditional website but want to use Kotlin instead of TypeScript, Kobweb can provide an excellent development experience for that case.
Current state: Foundations are in place! You may encounter API gaps.
You may wish to refer to our Kobweb 1.0 roadmap document.
Kobweb is becoming quite functional. We are already using it to build https://kobweb.varabyte.com and https://bitspittle.dev. Several users have created working portfolio sites already, and I'm aware of at least two cases where Kobweb was used in a project for a client.
At this point:
- It is easy to set up a new project and get things running quickly.
- The live reloading flow is pretty nice, and you'll miss it when you switch to projects that don't have it.
- It supports generating pages from Markdown that can reference your Composable code.
- While it's not quite a server-side rendering, you can export static pages which will get hydrated on load.
- A huge range of CSS properties are supported, along with support for style variables and animations.
- You can use the
Modifier
builder for a significant number of CSS properties. - Silk components are color-mode aware and support responsive behavior.
- There are quite a few widgets available, and it's easy to create your own.
However, there's always more to do.
- I'm trying to add support for every stabilized CSS property, but some are still missing, especially less common ones. (You can use a fallback for such cases in the meantime).
- There are still a handful of widgets planned to be added.
- A lot of detailed documentation is planned to go into the Kobweb site (linked just above) but it isn't done yet.
I think there's enough here now to let you do almost anything you'd want to do, as either Kobweb supports it or you can escape hatch to underlying Compose HTML / Kotlin/JS approaches, but there might be some areas where it's still a bit DIY. It would be great to get real-world experience to hear what issues users are actually running into.
In general, please understand that we are still pre-1.0, and as such, there is an expectation that you'll be a little more tolerant to occasional API migrations, unlike if you were using a more stable library.
We strive hard to ensure that any code we deprecate is kept around for at least 6 months, but after that, we are likely to remove it. This allows our very lean team to stay nimble as we focus on getting to a 1.0 release.
So, should you use Kobweb at this point? If you are...
- playing around with Compose HTML for the first time and want to get up and running quickly on a toy project:
- YES!!! Please see the connecting with usโผ section below, we'd definitely love to hear from you. It's still a good time if you want to have a voice in the direction of this project.
- a Kotlin developer who wants to write a small web app or create a new blog from scratch:
- Probably! I hope if you evaluate Kobweb at this point, you'll find a lot to like. You can get in touch with us at our Discord if you try it and have questions or run into missing features.
- someone who already has an existing project in progress and wants to integrate Kobweb into it:
- Maybe not? Depending on how much work you've done, it may not be a trivial refactor. You can review this guide on adding Kobweb to an existing project if you want to try anyway.
- a company:
- Probably not? I'm assuming most companies are so risk-averse they would not even use Compose HTML, which Kobweb is built on top of. If you were considering Compose HTML, however, Kobweb is worth a look.
On the fence but not sure? Connect with us, and I'd be happy to help you assess your situation.
I'm pleased to mention that Kobweb has received feedback from some satisfied users. Here are a few:
- "This is a pretty bloody amazing technology you've created here. I have been dreading upgrading [my] website for ages because I didn't want to go back to html and css ๐ซค now I can stay with Kotlin ๐"
- "Kobweb looks fantastic and I've been [trying] to use Kotlin in all parts of [my] hobby stuff and work, so I got real excited when I saw Kobweb, [even though] I hadn't been satisfied with a web framework in a long time. Incredible work."
- "I started using Kobweb last week and I have to say this [...] reinvented web development for me. [...] I used to hate html css. After getting my hands on kobweb Iโm in love with it."
- "Finally got paid -- all thanks to kobweb ๐๐ฅ"
- "I didn't wanna learn any JS framework so when I first learned about kobweb it felt like a no-brainer; having built 2 Android apps with compose already and a backend with ktor. One could argue Android developers are the best target audience since the additional knowledge needed to move an app to the web with Kobweb is minimal. I love it! ๐คฉ"
- Join my Discord!
- GitHub Discussions for this project
- The Kobweb channel on the Kotlin Slack
- You can send direct queries to my email
If you're comfortable with it, using Discord is recommended, because there's a growing community of users in there who can offer help even when I'm not around.
It is still early days, and while we believe we've proven the feasibility of this approach at this point, there's still plenty of work to do to get to a 1.0 launch! We are hungry for the community's feedback, so please don't hesitate to:
- Open an issue
- Contact us (using any of the ways mentioned above) telling us what features you want
- Ask us for guidance, especially as there are no tutorials yet (your questions can help us know what to write first!)
Thank you for your support and interest in Kobweb!
You should feel no obligation to pay anything to use Kobweb -- it is licensed liberally quite intentionally and given to the community without any strings attached.
However, if you like what we are doing and are determined to support our efforts financially, we would gratefully accept a donation at ko-fi.com/bitspittle. Money will go towards development fees and rewarding contributors.
Alternately, there are countless non-financial ways to support this project, such as:
- Just use Kobweb and spread the word!
- Consider tagging your website with a "Made with Kobweb" blurb in the footer.
- Write articles about Kobweb / share your experience using it.
- Send us feedback, be it appreciative or critical. Please don't be shy about letting us know if there are things you feel are missing. If you have ideas that you think can make Kobweb better, please share them.
- Join our community on Discord and/or Slack and answer questions.
- Pick up a bug or feature to work on.
Ultimately, I want Kobweb to be known for having a kind, patient, and welcoming community. As long as you are helping us accomplish that, then please consider yourself already supporting our efforts.