A Gradle plugin that builds your Compose Multiplatform web app as a progressive web app (PWA).
When I turned my first Compose Multiplatform web app into a PWA, I didn't want to run the workbox command after every build, so I wrote a Gradle task to automate it.
But when I made my second app, I didn't want to copy and paste that task into every new web app and maintain each copy separately.
So, I built this plugin.
When you run the wasmJsBrowserDistribution or jsBrowserDistribution task, this plugin does everything needed to turn your web app into a PWA.
Before the build, it automatically creates the required but missing resource files and config file, and adds the necessary tags to your index.html.
After the build, it creates the service worker.
The resource files are manifest.json, registerServiceWorker.js, and icons/*, and they are created next to your index.html.
The config file is workbox-config-for-wasm.js or workbox-config-for-js.js, and it is created directly in the project directory.
The config file is passed as is to the workbox-cli generateSW command.
The service worker has to be recreated on every build, so it is generated directly in the build output directory.
- Node.js (The author uses Volta to install Node.js)
gradle/libs.versions.toml
[versions]
composePwa = "x.x.x" # Please replace with the latest version.
[plugins]
composePwa = { id = "dev.yuyuyuyuyu.composepwa", version.ref = "composePwa" }webApp/build.gradle.kts
plugins {
alias(libs.plugins.composePwa)
}Just apply the plugin and run the wasmJsBrowserDistribution or jsBrowserDistribution task as usual.
./gradlew :webApp:wasmJsBrowserDistributionor
./gradlew :webApp:jsBrowserDistributionYour PWA will be generated in webApp/build/dist/wasmJs/productionExecutable or webApp/build/dist/js/productionExecutable.
You can edit the following files to customize your PWA:
workbox-config-for-wasm.js/workbox-config-for-js.jsmanifest.json(next to yourindex.htmlby default)icons/*(next to yourindex.htmlby default)
You can find a sample GitHub Actions workflow for deploying your PWA to GitHub Pages here:
.github/workflows/deploy-to-github-pages-as-pwa.yml
And you can check out a live example here:
https://compose-pwa-example.yuyuyuyuyu.dev
If you want to generate PWA icons from your own icon, you can use ngx-pwa-icons like this.
npx ngx-pwa-iconsThis plugin depends on the following open-source projects.
Thanks to these projects!
- Jsoup (MIT License) - Used to modify HTML files.
- Node Gradle Plugin (Apache License 2.0) - Used to call the
npxcommand. - Workbox /
workbox-cli(MIT License) - Used vianpxto generate the Service Worker for the PWA.
- Bug reports and bug-fix PRs are very welcome.
- Thinking about a new feature? Please open an issue first. I'd love to talk it through before you write any code — partly to check it fits the "make PWAs effortless" goal, and partly because I'm still figuring out what's in scope for this project.
- New features should come with tests, so that if something breaks later, the tests — not my memory — say how it's supposed to behave.
Before opening a pull request, run the auto-fixers and make sure the Lint check is green:
npm ci
npm run format
npm run lint
./gradlew ktlintFormat versionCatalogFormatSee .github/workflows/lint.yml for everything the Lint check runs.
Apache License 2.0
Copyright 2025 yu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.