Let's render a simple page with Ktor server and kotlinx.html : get ( "/users.html" ) { call . respondHtml { myLayout ( title = "Users" ) { userList ( users = db . users . value , ) } } } A reusable myLayout provides scaffolding, userList encapsulates the specific page content, and db.users is a StateFlow<List<User>> from the persistence layer. I've been doing this over and over to create admin das
26 Aug 2026Latest posts
Two months ago I gave my first ever live programming talk at KotlinConf. It was called "Talking to terminals (and how they talk back)", and you can watch it here . I've previously done slide-heavy talks which contained small demos or navigating through an existing codebase. Since this talk was starting from nothing, I decided to just write all the code from nothing. This meant spending the majorit
16 Jul 2026I'm happy to announce that Retrofit, OkHttp, and Okio are moving to a new GitHub organization, and along with SQL Delight are all joining the Commonhaus Foundation . You can read their announcement of the move . This move is meant to reinforce our commitment to these projects' longevity and honor the fact that they've long since outgrown the stewardship of a single company. The transfer of these p
17 Jun 2026Eight years ago we launched a library of Kotlin extensions for the Android platform, Android KTX. In the time since, the library became Core KTX, and numerous other KTX libraries were written for other AndroidX libraries. And while KTX's approach to adding Kotlin niceties was built on a strong technology foundation, we’ve made the difficult decision to begin winding down our KTX extension librarie
1 Apr 2026Many people rely on the Compose bill of materials (BOM) artifact to provide the complete set of Compose dependency versions. If we use Compose’s foundation 1.8.0 but a transitive dependency bumps foundation-layout, there’s a risk that these two versions are incompatible with each other despite otherwise being stable libraries. The Compose BOM will unify the versions so that all are guaranteed to w
3 Dec 2025Did you know the versioning of AndroidX libraries and their stability guarantees are different from most libraries? Their betas and RCs are actually production-ready, and you should be using them! In a “normal” library, such as the ones I release, features are added and known bugs are fixed to produce a stable release which might be released as version 1.2.0. If any bugs are found in that release,
19 Nov 2025I used to use Bit.ly to put links into my presentations. Their service allowed you to customize the path portion of the link, so I was able to create links like bit.ly/ok-libs . If you were attending the talks live, watching the recording, or browsing the slides, the short URL was easy to type into a browser. Unfortunately, the path customization of Bit.ly is a global namespace. Short and memorabl
14 Oct 2025It doesn't take long for a project to spawn multiple jobs in their GitHub Actions. Parallelization can lead to huge speedups for PRs. Job grouping makes it easier to conditionally enable or disable multiple steps. Each time you add a new job, however, you have to mark it as required in branch protection to prevent failing PRs from accidentally merging. Being a clever person, you might create a fin
7 May 2025JNI allows managed code inside the JVM or ART to call into native code. Java methods can be declared as native , and then a corresponding C function 1 can be written and automatically wired together when the native library is loaded. Native code lacks mechanisms like packages and overloads, so a special format is used to encode the Java method signature. A Java method defined as: package com.examp
12 Mar 2025When Espresso was made public a decade ago, one of its banner features was the "idling resource" concept. This monitored the main thread and any background thread pools to prevent your test from progressing until the app became idle. Waiting until idle generally increased the stability of tests since at that point the UI should be stable. We released RxIdler and okhttp-idling-resource for monitori
19 Feb 2025You want to be using the latest JDK for development. Don't use Gradle toolchains , they'll needlessly force you to use old JDKs. You can still target and test on old JVM versions but develop with the latest and greatest. Java and the JDK are literally built for this. Locally this hasn't been a problem. Homebrew (or your favorite equivalent) will keep your default JDK at the latest. Keeping my GitH
8 Jan 2025There was a time when I used Maven heavily, but today all the libraries I work on build with Gradle. Even though I'm publishing with Gradle, consumers can use Gradle, Maven, Bazel, jars in libs/ (but please don't), or anything else. That's a huge JVM ecosystem win! In general, I don't have to think about what build system someone is using. I'm not here to debate subjective pros and cons of one ver
28 Mar 2024The last post featured some Kotlin code inadvertently targeting a new Java API when the build JDK was bumped to 21. This can be solved with the -Xjdk-release Kotlin compiler flag, or by using Gradle toolchains to build with an old JDK. If you read the Gradle docs … Using Java toolchains is a preferred way to target a language version …or the Android docs … We recommend that you always specify the
21 Mar 2024Yesterday, our Android app crashed with a weird NoSuchMethodError . java.lang.NoSuchMethodError: No interface method removeFirst()Ljava/lang/Object; in class Ljava/util/List; or its super classes (declaration of 'java.util.List' appears in /apex/com.android.art/javalib/core-oj.jar) at app.cash.redwood.lazylayout.widget.LazyListUpdateProcessor.onEndChanges(SourceFile:165) at app.cash.redwood.lazyla
13 Mar 2024Given an array of integers ( [1, 2, 3, 1, 3, 1] ), find the elements which are duplicated. No, we're not interviewing. I'm trying to prevent a user from specifying a reserved value twice. Elsewhere in the file I already have duplicate detection for object tags. val dupes : Map < Int , List < Widget >> = widgets . groupBy ( Widget :: tag ) . filterValues { it . size > 1 } I can do the same techniqu
14 Feb 2024Given a list of users, extract their names and join them into a comma-separated list. Kotlin's extension functions on collections make this trivial. users . map { it . name }. joinToString () Writing this in IntelliJ IDEA produces a "weak warning" offering advice. Call chain on collection type may be simplified An intention action will refactor the code for you to a more efficient form. users . jo
7 Feb 2024This post was published externally on Cash App Code Blog. Read it at https://code.cash.app/molecule-1-0 .
19 Jul 2023This post was published externally on Cash App Code Blog. Read it at https://code.cash.app/native-ui-and-multiplatform-compose-with-redwood .
5 Jul 2023This post was published externally on Cash App Code Blog. Read it at https://code.cash.app/flow-testing-with-turbine .
21 Jun 2023jlink is a JDK tool to create bespoke, minimal JREs for your applications. Let's try it with a "Hello, world!" program: class Main { public static void main ( String ... args ) { System . out . println ( "Hello, world!" ); } } My laptop is an M1 Mac and I have downloaded the Azul Zulu JDK 19 build for it. With the JDK I can both compile Java and then run the resulting program. $ mkdir out $ zulu19
16 Jan 2023