
Ready-to-ship automation for library releases: converts README into a homepage, publishes API docs and interactive browser demo, generates downloadable sample apps, and wires full CI/CD.
A WebView library for Compose Multiplatform that enables you to display web content and HTML across Android, iOS, Desktop (JVM), and Web (WASM) platforms with a unified API.
Key Features:
onScriptResult)WebViewController.evaluateJavaScript)| Capability | Android | iOS | Desktop (JVM) | Web (WASM) |
|---|---|---|---|---|
Load remote url
|
✅ | ✅ | ✅ | ✅ (iframe; subject to CSP/X-Frame-Options) |
Load htmlContent
|
✅ | ✅ | ✅ | ✅ |
Custom request headers (headers) |
✅ | ❌ | ❌ | ❌ |
JS → Compose (onScriptResult) with htmlContent
|
✅ | ✅ | ✅ | ✅ |
JS → Compose (onScriptResult) with remote url
|
✅ (bridge injected) | ✅ (bridge injected) | ✅ (bridge injected) | |
Compose → JS (WebViewController.evaluateJavaScript) |
✅ | ✅ | ✅ (executes; no return values yet) | ✅ (same-origin / htmlContent only)
|
evaluateJavaScript return values
|
✅ | ✅ | ❌ (returns Unsupported)
|
✅ (same-origin / htmlContent only)
|
Notes:
htmlContent or same-origin pages you control.evaluateJavaScript currently does not surface return values (it returns WebViewJsResult.Unsupported(...)).Add the dependency to your Compose Multiplatform project:
Option A — Version catalog (recommended)
gradle/libs.versions.toml:[versions]
cmpWebview = "0.0.1"
[libraries]
cmp-webview = { module = "io.github.aryapreetam:cmp-webview", version.ref = "cmpWebview" }build.gradle.kts:kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation(libs.cmp.webview)
}
}
}
}Option B — Direct dependency
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.github.aryapreetam:cmp-webview:0.0.1")
}
}
}
}@Composable
fun MyScreen() {
WebView(
url = "https://example.com",
modifier = Modifier.fillMaxSize(),
onLoadStarted = { println("Loading started") },
onLoadFinished = { println("Loading finished") },
onLoadError = { error -> println("Error: $error") }
)
}@Composable
fun HtmlScreen() {
val html = """
<html>
<body>
<h1>Hello from HTML!</h1>
<p>This is rendered locally.</p>
</body>
</html>
""".trimIndent()
WebView(
htmlContent = html,
modifier = Modifier.fillMaxSize()
)
}JavaScript code in your web content can communicate with your Compose code:
In your HTML/JavaScript:
// Listen for bridge ready event
window.addEventListener('ComposeWebViewBridgeReady', function () {
// Send message to Compose
ComposeWebViewBridge.postMessage('Hello from JavaScript!');
});
// Example: Send button click data
document.getElementById('myButton').addEventListener('click', function () {
ComposeWebViewBridge.postMessage(JSON.stringify({
action: 'buttonClick',
data: 'some value'
}));
});In your Compose code:
@Composable
fun BridgeExample() {
WebView(
url = "https://example.com",
onScriptResult = { message ->
println("Received from JavaScript: $message")
// Parse JSON if needed
val data = Json.decodeFromString<MyData>(message)
// Handle the message
}
)
}If you need to call JavaScript from Compose, pass a WebViewController.
@Composable
fun ComposeToJsExample() {
val controller = rememberWebViewController()
val scope = rememberCoroutineScope()
Column {
Button(onClick = {
scope.launch {
controller.evaluateJavaScript(
"document.body.style.background = 'tomato';" +
"window.ComposeWebViewBridge?.postMessage('ack');"
)
}
}) {
Text("Run JS")
}
WebView(
htmlContent = "<html><body>...</body></html>",
controller = controller,
onScriptResult = { msg -> println("JS→Compose: $msg") },
)
}
}Notes:
htmlContent or same-origin content.Detailed documentation is available in the docs directory:
window.javaBridge → window.kmpJsBridge)Download and try the sample app on your platform without building from source:
| Platform | Download Link |
|---|---|
| 🍏 macOS (Intel) | |
| 🍎 macOS (Apple Silicon) | |
| 🪟 Windows | |
| 🐧 Linux | |
| 🤖 Android | |
| 🌐 Web (Wasm) | |
| iOS Simulator |
For instructions on how to install and run the pre-built executables or build and run the sample application from source code, please refer to the How to Run the Sample App guide.
MIT License © 2025 aryapreetam and contributors. See LICENSE for details.
See CONTRIBUTING.md for detailed contribution guidelines.
A WebView library for Compose Multiplatform that enables you to display web content and HTML across Android, iOS, Desktop (JVM), and Web (WASM) platforms with a unified API.
Key Features:
onScriptResult)WebViewController.evaluateJavaScript)| Capability | Android | iOS | Desktop (JVM) | Web (WASM) |
|---|---|---|---|---|
Load remote url
|
✅ | ✅ | ✅ | ✅ (iframe; subject to CSP/X-Frame-Options) |
Load htmlContent
|
✅ | ✅ | ✅ | ✅ |
Custom request headers (headers) |
✅ | ❌ | ❌ | ❌ |
JS → Compose (onScriptResult) with htmlContent
|
✅ | ✅ | ✅ | ✅ |
JS → Compose (onScriptResult) with remote url
|
✅ (bridge injected) | ✅ (bridge injected) | ✅ (bridge injected) | |
Compose → JS (WebViewController.evaluateJavaScript) |
✅ | ✅ | ✅ (executes; no return values yet) | ✅ (same-origin / htmlContent only)
|
evaluateJavaScript return values
|
✅ | ✅ | ❌ (returns Unsupported)
|
✅ (same-origin / htmlContent only)
|
Notes:
htmlContent or same-origin pages you control.evaluateJavaScript currently does not surface return values (it returns WebViewJsResult.Unsupported(...)).Add the dependency to your Compose Multiplatform project:
Option A — Version catalog (recommended)
gradle/libs.versions.toml:[versions]
cmpWebview = "0.0.1"
[libraries]
cmp-webview = { module = "io.github.aryapreetam:cmp-webview", version.ref = "cmpWebview" }build.gradle.kts:kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation(libs.cmp.webview)
}
}
}
}Option B — Direct dependency
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.github.aryapreetam:cmp-webview:0.0.1")
}
}
}
}@Composable
fun MyScreen() {
WebView(
url = "https://example.com",
modifier = Modifier.fillMaxSize(),
onLoadStarted = { println("Loading started") },
onLoadFinished = { println("Loading finished") },
onLoadError = { error -> println("Error: $error") }
)
}@Composable
fun HtmlScreen() {
val html = """
<html>
<body>
<h1>Hello from HTML!</h1>
<p>This is rendered locally.</p>
</body>
</html>
""".trimIndent()
WebView(
htmlContent = html,
modifier = Modifier.fillMaxSize()
)
}JavaScript code in your web content can communicate with your Compose code:
In your HTML/JavaScript:
// Listen for bridge ready event
window.addEventListener('ComposeWebViewBridgeReady', function () {
// Send message to Compose
ComposeWebViewBridge.postMessage('Hello from JavaScript!');
});
// Example: Send button click data
document.getElementById('myButton').addEventListener('click', function () {
ComposeWebViewBridge.postMessage(JSON.stringify({
action: 'buttonClick',
data: 'some value'
}));
});In your Compose code:
@Composable
fun BridgeExample() {
WebView(
url = "https://example.com",
onScriptResult = { message ->
println("Received from JavaScript: $message")
// Parse JSON if needed
val data = Json.decodeFromString<MyData>(message)
// Handle the message
}
)
}If you need to call JavaScript from Compose, pass a WebViewController.
@Composable
fun ComposeToJsExample() {
val controller = rememberWebViewController()
val scope = rememberCoroutineScope()
Column {
Button(onClick = {
scope.launch {
controller.evaluateJavaScript(
"document.body.style.background = 'tomato';" +
"window.ComposeWebViewBridge?.postMessage('ack');"
)
}
}) {
Text("Run JS")
}
WebView(
htmlContent = "<html><body>...</body></html>",
controller = controller,
onScriptResult = { msg -> println("JS→Compose: $msg") },
)
}
}Notes:
htmlContent or same-origin content.Detailed documentation is available in the docs directory:
window.javaBridge → window.kmpJsBridge)Download and try the sample app on your platform without building from source:
| Platform | Download Link |
|---|---|
| 🍏 macOS (Intel) | |
| 🍎 macOS (Apple Silicon) | |
| 🪟 Windows | |
| 🐧 Linux | |
| 🤖 Android | |
| 🌐 Web (Wasm) | |
| iOS Simulator |
For instructions on how to install and run the pre-built executables or build and run the sample application from source code, please refer to the How to Run the Sample App guide.
MIT License © 2025 aryapreetam and contributors. See LICENSE for details.
See CONTRIBUTING.md for detailed contribution guidelines.