rshankras/webkit-integration
WebKit integration in SwiftUI using WebView and WebPage for embedding web content, navigation, JavaScript interop, and customization. Use when embedding web content in SwiftUI apps.
npx skills add https://github.com/rshankras/claude-code-apple-skills --skill webkit-integration
Embed and control web content in SwiftUI apps using the native WebView struct and WebPage observable class. Covers loading, navigation, JavaScript execution, and view customization.
What do you need?
|
+-- Display a URL or HTML content
| +-- Simple, no interaction needed
| | +-- WebView(url:) --> see webview-basics.md
| +-- Need loading state, reload, custom config
| +-- WebPage + WebView(page) --> see webview-basics.md
|
+-- Navigate programmatically (back, forward, intercept)
| +-- Back/forward list, navigation events
| | +-- see navigation.md
| +-- Intercept or cancel navigation requests
| +-- NavigationDeciding protocol --> see navigation.md
|
+-- Execute JavaScript or communicate with web content
| +-- callJavaScript, arguments, content worlds
| +-- see javascript-advanced.md
|
+-- Capture snapshots, export PDF, web archive
| +-- page.snapshot(), page.pdf(), page.webArchiveData()
| +-- see javascript-advanced.md
|
+-- Handle custom URL schemes
+-- URLSchemeHandler protocol --> see javascript-advanced.md
| API | Minimum OS | Import |
|-----|-----------|--------|
| WebView | iOS 26 / macOS 26 | SwiftUI + WebKit |
| WebPage | iOS 26 / macOS 26 | WebKit |
| WebPage.Configuration | iOS 26 / macOS 26 | WebKit |
| NavigationDeciding | iOS 26 / macOS 26 | WebKit |
| WKContentWorld | iOS 14 / macOS 11 | WebKit |
| WKSnapshotConfiguration | iOS 11 / macOS 10.13 | WebKit |
| WKPDFConfiguration | iOS 14 / macOS 11 | WebKit |
import SwiftUI
import WebKit
struct BrowserView: View {
var body: some View {
WebView(url: URL(string: "https://developer.apple.com")!)
}
}
import SwiftUI
import WebKit
struct ControlledBrowserView: View {
@State private var page = WebPage()
var body: some View {
WebView(page)
.onAppear {
page.load(URLRequest(url: URL(string: "https://developer.apple.com")!))
}
}
}
| Mistake | Problem | Fix |
|---------|---------|-----|
| Using WebView(url:) when you need navigation control | No access to back/forward, reload, or events | Use WebPage + WebView(page) |
| Forgetting import WebKit alongside import SwiftUI | WebView is in SwiftUI but WebPage requires WebKit | Always import both |
| Not observing currentNavigationEvent | Missing loading states, errors go unnoticed | Use onChange(of: page.currentNavigationEvent) |
| Calling callJavaScript before page finishes loading | Script fails because DOM is not ready | Wait for .finished navigation event |
| Using persistent data store for private browsing | User data is saved to disk | Use .nonPersistent() on WebsiteDataStore |
| Not handling nil return from decidePolicyFor(navigationAction:) | Navigation proceeds when it should be cancelled | Return nil to cancel, return NavigationPreferences to allow |
| Passing JavaScript without argument binding | Vulnerable to injection, hard to debug | Use arguments: parameter for named values |
WebPage when any control beyond simple display is neededSwiftUI and WebKit are imported.nonPersistent() data storearguments: parameter, not string interpolationfindNavigator(isPresented:) if needed| File | Contents |
|------|----------|
| webview-basics.md | WebView creation, WebPage setup, configuration, find-in-page, customization modifiers |
| navigation.md | Loading content, back/forward list, navigation events, NavigationDeciding protocol |
| javascript-advanced.md | JavaScript execution, content worlds, snapshots, PDF export, custom URL schemes |
macos/architecture-patterns/ios/navigation-patterns/design/liquid-glass/Take rshankras/webkit-integration from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.