Kobweb is a framework built on Compose HTML, which itself is a reactive web UI framework from JetBrains that allows you to create web apps in Kotlin using a powerful API.
You can also read more about Kobweb from this earlier post.
In this post, we'll talk about how to use Kobweb to export your Compose HTML project into a format that can be consumed by various static website hosting providers. This means you can get fast and cheap (often free!) hosting for your Kotlin website.
These background sections are provided for people new to the world of frontend development and/or who are curious about Kobweb.
However, if you're ready to get your hands dirty, feel free to skip over them▼.
Compose HTML is an excellent tool for building a single-page application (SPA).
That is, it produces a single, minimal index.html
file plus some JavaScript and other resources that can be used to build your app up at runtime. Once the page is loaded by the browser and the script starts running, it continuously modifies the page's DOM in place to give the user the illusion that they're actually navigating around multiple pages as they click around on stuff.
Let's use this blog as a concrete example.
For a Compose HTML project, if a user entered a URL like https://bitspittle.dev/blog/staticdeploy
, the request would be intercepted before the browser could handle it, and its URL path would get parsed.
Based on the result (in this case, the value "/blog/staticdeploy"
), your project would dynamically choose to start rendering a new page associated with that path (so, maybe mysite.pages.blog.StaticDeployPage()
).
The core of your project is essentially a giant switch statement acting on a string value. You can imagine something like the following psuedocode:
// Inside your main `renderComposable`
val path by getPath() // Path updated when browser URL changes
when (path) {
"/blog/aboutme" -> mysite.pages.blog.AboutMePage()
"/blog/staticdeploy" -> mysite.pages.blog.StaticDeployPage()
// ... etc. ...
}
The above approach is fine as long as your server understands that this is happening! In other words, if I make a request to a server asking for resources associated with /blog/staticdeploy
, it should just send me the default index.html
page and its JavaScript, knowing that the JavaScript code is what will handle understanding the URL.
But static website host providers are simple. They blindly serve static files.
So if a user makes a request to a static website host provider for the path /blog/staticdeploy
, then a file called blog/staticdeploy.html
better exist on it or else that user is getting a 404 error.
Unlike Compose HTML, Kobweb can handle this problem because it sits one level above it. It is aware of all the pages on your site (since it is the one that generates the routing logic for you), and it comes with a binary that can run a bunch of useful, project-managing commands.
The important command in this case:
$ kobweb export --layout static
When you ask Kobweb to export your site, it will spin up a local Kobweb server, visit each page in turn, and save out its state to an html file. In this way, Kobweb can turn your dynamic Compose HTML pages into static snapshots.
For this article, we'll discuss two options, for two very popular (and, more importantly, free!) providers: Netlify and GitHub Pages.
Note: I am not affiliated with or sponsored by Netlify or GitHub in any way. Their inclusion here is because they are what users in my Discord server mentioned they were familiar with.
We'll start with steps common to both approaches.
Requirements
git
kobweb
binary (installation instructions)If you already have a project, you can skip this step.
Otherwise, run the following command, so you'll have something concrete to work with for the rest of this article:
$ kobweb create app
# Kobweb asks a bunch of questions, but defaults should be fine
$ cd app
The above steps should have offered to initialize your project with git
, but if you told it not to or if it didn't work for some reason, you can manually initialize it yourself:
$ git init -b main
$ git add . && git commit -m "Initial commit"
Follow the official instructions to create a new GitHub repository. You can choose whatever name you want. I used kobweb-netlify-demo
for Netlify and kobweb-ghp-demo
for GitHub Pages.
When given an opportunity to populate this repo with a README
and .gitignore
, don't! Since Kobweb already creates them for you.
When finished, sync your local project with the GitHub repo:
# REMOTE_URL looks something like
# https://github.com/<user>/<repo>.git
$ git remote add origin <REMOTE_URL>
$ git push -u origin main
Note: You should have finished the common steps▲ first. If you want to use GitHub Pages instead, skip to that section▼.
Netlify is becoming a popular solution for developers who want to create static websites that get served fast. They detect changes to your GitHub repository and publish your site in seconds.
It's free! Sign up here.
Add new site
buttonImport an Existing Project
GitHub
as your git providerEventually, you will reach a page that asks you to provide build settings. Leave everything blank except for the publish directory
field, which you can set to site/.kobweb/site
:
.kobweb/site
in gitignoreBy default, Kobweb is set up so that you don't check your exported site into source control.
However, for simplicity with Netlify's workflow, we're going to commit our exported site directly into our repository.
Open up the .gitignore
file in your project's site/
folder and add the line !.kobweb/site
to the bottom:
...
# Kobweb ignores
.kobweb/*
!.kobweb/conf.yaml
!.kobweb/site
# in kobweb-netlify-demo/site/...
$ kobweb export --layout static
This will run for a little while. When finished, run
$ git status
to verify that new files are now ready to be added.
If not, double-check your .gitignore
changes from the last step and also make sure that files were actually written to your .kobweb/site
folder.
$ git add . && git commit -m "Exported site"
$ git push
If everything went well, you should have a page that is either deployed or well on its way! It only takes a few seconds once Netlify is aware of the pushed changes.
Go to your Netlify dashboard. You should see an entry like the one I have here:
Click on it, and you should be taken to a page that has your URL in it:
If you click on the link, you should see a site that looks like this.
If so, congratulations! You're done. 🎉
If you're still having issues, feel free to compare your project with mine.
Note: You should have finished the common steps▲ first. If you want to use Netlify instead, go back to that section▲.
There are a few options for configuring GitHub Pages, and discussing them all is out of scope for this post. Instead, we'll go with the easiest -- using a docs/
root within your project.
Settings
tabCode and automation
section of the sidebar, click Pages
Source
section, set Branch
to main
and the folder to /docs
Save
As you can see, we don't have a lot of control over GitHub Pages. Since we can't change GitHub, we must change ourselves instead.
An additional wrinkle is that GitHub Pages deploys your site to a subfolder. This will look something like https://<user>.github.io/<project>/
. This means that if you try to navigate to the root in your Kobweb site (i.e. Link("/")
), or reference resources from the resource root (e.g. /images/example.png
), the browser will think you're asking to search against https://<user>.github.io
instead of the subdirectory!
Because GitHub Pages requires you to put your files under docs/
, and also because it serves your site under a subfolder instead of the root, you will need to modify two values in your .kobweb/conf.yaml
, "routePrefix" and "siteRoot":
site:
title: "..."
routePrefix: "<repo-project-name>"
# i.e. the name you chose for your repo.
# In my case, the value: "kobweb-ghp-demo"
# but your name is probably different...
server:
files:
dev:
contentRoot: "..."
script: "..."
api: "..."
prod:
# Kobweb content is in a subfolder. Need to export to the root, so use ".."
siteRoot: "../docs"
# in kobweb-ghp-demo/site/...
$ kobweb export --layout static
This will run for a little while. When finished, run
$ git status
to verify that new files are now ready to be added.
$ git add . && git commit -m "Exported site"
$ git push
If everything went well, you should have a page that is either deployed or well on its way! It takes less than a minute once GitHub is aware of the pushed changes.
Once it's ready, you can visit your GitHub Pages site, which uses a URL with a format like https://<user>.github.io/<project>
.
For example, my site is at https://bitspittle.github.io/kobweb-ghp-demo/.
Are you seeing something similar at your link? If so, congratulations! You're done. 🥳
If you're still having issues, feel free to compare your project with mine.
As you can see, static website hosting is cheap, fast, and easy to set up. There are a lot of options you can use besides the two listed here, including other popular features such as Firebase Hosting and AWS.
Compose HTML is an amazing API. And static website hosting is an amazing service. If you use Kobweb, you won't have to choose one or the other, but you can revel in the benefits of both!