Chromium Embedded Framework for SwiftUI apps on macOS.
Why
- Embed real Chromium (not WKWebView) in a SwiftUI app with a single view.
- Three hosting modes: a windowed native browser, a Chrome-runtime window with tabs and
chrome://pages, and an offscreen Metal-backed view for mixing web content into custom layouts. - A SwiftPM command plugin downloads the pinned CEF distribution and assembles a signed
.appwith the five helper bundles. No Xcode required.
Install
dependencies: [ .package(url: "https://github.com/Rajaniraiyn/CefSwift.git", from: "0.1.0") ], targets: [ .executableTarget( name: "MyApp", dependencies: [.product(name: "CefSwiftUI", package: "CefSwift")] ) ]
Quick start
import SwiftUI import CefSwiftUI @main struct MyApp: CefSwiftApp { var body: some Scene { WindowGroup { CefWebView(url: URL(string: "https://example.com")!) } } }
Build a runnable .app (CEF can't run from a bare executable):
swift package --allow-writing-to-package-directory \
--allow-network-connections all \
cef bundle --product MyAppHosting modes
| View | Backing | Use for |
|---|---|---|
CefWebView |
Native NSView, Alloy runtime |
Embedded web content in a SwiftUI layout |
CefChromeWindow |
Chrome runtime window | Tabs, extensions, chrome:// pages — full browser UI |
CefMetalWebView |
Offscreen render, IOSurface → CALayer |
Custom compositing, transforms, mixing into Metal scenes |
Examples
The Examples/ directory is a standalone package with three apps:
Inside the Launcher
Run any of them:
swift package --package-path Examples \
--allow-writing-to-package-directory \
--allow-network-connections all \
cef bundle --product Launcher
open Examples/dist/Launcher.appStatus
macOS only. Requires macOS 14+, Swift 6, and a CEF 148+ distribution (downloaded automatically by the plugin, pinned in CEF_VERSION.json, refreshed by a scheduled workflow). Apple silicon and Intel.
Current limitations: no native V8 window.foo binding (bridge goes through the cefswift:// scheme); accessibility-tree bridging for OSR is enablement-only (no NSAccessibility surface yet).
JS ↔ Swift bridge
Register Swift functions and call them from page JavaScript as typed promises. Inputs/outputs are Codable; handlers are async and run off the main thread.
// Swift CefRuntime.shared.bridge.register("greet") { (name: String) in "Hello, \(name)" }
// JS — window.cefSwift is auto-injected at load-end while any handler is registered const reply = await window.cefSwift.invoke('greet', 'World');
Push events the other way with CefRuntime.shared.bridge.broadcast(event: "tick", data: [...]) — pages subscribe via window.cefSwift.on('tick', fn).
Full reference (typed vs raw handlers, shim auto-injection, transport, security guidance): docs/configuration.md — JS ↔ Swift bridge.
Sandbox
The Chromium macOS sandbox is wired end-to-end. Off by default for ad-hoc dev builds; flip config.noSandbox = false to enable it in a properly signed bundle. See docs/sandbox.md.
Documentation
See docs/ for architecture (hosting modes, OSR/Metal, threading), bundling, configuration (JS bridge, links/popups, context menus), sandboxing, and the auto-update pipeline.
License
BSD 3-Clause. See LICENSE. The Chromium Embedded Framework is a separate work under the same license; ship its license alongside your app.
Made with ❤️ by Rajaniraiyn
































