Skip to content

Repository files navigation

Chatty iOS SDK

Native SwiftUI chat UI for Chatty — zero WebView, zero compromise.

Drop a fully native, on-brand support chat into any iOS app in minutes. Talks directly to the same /api/widget/* backend as the Chatty web widget, and renders every bubble, avatar, and composer with real SwiftUI views — no WKWebView, no JS bridge, no compromise on feel.

CI SPM compatible CocoaPods License: MIT iOS 15+ Stars

Install · Quick start · Design gallery · API reference · Example app


Note

Developed and code-reviewed in an environment without an Xcode/swiftc toolchain, so changes are never compiled locally before pushing. ci.yml runs swift build / swift test on real macOS runners on every push — check the badge above is green before relying on a pre-release build, and please open an issue if it isn't.

Why this SDK

No WebView, anywhere Every bubble, avatar, and the composer are real SwiftUI views — no iframe, no JS bridge, no WKWebView overhead.
Matches your dashboard automatically Fetches the bot's theme and renders with the exact colors, corner radii, and launcher shape chosen in the dashboard — no manual styling.
Two integration shapes A floating ChattyLauncher button + sheet, or an embedded ChattyChatView inside your own view hierarchy.
A real composer, not a stub Emoji picker, animated attach menu (camera + photo library), and mic-to-text voice notes — built in, not bolted on.
Zero third-party dependencies Only Apple's own SwiftUI, PhotosUI, AVFoundation, and Foundation.

Install

Swift Package Manager (recommended)

In Xcode: File → Add Package Dependencies… and enter:

https://github.com/PersonaliAI/chatty-ios-sdk

Or add it to Package.swift directly:

dependencies: [
    .package(url: "https://github.com/PersonaliAI/chatty-ios-sdk", from: "1.0.4")
]
CocoaPods
pod 'ChattySDK', '~> 1.0.4'

Quick start

Find your bot ID in the Chatty dashboard under Embed & Integrate → iOS SDK.

Floating launcher (recommended) — a button that expands into a chat sheet, the native equivalent of the web widget's launcher:

import ChattySDK

struct RootView: View {
    var body: some View {
        ContentView()
            .overlay(ChattyLauncher(botId: "YOUR_BOT_ID"))
    }
}

Embedded full-screen chat — place it directly in your own navigation, e.g. as a "Support" tab:

import ChattySDK

struct SupportScreen: View {
    var body: some View {
        ChattyChatView(botId: "YOUR_BOT_ID")
    }
}

Design gallery

The SDK ships all 10 Chatty widget designs as SwiftUI color/radius tokens, ported 1:1 from the web widget's globals.css, so a native screen looks like whatever design is chosen in the dashboard rather than one generic look. No configuration required — the SDK fetches the bot's theme and resolves the matching token set automatically, including legacy widget_style IDs from older presets.

Design Accent
minimal #1c1a15
playful #ff8a5c
corporate #1c2e4a
dark-sleek #00e5c7
gradient-glow #a855f7
glassmorphism #8f6ff0
ecommerce #0f9d8c
healthcare-calm #6f9c7d
neubrutalism #ff3d67
luxury-editorial #161412

Font pairing (each web design uses a distinct Google Font) is intentionally out of scope for this release; color, radius, and header/bubble treatment carry most of a design's identity.

API reference

ChattyLauncher

public init(
    botId: String,
    baseURL: String = chattyDefaultBaseURL,
    host: String? = nil,
    position: ChattyPosition = .bottomTrailing,
    color: Color? = nil,
    onVoiceCallPress: (() -> Void)? = nil,
    onNotificationBellPress: (() -> Void)? = nil
)
Param Description
botId Required. Your bot's ID from the dashboard.
baseURL Chatty backend base URL. Defaults to the production API.
host Advisory only — sent to the backend but not used for access control. See Notes.
position .bottomLeading or .bottomTrailing. Default .bottomTrailing.
color Overrides the launcher color. Defaults to the active design's accent color.
onVoiceCallPress Forwarded to ChattyChatView's header voice-call button. See Notes.
onNotificationBellPress Forwarded to ChattyChatView's header notification bell. See Notes.

ChattyChatView

public init(
    botId: String,
    baseURL: String = chattyDefaultBaseURL,
    host: String? = nil,
    onMessage: ((ChattyMessage) -> Void)? = nil,
    onVoiceCallPress: (() -> Void)? = nil,
    onNotificationBellPress: (() -> Void)? = nil,
    onClose: (() -> Void)? = nil
)
Param Description
botId Required. Your bot's ID from the dashboard.
baseURL Chatty backend base URL. Defaults to the production API.
host Advisory only — sent to the backend but not used for access control. See Notes.
onMessage Called for every inbound message — useful for unread badges or analytics.
onVoiceCallPress Header voice-call button tapped. Only shown when the bot's dashboard has voice enabled. See Notes.
onNotificationBellPress Header notification-bell button tapped, after the OS permission prompt resolves. See Notes.
onClose Renders a close (✕) button in the header when set. ChattyLauncher passes this for you.

Notes

Security — bot_id and domain restriction

bot_id is not a secret — it's extractable from any client, web or mobile. Domain restriction (allowed_domains in the dashboard) is enforced by the backend as a rate-limit tier, not a hard reject: verified web traffic gets 30 msgs/60s per bot+IP, everything else (including all mobile SDK traffic — there's no way for a native app to obtain a "verified" token the way a browser's Referer allows) gets throttled to 5 msgs/120s. The host param this SDK sends is advisory only and isn't used for access control. If your bot is mobile-primary, leave allowed_domains empty to get the normal 30/60s tier instead.

Notification bell — what it does and doesn't do

Tapping it requests the OS notification permission and then calls onNotificationBellPress. That's as far as this SDK goes — actually delivering a push when a reply arrives while the app is backgrounded needs APNs (or a wrapper like OneSignal) wired up at the app level: register the device token, send it to your backend, store it against the session/user, and have the backend call APNs when a message lands for a session that isn't actively polling. None of that exists yet — it's backend work in chatty-backend.

Voice-call button

Only shown when the bot's dashboard has voice enabled, and only fires onVoiceCallPress — this SDK doesn't bundle a voice-call implementation (a separate LiveKit integration, out of scope here).

  • Lead capture and meeting booking happen conversationally (the assistant decides to ask/act) — there's no separate REST call to trigger them from the SDK.
  • Polling for human-agent takeover messages runs every 4s while ChattyChatView is active, matching the web widget's behavior.
  • Conversation history is persisted locally (UserDefaults), mirroring the web widget's localStorage cache, so a returning user sees their prior messages.

Example app

Example/ChattySDKExample.xcodeproj is a minimal, runnable SwiftUI app demonstrating both integration styles side by side. Open it in Xcode (it resolves ChattySDK as a local Swift Package pointing at the repo root) and run on a simulator to try the floating launcher and the embedded full-screen chat against a live demo bot.

Requirements

  • iOS 15+ (macOS 13+ for the library target)

  • Swift 5.7+, SwiftUI

  • Uses async/await, @StateObject — no third-party dependencies

  • Add these keys to your app's Info.plist to use the composer's mic and camera buttons (a library target can't inject Info.plist entries — this has to be in the consuming app):

    <key>NSMicrophoneUsageDescription</key>
    <string>Used to record voice messages in chat.</string>
    <key>NSCameraUsageDescription</key>
    <string>Used to attach photos in chat.</string>

    Without these, tapping the mic/camera silently does nothing (iOS kills the process on a missing usage string rather than showing an error).


Contributing — bug reports, design-parity fixes, and PRs are welcome.

Licensed under MIT © PersonaliAI

About

Official iOS SDK for Chatty AI chatbots — native SwiftUI, no WebView

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages