webviewbridge-guide

Sunalamye's avatarfrom Sunalamye

Guide for using WebViewBridge Swift package to build WebPage (macOS 26.0+) bridges with JavaScript injection and bidirectional communication. Use when integrating WebPage with Swift, injecting JavaScript, or handling JS↔Swift messaging.

⭐0stars🔀0forks📁View on GitHub🕐Updated Dec 7, 2025⬇️1downloads

When & Why to Use This Skill

This Claude skill serves as a comprehensive integration guide for the WebViewBridge Swift package, specifically designed for macOS 26.0+ (WebPage API). It empowers developers to implement seamless bidirectional communication between Swift and JavaScript, providing robust patterns for JavaScript injection, message handling, and WebSocket interception to enhance hybrid application development.

Use Cases

  • Case 1: Building hybrid macOS applications that require high-performance, low-latency communication between native Swift logic and web-based user interfaces.
  • Case 2: Injecting custom JavaScript modules and core utilities into WebPages to extend web content functionality with native system capabilities.
  • Case 3: Implementing complex data synchronization and event handling between JavaScript environments and Swift controllers using structured messaging.
  • Case 4: Debugging and intercepting WebSocket traffic within a WebView to monitor real-time data flows or implement custom network security protocols.
namewebviewbridge-guide
descriptionGuide for using WebViewBridge Swift package to build WebPage (macOS 26.0+) bridges with JavaScript injection and bidirectional communication. Use when integrating WebPage with Swift, injecting JavaScript, or handling JS↔Swift messaging.
allowed-toolsRead, Glob, Grep, Write, Edit, Bash

WebViewBridge Guide

This skill helps use the WebViewBridge Swift package for WebPage (macOS 26.0+) bidirectional communication.

Package Overview

WebViewBridge is a Swift framework for WebPage API with JavaScript injection and bidirectional communication.

Installation

// Package.swift
dependencies: [
    .package(url: "https://github.com/Sunalamye/WebViewBridge.git", from: "1.0.0"),
]

targets: [
    .target(
        name: "YourApp",
        dependencies: ["WebViewBridge"]
    ),
]

Architecture

WebViewBridge/
├── Core/
│   └── WebViewBridge.swift    - Main bridge class
├── JavaScript/
│   └── bridge-core.js         - Core JS utilities
└── WebViewBridgeKit.swift     - Version info

Quick Start

1. Create Bridge & Register Modules

import WebViewBridge
import WebKit

@available(macOS 26.0, *)
@MainActor
class MyViewController: NSViewController {
    let bridge = WebViewBridge(handlerName: "myBridge")
    var webPage: WebPage?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Register core modules
        bridge.registerCoreModules()

        // Register custom module
        bridge.registerModule(JavaScriptModule(
            name: "my-module",
            source: """
                window.myApp = {
                    sendMessage: function(msg) {
                        window.__bridgeCore.sendToSwift('custom_message', { message: msg });
                    }
                };
            """
        ))

        // Handle messages
        bridge.onMessage = { type, data in
            print("Received: \(type) - \(data)")
        }

        // Configure WebPage
        var configuration = WebPage.Configuration()
        let userContentController = WKUserContentController()
        bridge.configure(contentController: userContentController)
        configuration.userContentController = userContentController

        // Create WebPage
        webPage = WebPage(configuration: configuration)
        bridge.configure(webPage: webPage!)
    }
}

2. JavaScript → Swift

// Using bridge-core
window.__bridgeCore.sendToSwift('my_event', { key: 'value' });

// Using custom API
window.myApp.sendMessage('Hello!');

3. Swift → JavaScript

Task {
    // ⚠️ MUST use `return` statement!
    let title = try await bridge.callJavaScript("return document.title")
}

⚠️ Critical: Return Statement

WebPage.callJavaScript() requires return statement!

// ❌ WRONG - returns null
try await bridge.callJavaScript("document.title")

// ✅ CORRECT
try await bridge.callJavaScript("return document.title")
try await bridge.callJavaScript("return JSON.stringify({a: 1})")

JavaScriptModule

let module = JavaScriptModule(
    name: "my-module",
    source: "window.myAPI = { ... };",
    injectAtStart: true,    // default: true
    mainFrameOnly: false    // default: false
)

// Load from bundle
let module = JavaScriptModule.fromBundle(named: "my-script", bundle: .main)

WebViewBridgeDelegate

@available(macOS 26.0, *)
public protocol WebViewBridgeDelegate: AnyObject {
    func bridge(_ bridge: WebViewBridge, didReceiveMessage type: String, data: [String: Any])
    func bridge(_ bridge: WebViewBridge, webSocketStatusChanged connected: Bool)  // optional
    func bridge(_ bridge: WebViewBridge, didEncounterError error: Error)  // optional
}

bridge-core.js API

// Send to Swift
window.__bridgeCore.sendToSwift(type, data)

// Log
window.__bridgeCore.log(message)

// Base64
window.__bridgeCore.arrayBufferToBase64(buffer)
window.__bridgeCore.base64ToArrayBuffer(base64)
window.__bridgeCore.blobToBase64(blob, callback)

// WebSocket interceptor
window.__bridgeCore.installWebSocketInterceptor({
    shouldIntercept: (url) => url.includes('api.example.com')
})

Message Types

Type Direction Description
websocket_open JS → Swift WebSocket connecting
websocket_connected JS → Swift WebSocket connected
websocket_message JS → Swift WebSocket message
websocket_closed JS → Swift WebSocket closed
console_log JS → Swift Log message

Complete Example

@available(macOS 26.0, *)
@MainActor
class WebManager {
    let bridge = WebViewBridge(handlerName: "app")
    var webPage: WebPage?

    func setup() {
        bridge.registerCoreModules()
        bridge.registerModule(JavaScriptModule(
            name: "app-api",
            source: """
                window.App = {
                    notify: (msg) => __bridgeCore.sendToSwift('notify', {msg})
                };
            """
        ))

        bridge.onMessage = { type, data in
            if type == "notify", let msg = data["msg"] as? String {
                print("Notification: \(msg)")
            }
        }

        var config = WebPage.Configuration()
        let ucc = WKUserContentController()
        bridge.configure(contentController: ucc)
        config.userContentController = ucc

        webPage = WebPage(configuration: config)
        bridge.configure(webPage: webPage!)
    }

    func getTitle() async -> String? {
        try? await bridge.callJavaScript("return document.title") as? String
    }
}

Checklist

  • Using @available(macOS 26.0, *)
  • Called registerCoreModules()
  • Configured both contentController and webPage
  • Using return in callJavaScript()
  • Set onMessage or delegate

Reference Documentation