FocusBloom: a Kotlin Multiplatform focus timer with a shared code base
A Kotlin Multiplatform app that helps users enhance their productivity and time management skills through focused work intervals and short breaks.
At a glance
- What is it?
- FocusBloom is a work interval timer built once in Kotlin and compiled to Android, iOS and desktop, and it reads like a well structured sample project rather than a finished application, with the readme itself saying so.
- Who is it for?
- FocusBloom is worth reading or forking as a reference for a Kotlin Multiplatform application that has to ship on Android, iOS and desktop from one code base, and its module split and dependency choices are a good template. It is not worth adopting as a finished productivity tool, since the project says it is still under development and some features may not work as expected, and the last published release is 1.0.5 from 2024-06-19.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Kotlin, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A focus timer that is explicitly a work in progress
FocusBloom is described as a Kotlin Multiplatform app that helps users enhance their productivity and time management skills through focused work intervals and short breaks. In other words, it is a pomodoro style timer, and the readme says so in the first line.
The second thing the readme says is that the project is still under development and that some features may not work as expected, with an invitation to open an issue or a pull request if you find bugs or have suggestions. That framing should be the first input to any adoption decision, because the screenshots show a finished looking application while the text underneath says the opposite.
The platform table is the most concrete part of the documentation. Android, iOS and Desktop are all marked as supported, and the web platform is marked as planned, which is a meaningful difference from the badge row of targets above it. A timer is exactly the kind of application where a web build would be useful, since the only state is a countdown, so the web target being the one that is not there is a little surprising.
There is no feature list beyond that, and no description of the settings, the notification behaviour, the session history or the data model. For a reader deciding whether to use the app, the documentation is thin, and the honest conclusion is that the code is the documentation here.
One shared module, three platform modules
The architecture section is short and clear. The app is shared between Android, iOS and Desktop, the shared code is written in Kotlin, and the user interface is built with Compose Multiplatform.
The compilation story is the part that matters for a multiplatform project. The shared code is compiled to JVM bytecode for Android and Desktop with Kotlin/JVM, and to native binaries for iOS with Kotlin/Native. One source tree, two compilation targets, and the platform specific parts stay in their own modules.
The module diagram in the readme shows the dependency direction, with the desktop and android modules both pointing at the shared module, and the module list underneath names the four of them.
The shared module contains all the code that is common between the platforms. The android module contains the Android app, the ios module contains the iOS app, and the desktop module contains the desktop app. The direction of the arrows is the important part, since the platform modules depend on shared and not the other way round, which is what keeps the shared code free of platform assumptions.
This is the standard shape for a Compose Multiplatform project, and the repository layout confirms it on disk, with shared, android, ios and desktop directories at the top level alongside the Gradle build files, a spotless directory for formatting configuration, a config directory, a scripts directory and the art directory holding the screenshots.
The dependency list is the interesting part of the readme
The built with section lists fourteen tools, and several of them tell you what the application does without the feature list ever saying so.
SQLDelight is there, which is the typed SQL library from Cash App, and it is the reason to think the app persists something structured, most likely session records and their durations. Multiplatform Settings is the key-value store, and Koin is the dependency injection framework, described as pragmatic. Type Safe Compose Navigation and the AndroidX ViewModel handle navigation and state, with the ViewModel class designed to store and manage user interface related data in a lifecycle conscious way.
Kotlinx-datetime and kotlinx-serialization are the multiplatform foundations, a date and time library and a serialization library, and both of those are the pieces you need for a timer that has to work identically on three platforms and store structured records. Koala Plot is a Compose Multiplatform based charting and plotting library, and its presence is the strongest hint about the product: a focus timer that draws a chart is a timer with a history of sessions. Compose Components Resources provides the resources for Compose Multiplatform, and Material3 Window Size Multiplatform is there so the same UI can adapt its layout to a phone or a desktop window.
The last three entries are about the project rather than the app. Spotless is a code formatter that keeps the codebase clean, GitHub Actions is the CI tool, and Renovate is the tool that automates dependency updates. That last one is worth pairing with the release history later on.
There is also a Maven repository entry for Compose Components Resources, which is a small sign of how the project pins its dependencies.
Running the app on each of the three platforms
The run project section gives one path per platform, and each expects a different toolchain.
For Android you open the project in Android Studio and run the imported android run configuration, which is the ordinary path for a Compose Multiplatform project that has an Android app module.
For the desktop there is a single gradle command, and it is the most convenient of the three because it needs nothing but the wrapper in the repository. The command is the desktop module's run task, and it builds through the same Kotlin/JVM target that the Android app uses.
Run the desktop application: `./gradlew :desktop:run`For iOS you open ios/iosApp.xcworkspace in Xcode and run the standard configuration, or you use the Kotlin Multiplatform Mobile plugin for Android Studio, which is the JetBrains plugin that lets the IDE drive the Xcode build. Either way, the iOS build is the slow one, because the shared code has to be compiled to a native binary rather than to bytecode.
For a reader trying the project out, the desktop path is the one to take first. It needs only the gradle wrapper that ships in the repository, it produces a runnable window on the machine you already have, and it avoids the two toolchains that are the actual cost of multiplatform development, which are the Android SDK and Xcode.
The web target is not listed among the run instructions, which is consistent with the platform table marking it as planned.
Where FocusBloom is the wrong choice
Four limits, and they mostly come down to the state of the project rather than to the design.
The first is the work in progress status. The readme says some features may not work as expected, and a timer has a lot of small behaviours that are easy to get subtly wrong: what happens when the app is backgrounded, whether sound plays, whether the session is recorded if you quit halfway. You will find these by using it, which is exactly the cost you were hoping to avoid by using an app instead of writing one.
The second is the release history. The published versions are 1.0.3, 1.0.4 and 1.0.5, with 1.0.5 published on 2024-06-19, while the last push to the default branch was on 2026-10-14. So there is a gap of more than two years between the newest release and the newest commit. Work is landing, and the last published artefact is old, which means the version you install from a store is not the version in the repository.
The third is the platform coverage. Three platforms are supported and one is planned, so a team that needs a browser based timer, or a Linux desktop build, will not find it here. The desktop target is built through Kotlin/JVM, so the platform it runs on is whatever the JVM runs on rather than a native binary.
The fourth is the absence of documentation about behaviour. The readme does not describe the settings, the notification options, the session history or the data model, so the only way to know what the app does is to read the source and run it.
Maintenance, the licence file and what the tooling implies
The repository is not archived and the last push was on 2026-10-14, so somebody is still working in it. The tooling in the tree is the tooling of a maintained project: Spotless for formatting, GitHub Actions for continuous integration, Renovate for automated dependency updates, and a spotless directory in the repository for the formatter configuration.
The licence position needs a note. The repository lists the licence as unknown, and there is no LICENSE file in the top level listing, while the readme carries an Apache License 2.0 notice with a copyright line reading 2023 JoelKanyi. The readme text is a statement of intent, and the header is what would travel with the code if it were copied, but the missing file is the gap.
The readme notice is the standard Apache License 2.0 header text, with the copyright line reading Copyright 2023 JoelKanyi.
If you plan to fork the project, ask the author to add a LICENSE file, or keep the notice in whatever you publish. This is not legal advice, and a permissive licence with the notice attached is easy to accept once the file exists.
One last observation about the release gap. With Renovate keeping dependencies current and Actions running the build, the commits in the last two years are plausibly maintenance rather than features, which would explain why no new version was tagged. That is a reasonable reading of the evidence rather than a fact the repository states, and it is the kind of thing to confirm with the author in an issue before you build on the project.
Editorial conclusion
FocusBloom is worth reading or forking as a reference for a Kotlin Multiplatform application that has to ship on Android, iOS and desktop from one code base, and its module split and dependency choices are a good template. It is not worth adopting as a finished productivity tool, since the project says it is still under development and some features may not work as expected, and the last published release is 1.0.5 from 2024-06-19. Before depending on it, check the web platform status, which is marked as planned rather than shipped, confirm the licence position given the metadata gap, and run the desktop target with the gradle wrapper to see how much of the timer actually works.
Frequently asked questions
What is FocusBloom?
It is a Kotlin Multiplatform app for productivity and time management, built around focused work intervals and short breaks. The readme notes that the project is still under development and that some features may not work as expected.
Which platforms does FocusBloom support?
The platform table marks Android, iOS and Desktop as supported, with the web target marked as planned rather than shipped. The shared code is compiled to JVM bytecode for Android and desktop with Kotlin/JVM, and to native binaries for iOS with Kotlin/Native.
How do I run the FocusBloom desktop application?
With the gradle wrapper in the repository, using the desktop module run task invoked as ./gradlew :desktop:run. On Android you open the project in Android Studio and run the imported android run configuration, and on iOS you open ios/iosApp.xcworkspace in Xcode or use the Kotlin Multiplatform Mobile plugin.
What libraries does FocusBloom use?
Compose Multiplatform for the user interface, SQLDelight for SQL, Multiplatform Settings for key-value data, Koin for dependency injection, type safe Compose Navigation and the AndroidX ViewModel, kotlinx-datetime and kotlinx-serialization, and Koala Plot for charting. On the build side it uses Spotless, GitHub Actions and Renovate.
Under what licence is FocusBloom released?
The readme carries an Apache License 2.0 notice with the copyright line Copyright 2023 JoelKanyi, although the licence field is shown as unknown and no LICENSE file appears in the top level listing. Anyone forking it should confirm the position with the author.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/joelkanyi-focusbloom)Was this useful?