Skip to main content

Getting Started

The BB Channel SwiftUI SDK embeds Blue Billywig video channels in SwiftUI apps. Channels include swim lanes, grids, carousels, search, and detail pages — all rendered in a WKWebView with a native bridge for seamless integration.

Compatibility

RequirementMinimum Version
iOS16+
Xcode15+
Swift5.9+

Package Access

BBChannelSwiftUI is distributed as a pre-built XCFramework from a private GitHub repository. Contact Blue Billywig to receive access.

To authenticate SPM with a private repo, add your GitHub credentials to ~/.netrc:

machine github.com
login YOUR_GITHUB_USERNAME
password YOUR_GITHUB_PAT

The PAT needs repo scope (read access to private repos).

tip

For CI/CD, set the PAT as a secret and write ~/.netrc in a setup step.

Installation

Add the package via Swift Package Manager:

  1. In Xcode, go to File > Add Package Dependencies...
  2. Enter the repository URL:
    https://github.com/bluebillywig/channel-sdks
  3. Select Up to Next Major Version and enter the version
  4. Add BBChannelSwiftUI to your target

Or add it to your Package.swift:

dependencies: [
.package(url: "https://github.com/bluebillywig/channel-sdks", from: "1.0.0"),
],
targets: [
.target(
name: "YourApp",
dependencies: [
.product(name: "BBChannelSwiftUI", package: "channel-sdks"),
]
),
]

Quick Start

import SwiftUI
import BBChannelSwiftUI

struct ContentView: View {
@StateObject private var viewModel = BBChannelViewModel()

var body: some View {
BBChannelView(
channelUrl: "https://demo.bbvms.com/ch/1152.json",
viewModel: viewModel,
callbacks: BBChannelCallbacks(
onReady: {
print("Channel loaded")
},
onMediaPlay: { media in
print("Playing: \(media.title ?? "") — clip \(media.clipId)")
}
)
)
}
}

Channel URL

Channel URLs follow this format:

https://{publication}.bbvms.com/ch/{channelId}.json

Where {publication} is your Blue Billywig publication name and {channelId} is the numeric channel ID.

Configuration Options

Pass a BBChannelOptions struct to customize behavior:

let options = BBChannelOptions(
autoPlay: false,
searchBar: true,
noStats: false,
playout: "default",
jwt: "eyJ..."
)

BBChannelView(
channelUrl: "https://demo.bbvms.com/ch/1152.json",
options: options,
viewModel: viewModel,
callbacks: callbacks
)
PropertyTypeDescription
autoPlayBool?Auto-play the first video. Default: true.
searchBarBool?Show the search bar. Default: from channel config.
noStatsBool?Disable analytics/statistics. Default: false.
playoutString?Override the playout used for players.
jwtString?JWT for authenticated/restricted content.
rpcTokenString?RPC token (legacy, prefer jwt).
nativePlayerModeBool?Use native player instead of WebView player. Default: false.

Events

Handle events via BBChannelCallbacks:

let callbacks = BBChannelCallbacks(
onReady: {
print("Channel is ready")
},
onMediaPlay: { media in
print("Playing: \(media.clipId)")
},
onNavigate: { event in
print("Page: \(event.pageType), can go back: \(event.canGoBack)")
},
onError: { error in
print("Error [\(error.code)]: \(error.message)")
}
)

Use the view model to control navigation:

// Navigate to a detail page
viewModel.navigateTo(page: "detail", clipId: "4701337")

// Go back
viewModel.goBack()

// Search
viewModel.search("keyword")

// Check if back navigation is available
if viewModel.canGoBack {
viewModel.goBack()
}

Deep Linking

Open the channel at a specific page by passing initialNavigationState:

BBChannelView(
channelUrl: "https://demo.bbvms.com/ch/1152.json",
initialNavigationState: BBNavigationState(
page: "detail",
clipId: "4701337"
),
viewModel: viewModel,
callbacks: callbacks
)

Supported pages: main, detail (requires clipId), overview (requires clipListId), search (requires query).

Authentication

For restricted content, pass a JWT in options or update it at runtime:

// Via options
let options = BBChannelOptions(jwt: "eyJ...")

// At runtime
viewModel.setJwt("eyJ...")

Architecture

The SwiftUI SDK uses the same WebView bridge architecture as the React Native SDK. See Architecture for details on the split bundle design, WebView bridge, and native mode detection.

What's Next