Frontend Development With Fritz2
By: Nick Apperley
Tags: Kotlin Js, Kotlin, Web Development

One time I came across a YouTube video where part of the video title included Reactive. Upon looking at the title I was about to dismiss the video as yet another one going into reactive concepts (for a different area), however there was more than meets the eye in the video itself which left me as a Kotliner intrigued. In the video the presenter covered doing frontend web development using Fritz2, which is a framework for developing frontend web applications using Kotlin that doesn’t have a dependency on any JS libraries/frameworks (at least it isn’t like this JS library), handles concurrency via Flow, and does development in ways that are Kotlinic (idiomatic Kotlin/the Kotlin way).

Many people that watch the video will be left very impressed by what was achieved in around an hour. If you thought Kotlin React was impressive after watching the Kotlin Conf presentation the Fritz2 presentation will blow you away. Fritz2 is one of these things in software development that changes the way you think about development in a specific area, which in this case is frontend web development.

Frontend Basics

Fritz2 covers the basics of Frontend web development by covering the following:

Styling

Custom controls

State management (incl data binding)

Data validation

Remote communication

Data formatting

Routing

Support for Web Components (an official web standard)

Much of Fritz2’s design philosophy revolves around ”less is more”. The only dependencies the framework relies on are the Kotlin JS Standard library, KotlinX Coroutines (for Flow), and Kotlin Test JS (for testing only). Many things that are done in the framework are written from the ground up in Kotlin with no JS in sight, which for many is a impressive feat.

The best way to understand how Fritz2 works is to develop a small web application. I have developed my own web application which shows some New Zealand Covid-19 statistics visually through a chart. You can see the rest of my web application on GitLab.

Views

With the views I heavily take advantage of Fritz2’s HTML DSL. Each major part of the view is built through a function, eg:

In the example above a button group is created which contains two Bootstrap buttons. The className attribute is set to btn-group through a static Flow data source that is created via the const function. All the button clicks events are connected to a event handler in the ChartStore (more on that later). Note that there is a separate function for creating a Bootstrap button since Fritz2 doesn’t have Bootstrap support although it is very easy to add the support in as needed.

The entire view is built in the render function which can only take a single top level HTML element. In order for the results to appear the view needs to be mounted (attached) to a existing part of the DOM. Usually Fritz2 based applications mount to the body via the target convention, eg:

This will be based on existing HTML which is similar to the following:

State Management

A core part of Fritz2 is centralised management of application state, which includes event handling, eg:

Each piece of state is managed in a separate store that is Flow based. All stores are created with a default state. In this example the default state is New Zealand Covid-19 Tests Per Month which was specified as the parameter to the RootStore constructor. Usually root stores are used for managing state. Any event handlers related to the state in the store are stored in the same store as the state itself. An event handler is created using the handle function and MUST have a value as the last line in the lambda, which updates the state in the store.

Data Binding

In Fritz2 many of the HTML element attributes have built in support for data binding, which includes events. Data binding is either one or two way (bi-directional) and is heavily tied to stores, eg:

The bind function is used to provide one way data binding to data in the ChartStore, which in this case is applied to text in the h2 HTML element. Every time the data changes in the ChartStore the text in the h2 HTML element is updated to reflect the new data in the ChartStore.

JetPack Compose

Takes a similar approach to Fritz2 with building/structuring views, and to a lesser degree with handling state but differs significantly with data binding. Unlike Fritz2 JetPack Compose doesn’t come with a wide range of controls out of the box which makes it unsuitable to use for developing business applications. Both JetPack Compose and Fritz2 use Kotlin compiler plugins. JetPack Compose doesn’t have a single way to handle concurrency (user either chooses Flow or Rx Java), whereas Frizt2 has a single way via Flow.

Testing is covered in JetPack Compose but not in Fritz2. Public APIs with JetPack Compose at times suffer from incoherent design. For instance functions don’t follow the official Kotlin Coding Conventions, and some parts of the API use the infamous Java Builder API design instead of being Kotlin DSL based.

Kotlin React

Takes a similar approach to Fritz2 with building/structuring views. Unlike Fritz2 Kotlin React is heavily reliant on a JS library which means there are a lot of dependencies, and the library only covers building/structuring views. Fritz2 covers much more and comes across as a complete frontend web development solution (covers all the basics).

Sponsorship

Considering how impressive and game changing Fritz2 is, along with the fact that Kotlin has a gem that will significantly improve its reputation in the frontend web space Fritz2 needs some sponsorship. There are two parties who come to mind who should be sponsoring the project.

First party is Pivotal who have already made a heavy investment in Kotlin which mainly revolves around the backend software development area. Some will be aware that Pivotal are using Kotlin extensively in various projects, and the company announced official support for Kotlin with Spring 5. Pivotal’s Kotlin advocate (Sébastien Deleuze) made a case on Kotlin for frontend web development which seems to fit in with Pivotal’s future plans for Kotlin.

In more recent times Pivotal developed a successor to Spring Boot 5 called WebFlux which is Reactive based, heavily relies on Kotlin DSLs, and uses reactive concurrency via Flow. If Pivotal are serious about using Kotlin for frontend web development then they should sponsor the project which would nicely complement their Kotlin strategy.

Second party is Barclays Bank who have used Kotlin in new frontend web development projects, and are banking big on using Kotlin for frontend web development instead of using TypeScript or JS. Barclays Bank have the resources to sponsor Fritz2 which would easily fit into the work they are doing which is Kotlin JS/HTML 5 based.

JetBrains is unlikely to sponsor Fritz2 since they are betting big on React via Kotlin React which they maintain/develop, and are heavily using Kotlin React in their Space product/service. A possible black horse who might sponsor Fritz2 is HTTP4K. The web backend Kotlin library like Fritz2 is functional based, uses some of the same ideas like lenses and using functions for program composition. HTTP4K doesn’t yet have a path forward for handling concurrency, and could take a similar approach that Fritz2 is taking with Flow. If HTTP4K were to support the use of Kotlin for frontend web development then sponsoring Fritz2 would be a way they can achieve that.

Conclusion

Despite Fritz2 being in the early stages the framework holds great promise. With some further maturity/development along with major sponsorship Fritz2 will be able to successfully challenge major JS libraries/frameworks like React, and Angular. For many Kotliners Fritz2 finally provides a viable way to develop frontend web applications using a pure Kotlin approach.

Considering what Fritz2 has achieved for Kotlin in the frontend web development space the project should be nominated for Kotlin project of the year. In the future if Fritz2 is still around then it would be good to see the framework ported to Kotlin WASM to give Kotlin a head start in the WASM space.