API reference
WebView, WebViewState, WebViewNavigator, settings, cookies, JS bridge, and request interception.
The public API lives under dev.nucleusframework.webview. Platform packages re-export the same types from commonMain.
WebView
The multiplatform composable. Draws the native engine and an optional Compose overlay.
@Composable
fun WebView(
state: WebViewState,
modifier: Modifier = Modifier,
navigator: WebViewNavigator = rememberWebViewNavigator(),
webViewJsBridge: WebViewJsBridge? = null,
onCreated: (NativeWebView) -> Unit = {},
onDispose: (NativeWebView) -> Unit = {},
content: @Composable () -> Unit = {},
)contentis Compose UI drawn over the native surface (TaoNativeViewcontent slot on desktop; a layered sibling elsewhere).onCreated/onDisposereceive the platformNativeWebViewhandle when the engine is attached or released.
WebViewState
State holder for one embedded engine. Create it with the rememberWebViewState* helpers.
@Stable
class WebViewState(webContent: WebContent) {
var lastLoadedUrl: String? // last committed URL
var content: WebContent // drives loads when reassigned
var loadingState: LoadingState // Initializing | Loading | Finished
val isLoading: Boolean // true until Finished
var pageTitle: String?
val errorsForCurrentRequest: SnapshotStateList<WebViewError>
val webSettings: WebSettings
val cookieManager: CookieManager
var webView: IWebView? // set after the platform view attaches
}@Composable
fun rememberWebViewState(
url: String,
additionalHttpHeaders: Map<String, String> = emptyMap(),
extraSettings: WebSettings.() -> Unit = {},
): WebViewState
@Composable
fun rememberWebViewStateWithHTMLData(
data: String,
baseUrl: String? = null,
encoding: String = "utf-8",
mimeType: String? = null,
historyUrl: String? = null,
): WebViewState
@Composable
fun rememberWebViewStateWithHTMLFile(
fileName: String,
readType: WebViewFileReadType,
): WebViewStateWebContent
sealed class WebContent {
data class Url(
val url: String,
val additionalHttpHeaders: Map<String, String> = emptyMap(),
) : WebContent()
data class Data(
val data: String,
val baseUrl: String? = null,
val encoding: String = "utf-8",
val mimeType: String? = null,
val historyUrl: String? = null,
) : WebContent()
data class File(
val fileName: String,
val readType: WebViewFileReadType,
) : WebContent()
data object NavigatorOnly : WebContent()
}
enum class WebViewFileReadType {
ASSET_RESOURCES,
COMPOSE_RESOURCE_FILES,
}LoadingState and WebViewError
sealed class LoadingState {
data object Initializing : LoadingState()
data class Loading(val progress: Float) : LoadingState()
data object Finished : LoadingState()
}
@Immutable
data class WebViewError(
val code: Int,
val description: String,
val isFromMainFrame: Boolean,
)WebViewNavigator
Programmatic navigation and script evaluation. Hoist with rememberWebViewNavigator.
@Stable
class WebViewNavigator(
val coroutineScope: CoroutineScope,
val requestInterceptor: RequestInterceptor? = null,
) {
var canGoBack: Boolean
var canGoForward: Boolean
fun loadUrl(url: String, additionalHttpHeaders: Map<String, String> = emptyMap())
fun loadHtml(
html: String,
baseUrl: String? = null,
mimeType: String? = null,
encoding: String? = "utf-8",
historyUrl: String? = null,
)
fun loadHtmlFile(
fileName: String,
readType: WebViewFileReadType = WebViewFileReadType.ASSET_RESOURCES,
)
fun evaluateJavaScript(script: String, callback: ((String) -> Unit)? = null)
fun navigateBack()
fun navigateForward()
fun reload()
fun stopLoading()
}
@Composable
fun rememberWebViewNavigator(
coroutineScope: CoroutineScope = rememberCoroutineScope(),
requestInterceptor: RequestInterceptor? = null,
): WebViewNavigatorBare HTTP(S) host URLs without a path gain a trailing slash before load (browser-style normalization).
WebSettings
@Stable
class WebSettings {
var isJavaScriptEnabled: Boolean // default true
var customUserAgentString: String?
var zoomLevel: Double // default 1.0
var supportZoom: Boolean // default true
var allowFileAccessFromFileURLs: Boolean // default false
var allowUniversalAccessFromFileURLs: Boolean // default false
var logSeverity: KLogSeverity // default None
var backgroundColor: Color // default Transparent
val androidWebSettings: PlatformWebSettings.AndroidWebSettings
val desktopWebSettings: PlatformWebSettings.DesktopWebSettings
val iOSWebSettings: PlatformWebSettings.IOSWebSettings
val wasmJSWebSettings: PlatformWebSettings.WasmJSWebSettings
}Each platform applies the subset it supports. Use the nested *WebSettings objects for engine-specific knobs.
Cookies
interface CookieManager {
suspend fun setCookie(url: String, cookie: Cookie)
suspend fun getCookies(url: String): List<Cookie>
suspend fun removeAllCookies()
suspend fun removeCookies(url: String)
}
data class Cookie(
val name: String,
val value: String,
val domain: String? = null,
val path: String? = null,
val expiresDate: Long? = null,
val isSessionOnly: Boolean = false,
val sameSite: Cookie.HTTPCookieSameSitePolicy? = null,
val isSecure: Boolean? = null,
val isHttpOnly: Boolean? = null,
val maxAge: Long? = null,
)Access the manager through state.cookieManager.
Request interception
interface RequestInterceptor {
fun onInterceptUrlRequest(
request: WebRequest,
navigator: WebViewNavigator,
): WebRequestInterceptResult
}
data class WebRequest(
val url: String,
val headers: MutableMap<String, String> = mutableMapOf(),
val isForMainFrame: Boolean = false,
val isRedirect: Boolean = false,
val method: String = "GET",
)
sealed interface WebRequestInterceptResult {
data object Allow : WebRequestInterceptResult
data object Reject : WebRequestInterceptResult
class Modify(val request: WebRequest) : WebRequestInterceptResult
}Interception applies to navigator-driven main-frame navigations only.
JS bridge
@Immutable
open class WebViewJsBridge(
val navigator: WebViewNavigator? = null,
val jsBridgeName: String = "kmpJsBridge",
) {
fun register(handler: IJsMessageHandler)
fun unregister(handler: IJsMessageHandler)
fun clear()
}
interface IJsMessageHandler {
fun methodName(): String
fun handle(
message: JsMessage,
navigator: WebViewNavigator?,
callback: (String) -> Unit,
)
}
@Composable
fun rememberWebViewJsBridge(navigator: WebViewNavigator? = null): WebViewJsBridgeAfter each finished load (or URL change), the library injects window.<jsBridgeName> with callNative(methodName, params, callback). Register handlers before or after attach; clear happens when WebView leaves composition.
What's next
- Getting started — the same API used across a full browser chrome.
- WebView overview — supported targets and platform backends.
Getting started
Load URLs and HTML, navigate the history stack, evaluate JavaScript, and intercept requests from Compose.
OS integration
Kotlin modules that expose native macOS, Windows, and Linux desktop capabilities such as notifications, system tray, global hotkeys, media controls, dark mode, and system colors.