A modern framework for full stack web apps in Kotlin

Overview

version: 0.6.4 Varabyte Discord Follow @bitspittle

K ๐Ÿ•ธ๏ธ bweb

Kobweb is an opinionated Kotlin framework for creating websites and web apps, built on top of Web Compose and inspired by Next.js and Chakra UI.

@Page
@Composable
fun HomePage() {
  Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
    Row(Modifier.align(Alignment.End)) {
      var colorMode by rememberColorMode()
      Button(
        onClick = { colorMode = colorMode.opposite() },
        Modifier.clip(Circle())
      ) {
        Box(Modifier.padding(4.px)) {
          // Includes support for Font Awesome icons
          if (colorMode.isLight()) FaSun() else FaMoon()
        }
      }
    }
    H1 {
      Text("Welcome to Kobweb!")
    }
    Row {
      Text("Create rich, dynamic web apps with ease, leveraging ")
      Link("https://kotlinlang.org/", "Kotlin")
      Text(" and ")
      Link("https://compose-web.ui.pages.jetbrains.team/", "Web Compose")
    }
  }
}


Kobweb is currently in technology preview. 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 Web Compose
  • an environment built from the ground up around live reloading
  • static site exports for improved SEO
  • shared, rich types between client and server
  • out-of-the-box Markdown support
  • an open source foundation that the community can extend
  • and much, much more!

Here's a demo where we create a Web Compose website from scratch with Markdown support and live reloading, in under 10 seconds:

kobweb-demo.mp4

Trying it out yourself

The first step is to get the Kobweb binary. You can download it or build it, so we'll include instructions for both approaches.

Download the Kobweb binary

Our binary artifact is hosted on github. To download latest:

$ cd /path/to/applications/kobweb
$ wget https://github.com/varabyte/kobweb/releases/download/v0.6.4/kobweb-0.6.4.zip
$ unzip kobweb-0.6.4.zip

and I recommend adding it to your path, either directly:

$ PATH=$PATH:/path/to/applications/kobweb/kobweb-0.6.4/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/kobweb-0.6.4/bin/kobweb kobweb

Build the Kobweb binary

Although we host Kobweb artifacts on github, it's easy enough to build your own.

Note: Building Kobweb requires JDK11 or newer. If you don't already have this set up, the easiest way is to download a JDK, unzip it somewhere, and 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

With JAVA_HOME set up, building is just a single Gradle command:

$ cd /path/to/src/root
$ git clone --recurse-submodules https://github.com/varabyte/kobweb
$ cd kobweb
$ ./gradlew :cli: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

Create your Kobweb site

$ cd /path/to/projects/
$ kobweb create site

You'll be asked a few questions required for setting up your project. When prompted for a folder name, it will create the folder within your current directory, so you don't have to worry about it overwriting any files.

When finished, you'll have a basic project with three pages - a home page, an about page, and a markdown page - and some components (which are collections of reusable, composable pieces). Your own directory structure should look something like:

my-project
โ””โ”€โ”€ src
    โ””โ”€โ”€ jsMain
        โ”œโ”€โ”€ kotlin
        โ”‚   โ””โ”€โ”€ org
        โ”‚       โ””โ”€โ”€ example
        โ”‚           โ””โ”€โ”€ myproject
        โ”‚               โ”œโ”€โ”€ components
        โ”‚               โ”‚  โ”œโ”€โ”€ layouts
        โ”‚               โ”‚  โ”‚  โ””โ”€โ”€ PageLayout.kt
        โ”‚               โ”‚  โ”œโ”€โ”€ sections
        โ”‚               โ”‚  โ”‚  โ””โ”€โ”€ NavHeader.kt
        โ”‚               โ”‚  โ””โ”€โ”€ widgets
        โ”‚               โ”‚     โ””โ”€โ”€ GoHomeLink.kt
        โ”‚               โ”œโ”€โ”€ MyApp.kt
        โ”‚               โ””โ”€โ”€ pages
        โ”‚                   โ”œโ”€โ”€ About.kt
        โ”‚                   โ””โ”€โ”€ Index.kt
        โ””โ”€โ”€ resources
            โ””โ”€โ”€ markdown
                โ””โ”€โ”€ Markdown.md

Note that there's no index.html or routing logic anywhere! We generate that for you automatically when you run Kobweb. Which brings us to the next section...

Run your Kobweb site

$ cd /path/to/projects/root/your-project
$ kobweb run

This command spins up a webserver 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.

Examples

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 ...`

โ€ข examples/todo: An example TODO app, showcasing client / server interactions
โ€ข site: A template for a minimal site that demonstrates the basic features of Kobweb

For example, kobweb create examples/todo will instantiate a TODO app locally.

Basics

Kobweb, at its core, is a handful of classes responsible for trimming away much of the boilerplate around building a Web Compose app, such as routing and setting up default CSS styles. It exposes a handful of annotations and utility methods which your app can use to communicate intent with the framework. These annotations work in conjunction with our Gradle plugin (com.varabyte.kobweb.application) that handles code and resource generation for you.

Kobweb is also a CLI binary of the same name which provides commands to handle the parts of building a Web Compose app that are less glamorous. We want to get that stuff out of the way, so you can enjoy focusing on the more interesting work!

Create a page

Creating a page is easy! It's just a normal @Composable method. To upgrade your composable to a page, all you need to do is:

  1. Define your composable in a file somewhere under the pages package in your jsMain source directory.
  2. Annotate it with @Page

Just from that, Kobweb will create a site entry for you automatically.

For example, if I create the following file:

// jsMain/kotlin/com/example/mysite/pages/admin/Settings.kt

@Page
@Composable
fun SettingsPage() {
    /* ... */
}

this will create a page that I can then visit by going to mysite.com/admin/settings.

By default, the path comes from the file name, although there will be ways to override this behavior on a case-by-case basis (* coming soon).

The file name Index.kt is special. If a page is defined inside such a file, it will be treated as the default page under that URL. For example, a page defined in .../pages/admin/Index.kt will be visited if the user visits mysite.com/admin.

Silk

Silk is a UI layer included with Kobweb and built upon Web Compose. (To learn more about Web Compose, please visit the official tutorials).

While Web Compose requires you to understand underlying html / css concepts, Silk attempts to abstract a lot of that away, providing an API more akin to what you might experience developing a Compose app on Android or Desktop. Less "div, span, flexbox, attrs, styles, classes" and more "Rows, Columns, Boxes, and Modifiers".

We consider Silk a pretty important part of the Kobweb experience, but it's worth pointing out that it's designed as an optional component. You can absolutely use Kobweb without Silk. You can also interleave Silk and Web Compose without issue (as Silk, itself, is just composing Web Compose methods).

What about Multiplatform Widgets?

Jetbrains is working on an experimental project called "multiplatform widgets" which is supposed to bring the Desktop / Android API to the web. And it may seem like the Kobweb + Silk approach is competing with it.

However, I've found there is a fundamental distance between Desktop / Android Compose and Web Compose. Specifically, Desktop / Android targets render to their own surface, while Web modifies a parallel html / css DOM tree and leaves it to do the final rendering.

This has major implications on how similar the two APIs can get. For example, in Desktop / Android, the order you apply modifiers matters, while in Web, this action simply sets html style properties under the hood, where order does not matter.

One approach would be to own the entire rendering pipeline, ditching html / css entirely and targeting a full page canvas or something. However, this limits the ability for robots to crawl and index your site, which is a major drawback. It also means that debugging in a browser would be a rough experience, as the browser's developer tools would be limited in the insights it could provide for your site. It would also prevent a developer from making use of the rich ecosystem of Javascript libraries out there that modify the DOM tree themselves.

For now, I am making a bet that the best way forward is to embrace the web, sticking to html / css, but providing a rich UI library of widgets that hopefully makes it relatively rare for the developer to worry about it. For example, flexbox is a very powerful component, but you'll find it's much easier to compose Rows and Columns together than trying to remember if you should be justifying your items or aligning your content, even if Rows and Columns are just creating the correct html / css for you behind the scenes anyways.

Components: Layouts, Sections, and Widgets

Outside of pages, it is common to create reusable composable parts. While Kobweb doesn't enforce any particular rule here, we recommend a convention which, if followed, may make it easier to allow new readers of your codebase to get around.

First, as a sibling to pages, create a folder called components. Within it, add:

  • layouts - High-level composables that provide entire page layouts. Most (all?) of your @Page pages will start by calling a page layout function first. You may only have a single layout for your entire site.
  • sections - Medium-level composables that represent compound areas inside your pages, organizing a collection of many children composables. If you have multiple layouts, it's likely sections would be shared across them. For example, nav headers and footers are great candidates for this subfolder.
  • widgets - Low-level composables. Focused UI pieces that you may want to re-use all around your site. For example, a stylized visitor counter would be a good candidate for this subfolder.

Define API routes

You can define and annotate methods which will generate server endpoints you can interact with. To add one:

  1. Define your method (optionally suspendable) in a file somewhere under the api package your jvmMain source directory.
  2. The method should take exactly one argument, an ApiContext.
  3. Annotate it with @Api

For example, here's a simple method that echoes back an argument passed into it:

// jvmMain/kotlin/com/example/mysite/api/Echo.kt

@Api
fun echo(ctx: ApiContext) {
    // ctx.req is for the incoming request, ctx.res for responding back to the client

    // Queries are parsed from the URL, e.g. here "/echo?message=..."
    val msg = ctx.req.query["message"] ?: ""
    ctx.res.setBodyText(msg)
  
    // You could also do something like: `ctx.res.body = ctx.req.body`
    // but using query parameters makes for an easier demo
}

After running your project, you can test the endpoint by visiting mysite.com/api/echo?message=hello

You can also trigger the endpoint in your frontend code by using the extension api property added to the kotlinx.browser.window class:

@Page
@Composable
fun ApiDemoPage() {
  val coroutineScope = rememberCoroutineScope()

  Button(onClick = {
    coroutineScope.launch {
      println("Echoed: " + window.api.get("echo?message=hello")!!.decodeToString())
    }
  })
}

All the HTTP methods are supported (post, put, etc.). Of course, you can also use window.fetch(...) directly.

Markdown

If you create a markdown file under the jsMain/resources/markdown folder, a corresponding page will be created for you at build time, using the filename as its path.

For example, if I create the following file:

// jsMain/resources/markdown/docs/tutorial/Kobweb.kt

# Kobweb Tutorial

...

this will create a page that I can then visit by going to mysite.com/docs/tutorial/kobweb

The power of Kotlin + Web Compose is composable interactive components though, not static text! That's why Kobweb Markdown support enables extensions to allow this out of the box.

Front Matter

Front Matter is metadata that you can specify at the beginning of your document, like so:

---
title: Tutorial
author: bitspittle
---

and these key / value pairs can be referenced in your Kotlin @Composable code (* coming soon).

However, there's a special value which, if set, will be used to render a root @Composable that wraps the code your markdown file would otherwise create. This is useful for specifying a layout for example:

---
root: .components.layout.DocsLayout
---

# Kobweb Tutorial

This will generate code like the following:

import com.mysite.components.layout.DocsLayout

@Composable
@Page
fun KobwebPage() {
    DocsLayout {
        H1 {
            Text("Kobweb Tutorial")
        }
    }
}

Kobweb Call

A markdown extension built just for Kobweb, you can surround a path to a @Composable method with double-curly braces to call it:

# Kobweb Tutorial

...

{{ .components.widgets.VisitorCounter }}

which will generate code for you like the following:

import com.mysite.components.widgets.VisitorCounter

@Composable
@Page
fun KobwebPage() {
    /* ... */
    VisitorCounter()
}

In this way, you can write pages that are mostly static text punctuated with beautiful, interactive components. This could be a great approach for people who want to write and host their own blogs, for example.

Can We Kobweb Yet

Current state: Functional but early

Kobweb has some pretty big pieces working already. 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. And while it's not quite server-side rendering, you can export static pages which will get hydrated on load.

However, there's still a lot to do. The API surface is a bit lean in some areas right now, especially around Silk UI components, plus filling in holes in the APIs that interact with Web Compose. There are probably quite a few sharp corners. And while the code is decently documented, higher level documentation is missing. Windows support needs love.

So, should you use Kobweb at this point? If you are...

  • a Kotlin tinkerer who is excited to play around with new tech and isn't afraid of creating toy projects atop APIs which may shift underfoot:
    • YES!!! Please see the connecting with us โ–ผ section below, we'd definitely love to hear from you. Now's a great time if you'd 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:
    • Maybe, but now is probably a bit too early.
  • someone who already has an existing project in progress and wants to integrate Kobweb into it:
    • No
  • a company:
    • NOOOOOO (someday, we hope, but not yet)

Templates

Kobweb provides its templates in a separate git repository, which is referenced within this project as a submodule for convenience. To pull down everything, run:

/path/to/src/root
$ git clone --recurse-submodules https://github.com/varabyte/kobweb

# or, if you've already previously cloned kobweb...
/path/to/src/root/kobweb
$ git submodule update --init

Known Issues

  • kobweb run sometimes gets stuck when Gradle (running behind it) gets stuck.
    • Quit kobweb, run ./gradlew --stop, and then try again
    • Run ./gradlew kobwebGen or ./gradlew kobwebStart with various Gradle debug options to see what's going on under the hood (e.g. ./gradlew kobwebStart --stacktrace)

Solutions didn't work? Or you're encountering issues not listed here? Please consider leaving feedback โ–ผ!

Connecting with us

Filing issues and leaving feedback

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!

Comments
  • Find better ways to distribute the kobweb binary

    Find better ways to distribute the kobweb binary

    ~~How to get onto package managers in Linux or Homebrew in Mac? What's the equivalent for Windows?~~

    Support and/or intentionally reject the following package managers:

    • [x] homebrew
    • [x] scoop
    • [X] ~~chocolatey~~ (1)
    • [X] ~~gofish~~ (2)
    • [X] ~~macports~~ (2)
    • [X] ~~snapcraft~~ (3)
    • [X] ~~spec~~ (4)
    • [X] ~~docker~~ (5)
    • [x] sdkman
    • ~~strikethrough~~ means not now, we can close this bug without them, but I'd always be open to supporting them later
    1. The process for Chocolatey feels a bit heavy handed for now. I can't simply self-host, instead I have to go through a whole process with their team, getting a review, etc. Plus, I found it hard to navigate the instructions. I'll leave this off for now, since Scoop is working, but can revisit this again in the future if Kobweb actually becomes regularly used.
    2. Requires setting up PRs on specific repositories, not low hanging fruit
    3. Strict mode is killing me. Snap sets up a whole environment just for Kobweb, making the download 100MB, and yet is getting killed by Snap and snappy-debug isn't really giving me useful information.
    4. Not too familiar with Fedora or spec, but I'm considered adding support for it is diminishing returns and therefore isn't my highest priority.
    5. A docker image is probably overkill. Users will be expected to have java on their machine anyway to compile Kobweb (Kotlin) projects, so I don't need to support an image where Java is included.
    process 
    opened by bitspittle 22
  • "kobweb export --layout static" doesn't generate any new files

    I followed the directions for setting up a static page for github pages here. https://bitspittle.dev/blog/2022/staticdeploy#kobweb-to-the-rescue

    I was able to generate the initial files after trying the instructions maybe 5 or so times. I then created a new page that works when I run kobweb run but when I try and generate the files with kobweb export --layout static no new files get made in the /docs folder.

    This is happening with Kobweb CLI 0.9.7 on Mac

    bug 
    opened by blakelee 9
  • Multiple refreshes, then blank page - no 404

    Multiple refreshes, then blank page - no 404

    When loading a url such as http://localhost:8080/test-refresh - which does not exist in a given project - the page continuously refreshes for some time, after which a blank page appears.

    Shouldn't this instead lead to a 404 status page immediately?

    bug 
    opened by PXNX 8
  • Kobweb components are recomposing too much

    Kobweb components are recomposing too much

    Thanks a ton to a user on my discord:

    Whenever you pass in a modifier directly to a composable, like
    ParentComposable(text: String) {
      ChildComposable(
        Modifier...
      )
    }
    
    I've noticed that everytime ParentComposable()  recomposes, ChildComposable() recomposes too, even if nothing changes about the Modifier being passed in. Is this intentional?
    Because on Android, ChildComposable() wouldn't recompose if the modifier didn't change.
    Similarly, if you do something using the attrs parameter like
    ParentComposable(text: String) {
      ChildComposable(
        attrs = {
          ...
        }
      )
    }
    
    ChildComposable() doesn't recompose if the attrs parameter doesn't change
    
    
    To avoid the unnecessary recomposition of ChildComposable(), I've found you need to do something like
    val modifier = remember { Modifier... }
    ParentComposable(text: String) {
      ChildComposable(
        modifier
      )
    }
    
    I did some more digging into this, and this seems to happen because your Modifier/ChainedModifier doesn't override hashCode(), which is what's used to check whether or not it should recompose
    
    bug 
    opened by bitspittle 7
  • Add `rememberBreakpoint` to Silk

    Add `rememberBreakpoint` to Silk

    This could be used to toggle code with logic, as an additional path besides component styling.

    val breakpoint = rememberBreakpoint()
    if (breakpoint >= Breakpoint.MD) {
       ... show this only on desktop ...
    }
    
    enhancement 
    opened by bitspittle 5
  • kobwebStart -t not available via run config

    kobwebStart -t not available via run config

    README describes invocation of dev server with live loading via kobweb cli, gradle cli and intellij run config. I couldn't get the run config to work, see youtrack issue.

    Is there an alternative way to get the live loading to work via run config?

    documentation external 
    opened by gabe97330 5
  • Investigate issues with M1 on Mac

    Investigate issues with M1 on Mac

    I've heard one report that Mac + M1 fails with an error like so:

    > Configure project :
    Kotlin Multiplatform Projects are an Alpha feature. See: https://kotlinlang.org/docs/reference/evolution/components-stability.html. To hide this message, add 'kotlin.mpp.stability.nowarn=true' to the Gradle properties.
    
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Could not determine the dependencies of task ':kotlinNodeJsSetup'.
    > Could not resolve all files for configuration ':detachedConfiguration1'.
       > Could not find org.nodejs:node:14.17.0.
         Searched in the following locations:
           - https://repo.maven.apache.org/maven2/org/nodejs/node/14.17.0/node-14.17.0.pom
           - https://maven.pkg.jetbrains.space/public/p/compose/dev/org/nodejs/node/14.17.0/node-14.17.0.pom
           - https://dl.google.com/dl/android/maven2/org/nodejs/node/14.17.0/node-14.17.0.pom
           - https://us-central1-maven.pkg.dev/varabyte-repos/public/org/nodejs/node/14.17.0/node-14.17.0.pom
           - https://nodejs.org/dist/v14.17.0/node-v14.17.0-darwin-arm64.tar.gz
         Required by:
             project :
    
    * Try:
    > Run with --info or --debug option to get more log output.
    > Run with --scan to get full insights.
    
    * Exception is:
    org.gradle.api.internal.tasks.TaskDependencyResolveException: Could not determine the dependencies of task ':kotlinNodeJsSetup'.
    	at org.gradle.api.internal.tasks.CachingTaskDependencyResolveContext.getDependencies(CachingTaskDependencyResolveContext.java:71)
    	at org.gradle.execution.plan.TaskDependencyResolver.resolveDependenciesFor(TaskDependencyResolver.java:49)
    	at org.gradle.execution.plan.LocalTaskNode.getDependencies(LocalTaskNode.java:168)
    	at org.gradle.execution.plan.LocalTaskNode.resolveDependencies(LocalTaskNode.java:133)
    	at org.gradle.execution.plan.DefaultExecutionPlan.doAddNodes(DefaultExecutionPlan.java:202)
    ...
    
    Caused by: org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration$ArtifactResolveException: Could not resolve all files for configuration ':detachedConfiguration1'.
    	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.rethrowFailure(DefaultConfiguration.java:1503)
    	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.access$3700(DefaultConfiguration.java:159)
    	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$DefaultResolutionHost.rethrowFailure(DefaultConfiguration.java:2139)
    	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.visitContents(DefaultConfiguration.java:1475)
    ...
    
    Caused by: org.gradle.internal.resolve.ModuleVersionNotFoundException: Could not find org.nodejs:node:14.17.0.
    Searched in the following locations:
      - https://repo.maven.apache.org/maven2/org/nodejs/node/14.17.0/node-14.17.0.pom
      - https://maven.pkg.jetbrains.space/public/p/compose/dev/org/nodejs/node/14.17.0/node-14.17.0.pom
      - https://dl.google.com/dl/android/maven2/org/nodejs/node/14.17.0/node-14.17.0.pom
      - https://us-central1-maven.pkg.dev/varabyte-repos/public/org/nodejs/node/14.17.0/node-14.17.0.pom
      - https://nodejs.org/dist/v14.17.0/node-v14.17.0-darwin-arm64.tar.gz
    Required by:
        project :
    
    
    
    * Get more help at https://help.gradle.org
    Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
    
    
    BUILD FAILED in 42s
    You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
    
    See https://docs.gradle.org/7.4/userguide/command_line_interface.html#sec:command_line_warnings
    
    Exiting continuous build as no executed tasks declared file system inputs.
    
    Starting a Kobweb server (development).
    

    Full pastebin attached: Kobweb startup failure.txt

    enhancement 
    opened by bitspittle 4
  • Server occasionally won't shut down?

    Server occasionally won't shut down?

    Not sure what's going on, but when you press Q to quit in the console, occasionally it just waits forever. You have to kill the process manually and CTRL-C kobweb. This is a horrible experience.

    It's possible it has something to do with a server freaking out after a bunch of live reloads. I mean, maybe it's just a guess, but I should look into my /api/kobweb-status event stream logic in Routing.kt, but no guarantees it isn't some other issue.

    It's probably easy to fix if I can find a way to regularly reproduce but I don't have any steps at the moment.

    bug 
    opened by bitspittle 4
  • Add support for clamping font sizes

    Add support for clamping font sizes

    A suggestion from the Discord!

    What about a clamp() function for font-sizes. I think it would be really useful ๐Ÿ™‚ With that you could define: min, max and normal font size. So for example: --fs-xl: clamp(3.5rem, 12vw + 1rem, 12rem)

    Would mean that the font is 12vw + 1rem big, but can shrink to min. 3.5rem and grow to a maximum of 12rem. That would make it a lot easier to create websites with Kobweb (without using so many Breakpoints for fonts) ๐Ÿ™‚

    I'm not a big CSS or HTML expert so Idk if that is a common thing but I think it's awesome... ๐Ÿคท Maybe let me know what you guys think about an implementation of clamp().

    ps: The possibility to set a .fontSize(min, normal, max) - just like in the clamp() func - would do it too I think ^^

    I wrote some code as a workaround for those of you that may also need it ^^. Should work perfectly.

    data class Clamp(val min: CSSNumeric, val normal: CSSNumeric, val max: CSSNumeric) {
        override fun toString(): String = "clamp(${this.min}, ${this.normal}, ${this.max})"
    }
    
    fun Modifier.fontSize(clamp: Clamp) = styleModifier { fontSize(clamp) }
    fun StyleScope.fontSize(clamp: Clamp) = property("font-size", clamp.toString())
    }
    

    The "Clamp" data class is optional. It can also be replaced with just three simple parameters (min, normal, max) in the Modifier.fontSize() and StyleScope.fontSize() functions.

    See also: https://developer.mozilla.org/en-US/docs/Web/CSS/clamp

    enhancement maybe 
    opened by bitspittle 3
  • Allow `kobweb run` to work in submodules of Gradle projects

    Allow `kobweb run` to work in submodules of Gradle projects

    Given a project like:

    root/
      gradlew
      a/
      b/
      c/d/e/kobweb-site/
    

    this should work:

    cd root/c/d/e/kobweb-site
    kobweb run
    

    Right now it doesn't because it's looking for gradlew in the current directory. Instead, we should crawl up to see if we can find gradlew in a parent directory instead of giving up immediately.

    enhancement 
    opened by bitspittle 3
  • Add support for custom slugs inside @Page annotations

    Add support for custom slugs inside @Page annotations

    I need to think through this feature. Do we even want to allow it? Will it allow us to specify dynamic routes, e.g. https://nextjs.org/docs/routing/dynamic-routes ?

    If we do support it, we need to update the Kobweb gradle plugin to detect the slug name inside the annotation and use it instead of the file name.

    enhancement 
    opened by bitspittle 3
  • Review JavaScript API css classes

    Review JavaScript API css classes

    For example: https://developer.mozilla.org/en-US/docs/Web/CSS/visibility, we are missing a few global values in our Visibility class.

    We should review all of the classes Kobweb provides and compare them exhaustively with the javascript APIs.

    enhancement 
    opened by bitspittle 0
  • Create defaults for a nice circular button

    Create defaults for a nice circular button

    Probably a CircleButton variant? Alternately, a CircleButton composable, which may be better if we start adding in size parameters to our widgets? (Since otherwise it might be hard to respond to different sizes)

    Currently, if you clip with a Circle and set padding to 0.px, you get something where the button edges show slightly:

    Test image

    Anyway, if we support something official, then users won't have to worry about this.

    I'm leaning towards making a CircleButton composable; it is readable and a bit more flexible for future changes.

    enhancement 
    opened by bitspittle 2
  • Sometimes it seems like a kobweb server starts after one stops (on  Windows?)

    Sometimes it seems like a kobweb server starts after one stops (on Windows?)

    Example repro steps:

    1. cd examples/jb/counter
    2. ./gradlew clean
    3. ./gradlew --stop
    4. kobweb run -> Server started PID=13860
    5. q -> server stopped PID=13860
    6. kobweb stop -> Did not detect running server.
    7. ./gradlew clean -> Task failed / java.io.IOException: Unable to delete directory '...\kobweb-templates\examples\jb\counter\build' / Failed to delete some children. This might happen because a process has files open or has its working directory set in the target directory.
    7.5 (sometimes). kobweb stop -> Did not detect running server.
    8. kobweb stop -> Server stopped PID=20940
    
    bug windows 
    opened by bitspittle 3
  • Make the default site template look nicer

    Make the default site template look nicer

    The current one looks very programmer-artsy.

    We don't need anything too complicated, but maybe something that looks a little more clean, akin to what the default nextjs template looks like.

    enhancement good first issue 
    opened by bitspittle 0
  • Support ligature fallback in Material Design Icon support

    Support ligature fallback in Material Design Icon support

    See also: https://developers.google.com/fonts/docs/material_icons#using_the_icons_in_html

    Relevant code can be found in kobweb-silk-icons-mdi/build.gradle.kts

    enhancement 
    opened by bitspittle 0
  • Add support for sizes and color schemes in Buttons

    Add support for sizes and color schemes in Buttons

    So something like

    Button(size = Sizes.Lg, scheme = ColorSchemes.Blue) {
       ...
    }
    

    (Also audit other widgets and make sure they support these features too)

    enhancement 
    opened by bitspittle 0
Releases(v0.11.5)
  • v0.11.5(Jan 1, 2023)

    Silk

    • New widgets!
      • Overlay: Render a full screen dark grey background (optionally, override the color by passing in a modifier). Any child of the overlay will render on top of it.
        • Useful for creating your own modal dialog class, for example.
      • Popup: Render content next to some other element when that element is mouse-overed.
      • Tooltip: Like Popup, but wraps content in a black chat bubble. Well suited for text blurbs.
    • Silk now supports deferred rendering via the deferRender utility method, which breaks normal composition flow and renders some target Composable after everything else is rendered. This lets you accomplish rendering elements globally on top of other elements without resorting to zIndex tricks.
      • Overlays and Popups use deferred rendering under the hood.
    • ComponentStyle css selector builders now support using functional psuedo-classes
    • Bumped SimpleGrid max size from 4 to 5.

    Frontend

    Gradle

    • [Multimodule] Fixed an issue where public resources in dependent projects weren't getting copied into the final site's resources.
    Source code(tar.gz)
    Source code(zip)
  • v0.11.4(Dec 17, 2022)

    This release doesn't add any new features on top of Kobweb 0.11.3, but it now compiles against Compose for Web 1.2.2. Once you upgrade to this version, you need to also make sure your project uses Compose for Web 1.2.2 itself.

    Compose for Web 1.2.2 fixed a major performance regression that caused composables to rerender unnecessarily if (at least) one of their parameters was of a type that was defined in a compose library.

    See the Compose for Web 1.2.2 release notes for more information.

    Source code(tar.gz)
    Source code(zip)
  • v0.11.3(Dec 17, 2022)

    Frontend

    • Added input event modifiers for drag/drop events

    Silk

    • :tada: Support added for Google Material Design icons!
    • [Potentially backwards incompatible] Changed Row behavior to not wrap by default.
      • This brings its behavior closer in line to what Jetpack Compose does, as rows don't wrap there.
      • You shouldn't notice a difference unless you had a row that wrapped across multiple lines.
      • If your row broke visually, add .flexWrap(FlexWrap.Wrap) to its Modifier
    • [Potentially backwards incompatible] Tweak default Button styles
      • Before, button defaults didn't include any padding, leaving it up to users to set it. However, this behavior means when you create default buttons, they don't look good and require additional styling.
      • Also changed the cursor icon to a no-op pointer if the button was disabled.
      • If your button broke visually, add .padding(0.px) to its Modifier

    Gradle

    • Added Kobweb config API support for allowing custom target names (e.g. the "js" and "jvm" prefixes that show up in associated Gradle tasks)
    • You can now start a Kobweb server using the Gradle kobwebStart task from any folder.
      • Note: The kobweb binary, which delegates to Gradle behind the scenes, is not changed, and it still requires being run in the root of a Kobweb application folder.
    • Fixed issue when publishing Kobweb artifacts, so they all include sources and javadoc jars now.

    :bow: HUGE THANKS to...

    • @jassycliq for researching and then implementing Google Material Design icons.
    • @DVDAndroid for the various Gradle fixes.
    Source code(tar.gz)
    Source code(zip)
  • v0.11.2(Dec 11, 2022)

    A small update which includes a fix for an unfortunately long-standing export bug on Windows.

    Silk

    • Update the Silk ref methods to allow nullable keys:
         val someFeatureProperty: Any? = /* ... */
         SomeWidget(
            ref = ref(someFeatureProperty) { /* ... rerun if someFeatureProperty changes */ }
         )
      

    Gradle plugins

    • Fixed an issue where kobweb export wasn't working right on Windows due to path issues. (Note: The kobweb export --layout static variant worked fine)

    • If a server fails to run when you trigger kobweb run, the stderr of the process is now captured and shown to the user.

    Templates

    • Updated all templates to use the Silk way of registering global styles, via Modifier and not StyleSheet approaches.
      • Both are honestly fine, but being able to consistently use Modifier styles everywhere makes the project feel a bit more cohesive.
    Source code(tar.gz)
    Source code(zip)
  • v0.11.1(Nov 29, 2022)

    A fairly minor release -- just some misc. changes after the major v0.11.0 update landed.

    I also updated the responsive example ($ kobweb create examples/responsive) to showcase a responsive side menu which gets hidden behind a button on mobile.

    Frontend

    • New modifier for the CSS float property
    • New modifier for the CSS visibility property

    Gradle

    • New configAsKobweb[Application|Library] utility methods, which can help remove boilerplate from your Kobweb project's gradle scripts.
      • Used in a kotlin block to set up js and jvm configuration values that Kobweb expects. Looks like:
      kotlin {
          configAsKobwebApplication(includeServer = true)
          commonMain { ... }
          jsMain { ... }
          jvmMain { ... } // <-- Excluded if includeServer = false
      } 
      
      • All templates have been updated to use this approach, so you can refer to them if you want to migrate your own build scripts over.
    • New notifyKobwebAbout[Frontend|Backend]CodeGeneratingTask utility methods, useful if you have a task in your own project that generates some code as a side effect that Kobweb should pick up on.
      • This used to be something you could accomplish by explicitly inserting your own task in front of :kobwebGenFrontend and :kobwebGenBackend, but that was fragile as there aren't any guarantees that Kobweb Gradle plugins won't be updated in the future so this assumption is no longer true.
    Source code(tar.gz)
    Source code(zip)
  • v0.11.0(Nov 24, 2022)

    This release introduces multimodule support.

    This means you can now break your monolithic Kobweb project up into multiple pieces. See the new README section as well as the multimodule example for more details.

    Multimodule support is accomplished with the introduction of the Kobweb library gradle plugin (and a massive behind the scenes refactoring of the application plugin to pull out the shared parts). If you want to create a library module instead of a site app module (perhaps for organization purposes, or to create a widget library that can be published and shared), you can now apply the com.varabyte.kobweb.library plugin in that module's bulid script.


    :warning: In theory, you can just apply this version and things will just work. However, you might run into some compile errors with your build.gradle.kts file after this change. To fix them, make sure you've migrated any of the following references:

    • kobweb.appGlobals is now kobweb.app.globals
    • kobweb.index is now kobweb.app.index
    • kobwebx.markdown is now just kobweb.markdown (the kobwebx block has been removed)
    Source code(tar.gz)
    Source code(zip)
  • cli-v0.9.10(Nov 24, 2022)

    This fix includes some minor Kobweb CLI tweaks, particularly in preparation for multimodule support, which is going to land very soon.

    (Multimodule changes the assumption that Kobweb projects are always grounded to the root directory. Some Kobweb logic needed to be updated to handle it. Older binaries will still work for all previous projects but will not detect the multimodule sample)

    Changes

    • Latest kobweb binary will be able to detect the multimodule sample (when it is eventually released)
    • Improved the logic around surfacing exceptions
      • Before, exceptions directly from Gradle would be missed, requiring the user to have to scroll all the way up past the gigantic callstack. Now, they are included in the list of errors and warnings that Kobweb shows.
    • Other misc. background changes that simplify the code a bit but won't be visible to the end user.
    Source code(tar.gz)
    Source code(zip)
    kobweb-0.9.10.tar(7.01 MB)
    kobweb-0.9.10.zip(6.33 MB)
  • v0.10.6(Nov 22, 2022)

    Multimodule support is planned to release a day or two after this release. These are the miscellaneous bug fixes I wanted to get in first before that change, as that one will cause the "major" version to go up (from 0.10.x to 0.11.x)

    Core

    • Added support for SpaceAround, SpaceBetween, and SpaceEvenly Arrangements.
    • Added special Arrangement.FromStyle and Alignment.FromStyle values, useful for cases where you know what you're doing and plan to specify the flex style yourself using CSS modifiers.
    • Added disabled modifier
    • Added flexBasis modifier
    • Fixed bug with Color.rgba method not working.
    • Deprecated asAttributesBuilder, now toAttrs for conciseness / consistency with other APIs.
    • Fixed an IndexOutOfBounds exception caused by query parameters that were just keys without values
      • For example, https://site.com/hello?test would crash when trying to parse the test parameter

    Silk

    • Added support for disabling Button widgets.
    • Added replaceComponentVariant methods (before, we only had replaceComponentStyle methods).
      • These can be used to override some variant provided by Silk.
    • Fixed a bug where the extraModifier parameter didn't work when defining variants.

    Markdown

    • Improved generated markdown code if no Composable root was explicitly specified.
      • Before, it dropped all text into a Box, which had the effect of stacking each line on top of the other.

    Gradle

    • Tweaked Kobweb application plugin error logging so that they are highlighted better by the Kobweb CLI.
    • Fixed some Kobweb tasks that weren't being shown in the "kobweb" Gradle category.
    Source code(tar.gz)
    Source code(zip)
  • v0.10.5(Nov 12, 2022)

    Just a minor release, with some simple bugs I fixed while most of my attention is on a much larger Gradle plugin refactoring that will be landing soon (TM).

    Frontend

    • Added Modifier.borderStyle modifier.
    • Modifier.content will now auto-surround your string with quotes if they are missing.
      • So if you forget to write Modifier.content("\" โ€ข \"") Kobweb has your back my friend.
    • The Kobweb Color class now inherits from the CSSColorValue interface.
      • This means it now plays nice with all existing CfW color APIs, no toCssColor necessary.
      • Removed all modifiers that took Color as an argument; instead, users should use the CSSColorValue ones.
    • Added Silk-aware main.kt code generation for apps using Silk that don't use the @App annotation.
    Source code(tar.gz)
    Source code(zip)
  • v0.10.4(Nov 7, 2022)

  • v0.10.3(Nov 7, 2022)

    Misc. fixes, which I'm snapshotting into a release so that I can follow up shortly with another release that depends on Compose v1.2.1, which was just released recently.

    Frontend

    • Refactor alignment modifiers
      • Introduce Kobweb's version of AlignItems, JustifyItems, etc. classes, since the Compose for Web versions don't handle baseline and overflow settings.
      • Add missing modifier for placeItems
    • Rename kobweb.core.navigation.Link to kobweb.core.navigation.Anchor, to avoid confusion caused with Silk's own kobweb.silk.navigation.Link widget.
      • Technically, an Anchor is a more robust A tag, while a Link is a specific anchor that renders the underlined link text we all know and love when using the web.
      • In most cases, users will want to use Link and not Anchor.
    • (Possible backwards incompatibility) Refactor the elementScope parameter in all Silk widgets, changing them into a version that takes a ref listener (with a callback that receives an ElementRefScope)
      • This makes it safer to get access to the underlying raw element for a widget without exposing an unnecessary composable block.
      • Before, to get a raw element that backs a widget:
        Widget(elementScope = { 
           DisposableSideEffect {
              // use scopeElement here
              onDispose {}
           })
        

        After:

        Widget(ref = ref { element -> ... })
        // or, if you need dispose handling:
        // Widget(ref = disposableRef { element -> ...; onDispose { ... }})
        
    Source code(tar.gz)
    Source code(zip)
  • v0.10.2(Oct 30, 2022)

    I'm planning to experiment with migrating the Kobweb Gradle plugin over to KSP shortly, so right before getting lost in that seems like a good time to slice off a release.

    Frontend

    • Fixed a bug with the various transition modifiers not working when specifying multiple parameters
      • For example, Modifier.transitionProperty("color", "font-size").transitionDuration(100.ms, 300.ms) would silently break before.
    • Add a slew of transform modifiers
      • For example, Modifier.rotate, Modifier.scale, etc., with various input parameter configurations.
    • Add boxSizing and boxDecorationBreak box modifiers.
      • Potential backwards incompatible change The old Modifier.boxSizing(String) API has been removed.
        • Instead, use the one that takes in multiple arguments instead.
        • You can also use styleModifier { boxSizing(String) } in a pinch.

    Markdown

    • There are no longer any unsupported markdown features. Everything should work now. Specifically...
      • <html> blocks now generate the correct Compose code for creating simple elements.
      • > can now be used to create block quotes (although sites must still define their own blockquote style using css rules; the default is very bland).
      • Link referencing (read more about what this is here) now works.
    Source code(tar.gz)
    Source code(zip)
  • v0.10.1(Oct 22, 2022)

    This release is essentially the same as v0.10.0, except that, when you run an export, it now produces final output that has dead code elimination applied to it. You may expect to see anywhere from a 50-75% reduction in your final site's javascript file.


    Note that if you have an existing project, you must do the following steps to take advantage of this:

    1. Open your .kobweb/conf.yaml file
    2. Under the prod: section, add a script: field set to "build/distributions/(yourproject.js)"

    For example, if your project was called example, then your final conf file might look like:

    # example/.kobweb/conf.yaml
    
    site:
      title: "Example Project"
    
    server:
      files:
        dev:
          contentRoot: "build/processedResources/js/main/public"
          script: "build/js/packages/helloworld/kotlin/example.js"
        prod:
          script: "build/distributions/example.js" # <--- This line is new!
          siteRoot: ".kobweb/site"
    
      port: 8080
    

    If you create a new project, e.g. kobweb create site, then this will already be done for you.

    Source code(tar.gz)
    Source code(zip)
  • v0.10.0(Oct 15, 2022)

    :tada: Update Kobweb to compile against Compose for Web 1.2.0 :tada:

    Feature-wise, this release is identical to 0.9.15. However, it now depends on the latest stable Compose version. This also means you must use Kotlin 1.7.10 to build projects using this version of Kobweb.

    Source code(tar.gz)
    Source code(zip)
  • v0.9.15(Oct 15, 2022)

    Frontend

    • Fixed ComponentVariant always causing methods to recompose when passed in as an argument to one
    • Added a handful of missing Modifier.background methods, e.g. Modifier.backgroundImage

    Markdown

    • Fix issues with nested Markdown files not exporting correctly on Windows
    • Fix issue with dollar signs in Markdown generating Kotlin code that didn't compile
    Source code(tar.gz)
    Source code(zip)
  • v0.9.14(Sep 29, 2022)

    Frontend

    • Fixed unnecessary recompositions by adding equals and hashcode logic to Kobweb Modifier implementations
    • Added an additional, more idiomatic Kotlin API for Modifier.boxShadow

    Silk

    • Re-added Text and TextStyle back in but with @Deprecation annotations, after previously deleting them in 0.9.13. This means if projects upgrade from v0.9.12 (or earlier) to v0.9.14 (or later), they'll get helpful warnings instead of hard errors.
      • All Kobweb Text references should be renamed to SpanText. This was done in v0.9.13 because Text kept running against the very common Text function in the Compose Web API.

    Markdown

    • Fixed a bug with the Markdown plugin on Windows (caused by platform dependent slash logic), where before it didn't generate export paths correctly for nested markdown files.
      • e.g. src\jsMain\resources\markdown\a\b\c\test.md will now export to a\b\c\test.html, not test.html
      • Linux and Mac were fine.
    Source code(tar.gz)
    Source code(zip)
  • v0.9.13(Sep 5, 2022)

    Frontend

    • Backwards Incompatible Migrated Kobweb's Text to SpanText
      • Previously, Kobweb's Text tried to be smart and only wrapped its text in a span if a Modifier was passed in, but this was really subtle, and probably surprising, behavior. By renaming it, we now avoid a common import overlap between Kotlin's Text and Kobweb's version. Additionally, the name makes it clearer that this is text wrapped in a <span> block, and that that implementation will be consistent.
      • If you get a compile error around Text in your Kobweb project, you should be able to rename it to SpanText.
    • Updated Font Awesome support from v5 to v6
      • Potentially backwards incompatible Some font awesome icon names have changed as part of the migration. Please use their icon search to figure out the new names.
    • Added support for clamp, min, and max CSS functions whose output can be passed into relevant Modifier methods.
      • Thanks to @ayfri and @conradboehnke for their support on this feature!
    • The site's title is now automatically added to your app globals
      • So you can access it using AppGlobals["title"] in your code, instead of hard-coding it, in case things change down the line.
    • Fixed Modifier.role(...), which is now correctly implemented as an HTML attribute and not a style.
    • Fixed various copy/paste issues with CSS class instances (see commit cec1f7b for the changes)
    Source code(tar.gz)
    Source code(zip)
  • v0.9.12(Jun 18, 2022)

    This patch isn't large, but it brings in a few fixes as I return back to Kobweb after a break, having been sidelined by a different project for a while.

    There aren't any groundbreaking features introduced in this patch, but it does bring versions of Gradle, Compose, and Kotter dependencies up to date, as well as fixing a few issues reported by users.

    Frontend

    • Add default values to padding and margin for the versions that take topBottom and leftRight parameters.
    • Fixed buggy implementation of Modifier.thenIf extension methods
    • Fixed copy/paste error in API around JustifySelf/JustifyItem methods.
    • Update Gradle, Compose, and Kotter dependencies to latest versions.
      • Compatibility FYI This version of Kobweb now targets Compose 1.1.1, which, for web, has deprecated / renamed a fair bit of code. There's a chance you won't even notice. For example, all Kobweb template projects migrated without issue. However, moving your own project to Compose 1.1.1 may not be as trivial.
      • See also: COMPATIBILITY.md

    Gradle

    • Support custom names in source sets (thanks @DVDAndroid !)
    Source code(tar.gz)
    Source code(zip)
  • cli-v0.9.9(Apr 10, 2022)

    Contains only one change since v0.9.8, but it's kind of a big one :) This fixes issues of Kobweb hanging on Mac.

    • In 0.9.8, Kobweb switched from bundling a git library to using git installed on the user's machine. However, there was a bug in detecting if git was present on their machine which caused it to hang. This has been fixed by 1) detecting the errant case and 2) making the git detection logic way more forgiving.
    Source code(tar.gz)
    Source code(zip)
    kobweb-0.9.9.tar(6.93 MB)
    kobweb-0.9.9.zip(6.25 MB)
  • v0.9.11(Mar 26, 2022)

    A very small update, but pushed out since the Gradle export bug fix is important to people who change the route prefix.

    Frontend

    • Added versions of ComponentModifier / ComponentVariant methods thenIf and thenUnless that evaluate lazily
      • Before: Modifier.thenIf(condition, ConditionalModifier)
      • After: Modifier.thenIf(condition) { ConditionalModifier }
      • This additional version can be useful if you want to do something expensive when creating the modifier (or variant) that's supplied

    Gradle

    • Remove hardcoded reference to .kobweb/site in the Gradle plugin
      • This value should have been changed earlier to ready from the .kobweb/conf.yaml file after the route prefix feature was added
      • This should resolve issues some users would see when trying to re-export their site using a non-standard route prefix setting, e.g. targeting github pages
    Source code(tar.gz)
    Source code(zip)
  • cli-v0.9.8(Mar 26, 2022)

    While not an urgent change, a handful of simple QOL changes.

    Potentially breaking change for some users: kobweb no longer bundles its own git support but requires users have it installed on their system and in their path. This shrinks the binary by several megabytes, allows us to use shallow cloning for a much faster startup experience, and we can now offer to initialize a git project for the user when they run kobweb create

    • kobweb create now offers to auto-initialize git for your new project
    • kobweb create and kobweb list now use shallow clone, providing a much snappier response
    • kobweb run and kobweb export will now prevent a user from progressing if a server is already running
      • This is useful as otherwise the commands can interfere subtly with each other producing undefined behavior
    Source code(tar.gz)
    Source code(zip)
    kobweb-0.9.8.tar(6.92 MB)
    kobweb-0.9.8.zip(6.25 MB)
  • v0.9.10(Mar 5, 2022)

    An overall small update, but the Gradle bugfix around input / output files makes it worth releasing.

    Frontend

    • Fixed a bug with transparency not working when using Silk colors
      • That is, Color.rgba(255, 0, 0, 128) would just become red, not half-transparent red.
    • (Experimental) Added support for adding extra modifiers to a component style directly, as a way to accommodate attribute modifiers which are not otherwise allowed in that scope.
      • Before:
           val ButtonStyle = ComponentStyle("my-button") { ... }
           ...
        
           // Set tab index so this element can receive keyboard focus
           Button(ButtonStyle.toModifier().tabIndex(0)
        
      • After:
         val ButtonStyle = ComponentStyle("my-button") { ... }
            + Modifier.tabIndex(0) // Set tab index so this element can receive keyboard focus
        
         ...
         Button(ButtonStyle.toModifier())
        

    Gradle

    • Updated the "generate site" tasks so that files they output no longer makes those tasks think that they need to run again
    • Updated task listener logic so that the code is less fragile allowing the "Building..." indicator to show up more consistently
    Source code(tar.gz)
    Source code(zip)
  • v0.9.9(Feb 28, 2022)

    I'm now starting to use Kobweb more and more in personal projects. This update is a mish-mash of fixes I ran into needing while doing so.

    Note: (Breaking change) Some breakpoint code (such as rememberBreakpoint) has been refactored under a subpackage, which may cause compile errors in some projects (although it's not expected that this feature is heavily used at this time)

    Frontend

    • Fixed an issue with Boxes with more than one child not stacking as expected
    • Modifier extensions
      • Outline support
      • Transform support
      • placeContent support
    • Allow chaining ComponentVariants (meaning you can define a base style and apply multiple variants to it, not just a single one)
    • (Breaking change) Rename addBaseVariant to addVariantBase.
      • The original format was probably due to me being tired at the time. My hope is that most people aren't using this feature yet and many won't notice, but you can simply rename this if you're seeing errors here.
    • Add optional elementScope parameter to all Kobweb / Silk widgets.
      • This can allow a user to get access to the underlying element reference, which also allows using Compose for Web side effects
    • rememberPageContext crashes with a more descriptive error message now if used outside of a @Page context
    • Fixed the implementation of the various DisplayIf modifers (DisplayIfSm, DisplayIfMd, etc.), which was previously and unintentionally breaking elements that themselves needed to set the display style (like, uh, Rows, Columns, and Boxes.... whoooops....)
    • Add support for AppGlobals, a way to register global strings from your build.gradle file that can be seen from your Kobweb app
      • This is good for letting your build process set a version, for example.
    • Add helper thenIf and thenUnless helper extensions for Modifier and ComponentVariant classes, which makes it way easier to chain them conditionally
    • Remove the ugly and unecessary outline from showing up when setting keyboard focus on a Button widget

    Gradle

    • Refactored code allowing the Kobweb Applicaiton Plugin to no longer prevent configuration caching from working
    Source code(tar.gz)
    Source code(zip)
  • cli-v0.9.7(Feb 28, 2022)

    The major feature for this update is a better experience around displaying compile errors and warnings (vs. before where you had to scroll up past a huge callstack to see them). Local testing has shown this experience to be so good, it's worth upgrading for it.

    • Compile errors / warnings are now collected from Gradle output and shown in a scrollable list in a convenient location -- no more need to scroll up needing to dig through history to see what went wrong.
    • The "Output may seem to pause for a while..." message goes away once it's clear the download phase is complete.
    • Added an interactive mode for kobweb stop, which before would always switch to dumb mode
    • kobweb list now supports highlighting projects, useful for bringing attention to a few choices in an otherwise large list
      • Despite being implemented, I will be waiting a while before updating projects to use this, as this introduces a backwards incompatible change due to an unfortunate default serialization configuration.
    Source code(tar.gz)
    Source code(zip)
    kobweb-0.9.7.tar(9.79 MB)
    kobweb-0.9.7.zip(8.88 MB)
  • v0.9.8(Feb 21, 2022)

    This fix is a collection of a bunch of miscellaneous, minor improvements. Nothing particularly urgent.

    Frontend

    • A bunch of new Modifier extensions
      • object fit
      • vertical alignment
      • support for many grid properties
      • an optional parameter for distinguishing width / height styles vs. attributes
    • Added Color.toRgb so you can pull RGB colors out if you need to
      • This was useful in my openGL sample for setting the clear color
    • Now throw an exception if you define two component variants with the same name

    Gradle

    • No longer using deprecated Gradle methods in the Kobweb Application plugin
      • Uncertain at this point but it may enable a caching performance improvement later

    Misc

    • Updated dependencies under the hood, e.g. Kotlin to 1.6.10 and Compose to 1.0.1
    Source code(tar.gz)
    Source code(zip)
  • v0.9.7(Feb 15, 2022)

    The main feature in this release is the addition of the new routePrefix setting, which, when set in your project's conf.yaml will tell Kobweb that your site lives under a subfolder in the domain.

    So if you owned the domain example.com and set the routePrefix of a/b/c would mean that the root of your site would map to https://example.com/a/b/c/


    Frontend

    • You can now set routePrefix in your conf.yaml
    • Update Silk Link widget to be routePrefix aware
    • Add new Image widget to Silk (which is essentially an Img that is routePrefix aware)
    • Add new Divider widget to Silk (which is essentially an Hr tag but Silk-theme aware plus some better defaults)
    • Fixed bugs with relative paths and mailto, etc. URLs not working
    • Screen now resets to the top when you change the current path
    • Allow users to customize the link opening strategy so, e.g., they can always make sure that links open in new pages instead of the current one
      • Also, control keys are now respected, e.g. "Ctrl + left click" opens a link in a new browser
    • Fixed a bug with overwriting Silk theme styles being rejected as a duplicate incorrectly

    Markdown

    • Markdown now uses the new Silk Image and Divider classes if available
    • Markdown logic around computing header IDs is improved
      • Duplicate header IDs are now made unique by appending an incrementally counting number
      • The IDs are stored in a per page data map so that they can be checked against later instead of recalculated

    Misc

    • Gradle updated to version 7.4
    Source code(tar.gz)
    Source code(zip)
  • cli-v0.9.6(Feb 15, 2022)

    The main feature in this release is the addition of the new routePrefix setting, which, when set in your project's conf.yaml will tell Kobweb that your site lives under a subfolder in the domain.

    So if you owned the domain example.com and set the routePrefix of a/b/c would mean that the root of your site would map to https://example.com/a/b/c/


    • If a project has its routePrefix set, kobweb run will append it to the link that it shows
    • Tightened up sloppy wording in a few places
    Source code(tar.gz)
    Source code(zip)
    kobweb-0.9.6.tar(9.76 MB)
    kobweb-0.9.6.zip(8.85 MB)
  • v0.9.6(Feb 10, 2022)

    With this version, Kobweb now supports exporting static layouts. This means if you don't care about any of Kobweb's dynamic features, and you're happy just serving static html / js directly, you can use Kobweb to export your website into a simpler format that various existing hosting sites can host for you for cheap (or even free).

    $ kobweb export --layout static
    # If you want to test that it's working locally, you have to tell "run" about it
    $ kobweb run --env prod --layout static
    

    This feature will only work if you are using the kobweb CLI versioned 0.9.5 or newer, so please check kobweb version first if you're experiencing issues.

    Source code(tar.gz)
    Source code(zip)
  • cli-v0.9.5(Feb 10, 2022)

    With this version, Kobweb now supports exporting static layouts. This means if you don't care about any of Kobweb's dynamic features, and you're happy just serving static html / js directly, you can use Kobweb to export your website into a simpler format that various existing hosting sites can host for you for cheap (or even free).

    $ kobweb export --layout static
    # If you want to test that it's working locally, you have to tell "run" about it
    $ kobweb run --env prod --layout static
    

    This feature will only work if you are targeting Kobweb libraries 0.9.6 or newer, so please check your gradle/libs.versions.toml file first if you're experiencing issues.


    Release Notes

    • For convenience, you can now use kobweb --version or kobweb -v in addition to kobweb version
    • Improve help docs for kobweb conf
    • Support different export layouts, and support static layouts in addition to classic Kobweb layouts
    Source code(tar.gz)
    Source code(zip)
    kobweb-0.9.5.tar(9.75 MB)
    kobweb-0.9.5.zip(8.85 MB)
  • v0.9.5(Feb 8, 2022)

    A very tiny patch release that comes with a breaking change in Canvas

    Normally this fix on its own wouldn't be worth releasing, except I just pushed out a blog post talking about the canvas widget exposing the colorMode value, and, whoops, my memory was wrong. Instead, it exposes a SilkPalette field.

    The SilkPalette class used to expose the current color mode but that changed at some point, and now it's better to expose the color mode instead. You can get a palette from the color mode but not the other way around.

    If you get a compile error, here's how to fix it.

    Before:

    Canvas2d(...) {
       val someColor = palette.color
       ...
    }
    

    After:

    Canvas2d(...) {
       val palette = colorMode.toSilkPalette()
       val someColor = palette.color 
       ...
    }
    
    Source code(tar.gz)
    Source code(zip)
Owner
Varabyte
Varabyte
Cross-platform framework for building truly native mobile apps with Java or Kotlin. Write Once Run Anywhere support for iOS, Android, Desktop & Web.

Codename One - Cross Platform Native Apps with Java or Kotlin Codename One is a mobile first cross platform environment for Java and Kotlin developers

Codename One 1.4k Dec 23, 2022
A small, yet full-featured framework that allows building View-based Android applications

Conductor A small, yet full-featured framework that allows building View-based Android applications. Conductor provides a light-weight wrapper around

BlueLine Labs 3.9k Jan 6, 2023
A full-featured framework that allows building android applications following the principles of Clean Architecture.

EasyMVP A powerful, and very simple MVP library with annotation processing and bytecode weaving. EasyMVP eliminates the boilerplate code for dealing w

null 1.3k Nov 19, 2022
A Model-View-Presenter / Model-View-Intent library for modern Android apps

Mosby A Model-View-Presenter and Model-View-Intent library for Android apps. Dependency dependencies { compile 'com.hannesdorfmann.mosby3:mvi:3.1.1

Hannes Dorfmann 5.5k Dec 25, 2022
UltimateAndroid is a rapid development framework for developing your apps

UltimateAndroid Version:0.10.2 UltimateAndroid is a rapid development framework for developing apps Master branch: Dev branch: V0.7.0 Ui Demo screensh

MarshalChen 2.1k Dec 26, 2022
A plugin system that runs like a browser, but instead of load web pages, it load apk plugins which runs natively on Android system.

Android Dynamic Loader Android Dynamic Loader is a plugin system. The host application is like a browser, but instead of load web pages, it load plugi

Tu Yimin 1.4k Dec 28, 2022
A framework for hook java methods.

Legend Projects are out of date, plese move to: Whale Hook What is Legend? Legend is a Hook framework for Android Development, it allows you to Hook J

Lody 1.6k Dec 15, 2022
LiteOrm is a fast, small, powerful ORM framework for Android. LiteOrm makes you do CRUD operarions on SQLite database with a sigle line of code efficiently.

#LiteOrm๏ผšAndroid้ซ˜ๆ€ง่ƒฝๆ•ฐๆฎๅบ“ๆก†ๆžถ A fast, small, powerful ORM framework for Android. LiteOrm makes you do CRUD operarions on SQLite database with a sigle line

้ฉฌๅคฉๅฎ‡ 1.5k Nov 19, 2022
Rosie is an Android framework to create applications following the principles of Clean Architecture.

Rosie The only way to make the deadlineโ€”the only way to go fastโ€”is to keep the code as clean as possible at all times. โ€” Robert C. Martin in Clean Cod

Karumi 1.8k Dec 28, 2022
A data-binding Presentation Model(MVVM) framework for the Android platform.

PLEASE NOTE, THIS PROJECT IS NO LONGER BEING MAINTAINED. As personal time contraints, I am currently unable to keep up. Please use official android da

RoboBinding open source 1.3k Dec 9, 2022
Android Plugin Framework

Android Plugin Framework This project is pre-mature and may be changed very frequently. Introduction Android Plugin Framework (APF) aims to providing

Umeng Limited 322 Nov 17, 2022
MVVM framework for Android

RoboMVVM - MVVM Framework For Android RoboMVVM is an open source library that facilitates the use of the MVVM pattern in Android apps. The MVVM patter

Debdatta Basu 55 Nov 24, 2020
๐Ÿ”ฅ Android component-based routing framework

README-CN Latest version module krouter-core krouter-compiler krouter-annotation krouter-plugin version Features ๆ”ฏๆŒ้€š่ฟ‡่ทฏ็”ฑ่Žทๅ–intent ๆ”ฏๆŒๆ–นๆณ•ๆณจ่งฃ๏ผŒ้€š่ฟ‡่ทฏ็”ฑ่ฐƒ็”จๆ–นๆณ• ๆ”ฏๆŒ็ป™fra

Jiaming Gu 6 Jun 24, 2022
VasSonic is a lightweight and high-performance Hybrid framework developed by tencent VAS team, which is intended to speed up the first screen of websites working on Android and iOS platform.

VasSonic: A Lightweight And High-performance Hybrid Framework VasSonic is a lightweight and high-performance Hybrid framework developed by tencent VAS

Tencent 11.6k Dec 30, 2022
๐Ÿ”ช AOP development framework implemented through *Annotation + ASM + Gradle Transform API* for Android๐Ÿค–

?? AOP development framework implemented through *Annotation + ASM + Gradle Transform API* for Android??

Pumpkin 325 Nov 22, 2022
๐Ÿš€Plugin for Android Studio And IntelliJ Idea to generate Kotlin data class code from JSON text ( Json to Kotlin )

JsonToKotlinClass Hi, Welcome! This is a plugin to generate Kotlin data class from JSON string, in another word, a plugin that converts JSON string to

Seal 2.8k Jan 3, 2023
Create kotlin android project with one line of command.

README This is an android application template project built with kotlin language and some useful libraries. It provides a creator script to quickly c

nekocode 1.6k Dec 20, 2022
Intellij Idea, Android Studio plugin for generating Kotlin data classes from JSON. Helps to avoid writing boilerplate code for model classes. Supports annotations for Gson, Moshi, Jackson.

JSONToKotlinClass Intellij Idea, Android Studio plugin. Plugin generates Kotlin data classes from JSON text. It can find inner classes in nested JSON.

Vasily 139 Dec 21, 2022
The most complete and powerful data-binding library and persistence infra for Kotlin 1.3, Android & Splitties Views DSL, JavaFX & TornadoFX, JSON, JDBC & SQLite, SharedPreferences.

Lychee (ex. reactive-properties) Lychee is a library to rule all the data. ToC Approach to declaring data Properties Other data-binding libraries Prop

Mike 112 Dec 9, 2022