capacitor-watch-bridge
v7.0.0
Published
A generic JSON sync bridge between a Capacitor iOS app and a native watchOS app using WatchConnectivity and App Groups.
Readme
⌚️ capacitor-watch-bridge
A modern, generic JSON bridge between a Capacitor iOS app and a native watchOS app
using WatchConnectivity and App Groups — built with Capacitor 7 & Swift 5.9.
👉 GitHub: github.com/kisimediaDE/capacitor-watch-bridge
📚 Table of Contents
- 🚀 What you get
- 📦 Installation
- ⚙️ Configuration
- 🧠 Usage
- 🧩 Example App
- API
- 🧰 Requirements
- 🧑💻 Author
- 🪲 Known Limitations
- 📝 License
🚀 What you get
This package contains two Swift targets:
WatchBridgePlugin– the Capacitor iOS plugin (used in your iPhone app)WatchBridgeKit– a tiny watchOS helper framework that:- wraps
WCSessionon the watch - reads the App Group ID from
WatchBridgeAppGroupIdin the watch Info.plist - exposes
@PublishedpropertieslatestKeyandlatestJsonfor your UI
- wraps
High-level features:
✅ Sync arbitrary JSON from iOS → watchOS via updateApplicationContext()
✅ Store the same data in a shared App Group for offline access
✅ Gracefully degrades if no Watch is paired or the app isn’t installed
✅ Swift Package Manager and CocoaPods support
✅ Drop-in Capacitor 7 plugin – zero additional configuration on web
📦 Installation
1. Install the Capacitor plugin
npm install capacitor-watch-bridge
npx cap sync iosCapacitor will add the iOS plugin (CapacitorWatchBridge) to your Podfile automatically.
2. Add WatchBridgeKit to your watchOS target (SPM)
In Xcode:
- File → Add Packages…
- Enter the repo URL:
https://github.com/kisimediaDE/capacitor-watch-bridge.git - Add the following products:
- "CapacitorWatchBridge" → iOS app target (if you also use SPM directly)
- "WatchBridgeKit" → WatchKit Extension target
The repo already ships a Package.swift with:
products: [
.library(name: "CapacitorWatchBridge", targets: ["WatchBridgePlugin"]),
.library(name: "WatchBridgeKit", targets: ["WatchBridgeKit"]),
]⚙️ Configuration
Configure your App Group (iOS + watchOS)
Create an App Group, e.g.:
group.de.kisimedia.watchbridgeThen enable this group under Signing & Capabilities → App Groups for:
- the iOS App target
- the WatchKit Extension target
Capacitor config (iOS app)
// capacitor.config.ts / capacitor.config.json export default { // ... plugins: { WatchBridge: { appGroupId: 'group.de.kisimedia.watchbridge', }, }, };On iOS the plugin:
- First tries plugins.WatchBridge.appGroupId from capacitor.config.
- Falls back to the Info.plist key WatchBridgeAppGroupId (see below).
Info.plist key (watchOS and optional iOS fallback)
WatchKit Extension Info.plist
<key>WatchBridgeAppGroupId</key> <string>group.de.kisimedia.watchbridge</string>This is what WatchBridgeKit uses to know which App Group to write into.
Optional: iOS App Info.plist
If you don’t want to configure the App Group in capacitor.config, you can also set the same key in your iOS app’s Info.plist and skip the plugin config:
<key>WatchBridgeAppGroupId</key> <string>group.de.kisimedia.watchbridge</string>
🧠 Usage
From Capacitor (iOS / web)
import { WatchBridge } from 'capacitor-watch-bridge'; await WatchBridge.syncJson({ key: 'debugText', json: JSON.stringify({ text: 'Hello from Capacitor!' }), }); const info = await WatchBridge.isAvailable(); console.log('Watch status:', info);On watchOS with WatchBridgeKit
SwiftUI example
import SwiftUI import WatchBridgeKit @main struct MyWatchApp: App { @StateObject private var session = WatchBridgeSession.shared var body: some Scene { WindowGroup { VStack(spacing: 8) { Text("WatchBridge Debug") .font(.headline) Text("Key: \(session.latestKey)") .font(.footnote) Text("JSON:") .font(.caption2) ScrollView { Text(session.latestJson) .font(.caption2) .multilineTextAlignment(.leading) } } .padding() } } }WatchBridgeSession will:
- activate the WCSession once
- apply any previously known applicationContext on startup
- listen for new contexts via didReceiveApplicationContext
- optionally write the JSON into your App Group UserDefaults(suiteName:)
Non-SwiftUI / manual access
You can also use it without SwiftUI:
import WatchBridgeKit let session = WatchBridgeSession.shared // Access session.latestKey / session.latestJson // or subscribe via Combine: session.$latestJson.sink { ... }
🧩 Example App
A minimal Capacitor 7 + Vite demo is included under example-app/.
It ships a full working setup:
- iOS app with the Capacitor plugin
- watchOS app using WatchBridgeKit
- both targets sharing the App Group
- a small HTML UI that shows connectivity state & sends JSON to the watch
| iPhone Demo | Watch Demo | | ------------------------------------------------------------------ | ---------------------------------------------------------------------- | | | |
To run it:
cd example-app
npm install
npx cap sync ios
npx cap open iosThe example already uses:
- App Group: group.de.kisimedia.watchbridge
- WatchBridgeKit in the WatchKit Extension
- WatchBridgeSession as shown above
API
Public API of the WatchBridge plugin.
syncJson(...)
syncJson(options: SyncJsonOptions) => Promise<void>Stores a JSON string in the configured App Group and tries to sync it to the watchOS app via WatchConnectivity.
If no watch is paired or available, the data is still written to the App Group and the Promise resolves without error.
| Param | Type |
| ------------- | ----------------------------------------------------------- |
| options | SyncJsonOptions |
isAvailable()
isAvailable() => Promise<IsAvailableResult>Returns information about WatchConnectivity availability:
- if it is supported
- if a watch is paired
- if the watchOS app is installed
Returns: Promise<IsAvailableResult>
Interfaces
SyncJsonOptions
| Prop | Type | Description |
| ---------- | ------------------- | ---------------------------------------------------------------------------------------- |
| key | string | Key under which the data is stored in the shared App Group. Example: "items" or "tasks". |
| json | string | JSON string provided by the app. The plugin does not validate or parse this string. |
IsAvailableResult
| Prop | Type | Description |
| ------------------ | -------------------- | ------------------------------------------------------------------ |
| supported | boolean | True if WatchConnectivity (WCSession) is supported on this device. |
| paired | boolean | True if an Apple Watch is paired with the iPhone. |
| appInstalled | boolean | True if the watchOS companion app is installed. |
🧰 Requirements
- iOS 14+
- watchOS 10+ (for WatchBridgeKit as defined in Package.swift)
- Capacitor 7.0+
- Swift 5.9+
- Xcode 15+
🧑💻 Author
Made with ❤️ by Kisimedia for open-source Capacitor developers everywhere.
🪲 Known Limitations
- Android not implemented (stub only)
- Plugin does not validate JSON syntax
- No bi-directional sync yet (watch → iPhone planned for v2)
📝 License
MIT © Kisimedia.de
See LICENSE for details.
