Exporting using GitHub Workflows

While you can always export your site manually on your machine, you may want to automate this process. A common solution for this is a GitHub workflow.

Below, we include a sample workflow that exports a site and then uploads the results which you can then download from that workflow's summary page:

name: Export Kobweb site

on:
  workflow_dispatch: #A

jobs:
  export_and_upload:
    runs-on: ubuntu-latest
    defaults:
      run:
        shell: bash

    steps:
      # Will fetch latest CLI version and store it in KOBWEB_CLI_VERSION env var
      - name: Fetch latest Kobweb CLI version
        run: |
          VERSION=$(curl -sSL https://raw.githubusercontent.com/varabyte/data/refs/heads/main/kobweb/cli-version.txt | xargs)
          echo "KOBWEB_CLI_VERSION=$VERSION" >> $GITHUB_ENV

      - uses: actions/checkout@v7
      - uses: actions/setup-java@v6
        with:
          distribution: temurin
          java-version: 17 # B

      # When projects are created on Windows, the executable bit is sometimes lost. So set it back just in case.
      - name: Ensure Gradle is executable
        run: chmod +x gradlew

      # C
      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v6

      # D
      - name: Query Browser Cache ID
        id: browser-cache-id
        run: echo "value=$(./gradlew -q :site:kobwebBrowserCacheId)" >> $GITHUB_OUTPUT

      # Also D
      - name: Cache Browser Dependencies
        uses: actions/cache@v6
        id: playwright-cache
        with:
          path: ~/.cache/ms-playwright
          key: ${{ runner.os }}-playwright-${{ steps.browser-cache-id.outputs.value }}

      - name: Fetch kobweb
        uses: robinraju/release-downloader@v1.9
        with:
          repository: "varabyte/kobweb-cli"
          tag: "v${{ env.KOBWEB_CLI_VERSION }}"
          fileName: "kobweb-${{ env.KOBWEB_CLI_VERSION }}.zip"
          tarBall: false
          zipBall: false

      - name: Unzip kobweb
        run: unzip kobweb-${{ env.KOBWEB_CLI_VERSION }}.zip

      - name: Run export
        env:
          KOBWEB_EXPORT_NUM_THREADS: half # E
        run: |
          cd site
          ../kobweb-${{ env.KOBWEB_CLI_VERSION }}/bin/kobweb export --notty --layout static

      # F
      - name: Upload site
        uses: actions/upload-artifact@v7
        with:
          name: site
          path: site/.kobweb/site/
          if-no-files-found: error
          retention-days: 1
.github/workflows/export-site.yml

You can copy this workflow into your own GitHub project and then modify it to your needs.

We tagged some of the workflow code above with lettered comments (#A, #B, ...). Here are some additional notes about those sections:

  • (A) workflow_dispatch: This means that you can manually trigger this workflow from the GitHub UI, which I suggested here to prevent running a potentially expensive export operation without your direct involvement. Of course, you can also configure your workflow to run on a schedule, or on push to a branch, etc. Please refer to the relevant GitHub docs for a full list of events you can use.
  • (B) Java Version: Feel free to change the Java distribution and bump up the Java version to something more recent than what we used here. We are using Java 17 simply because it is the minimum version that the latest version of Gradle requires (at the time of writing this article, at least!)
  • (C) Setup Gradle: This action is optional, but I recommend it as it configures a bunch of caching for you.
  • (D) Caching the browser: kobweb export needs to download a browser the first time it is run. This workflow sets up a cache that saves it across runs. The cache is tagged with a unique ID tied to the current browser version used by Kobweb. If this ever changes in a future release, GitHub will be instructed to use a new cache bucket (allowing GitHub to eventually clean up the old one).
  • (E) Configure export parallelism: This line actually has no effect because "half of available CPU cores" is the default value for KOBWEB_EXPORT_NUM_THREADS. However, you may want to experiment setting this value to "max" (100%), "high" (75%), "1" (disable parallelism), or other values, based on the power of your CI environment, so we included it here. You can delete these lines as well if you are happy with the default behavior.
  • (F) Upload site: This action uploads the exported site as an artifact. You can then download the artifact from the workflow summary page. Your own workflow will likely delete this action and do something else here, like upload to a web server (or some location accessible by your web server) or copy files over into a gh_pages repository. Still, I've included this here (and set the retention days very low) just so you can verify that the workflow is working for your project.

For a simple site, the above workflow should take no more than 2 to 3 minutes to run.

To see a real example, you can review the workflow used by this very site!

Exporting a fullstack site

The above example assumes you want to export a site with a static layout. If you are hoping to export a fullstack site instead, you have to change two lines -- the export itself, and the upload artifacts step:

      - name: Run export
        run: |
          cd site
          ../kobweb-${{ env.KOBWEB_CLI_VERSION }}/bin/kobweb export --notty --layout fullstack

      - name: Upload site
        uses: actions/upload-artifact@v7
        with:
          name: kobweb-folder
          path: site/.kobweb
          include-hidden-files: true
          if-no-files-found: error
          retention-days: 1
Caution

Note how we set the include-hidden-files key to true. If you don't do this, the upload-artifact action filters out the .kobweb path we pass in, ultimately uploading nothing!

I discuss more about exporting fullstack sites in this blog post (since, once you've uploaded the site, you probably want to download it again somewhere.)

This site is open source.
Copyright © 2026 Varabyte. All rights reserved.