A lightweight, cross-platform SwiftUI chat UI framework.
Perfect for AI chatbots, customer support, and messaging apps.
Installation • Quick Start • Message Types • Themes • AI & Chatbot • Custom Cells
Also available for Flutter.
- 11 built-in message types — text, image, video, location, carousel, quick replies, link previews, contacts, loading indicators, and more
- 8 pre-built themes with full style customization via SwiftUI environment
- Cross-platform — iOS 17+ and macOS 14+ from a single codebase
- High performance — O(n) complexity, cached formatters, async image loading
- Chatbot-ready — carousels, quick replies, and loading states designed for AI/bot interfaces
- Lightweight — just 2 dependencies (Kingfisher + SwiftUIEKtensions)
- Custom message cells for any type you need
- Landscape orientation support with auto-scaling cells
- User avatars with configurable positioning
- Keyboard dismiss on tap and scroll
- Scroll to bottom or to a specific message
- Picture-in-Picture video playback
- Per-corner rounding on text bubbles
- Multiline input bar (BasicInputView)
- Attributed string / markdown support
| Light | Dark | Theme Showcase |
|---|---|---|
![]() |
![]() |
![]() |
Add SwiftyChat in Xcode via File → Add Package Dependencies:
https://github.com/EnesKaraosman/SwiftyChat.git
Or add it to your Package.swift:
dependencies: [
.package(url: "https://github.com/EnesKaraosman/SwiftyChat.git", from: "4.1.1")
]import SwiftyChat
struct ContentView: View {
@State private var messages: [YourMessage] = []
@State private var message = ""
@State private var scrollToBottom = false
var body: some View {
ChatView(messages: $messages, scrollToBottom: $scrollToBottom) {
BasicInputView(
message: $message,
placeholder: "Type something",
onCommit: { messageKind in
messages.append(/* your message */)
}
)
}
.environment(\.chatStyle, ChatMessageCellStyle())
}
}
YourMessagemust conform to theChatMessageprotocol (which has an associatedChatUsertype). See the SwiftyChatDemo app for a complete implementation.
public enum ChatMessageKind: CustomStringConvertible {
case text(String) // Auto-scales for emoji-only messages
case image(ImageLoadingKind) // Local (UIImage/NSImage) or remote (URL)
case imageText(ImageLoadingKind, String) // Image with caption
case location(LocationItem) // MapKit pin
case contact(ContactItem) // Shareable contact card
case quickReply([QuickReplyItem]) // Tappable options, auto-disables after selection
case carousel([CarouselItem]) // Scrollable cards with buttons
case video(VideoItem) // Video with PiP support
case linkPreview(LinkPreviewItem) // Rich URL preview with Open Graph metadata
case loading // Animated loading indicator
case custom(Any) // Your own message type
}A built-in BasicInputView is included. Use it as-is, or build your own — ChatView accepts any view via its inputView closure.
Every visual aspect is customizable through ChatMessageCellStyle — text styles, edge insets, avatar styles, and cell styles for every message type. Inject via .environment(\.chatStyle, yourStyle). All properties have sensible defaults.
See Styles.md for the full style reference and CustomMessage.md for custom cell types.
| Theme | Description |
|---|---|
| Modern | Clean blue, minimal design |
| Classic | Traditional green messaging |
| Dark Neon | Cyberpunk with neon pink accents |
| Minimal | Subtle gray tones |
| Ocean | Calming teal, sea-inspired |
| Sunset | Warm orange gradients |
| Nature | Fresh green, eco-friendly |
| Lavender | Soft purple, relaxing |
See ThemeShowcaseView in the SwiftyChatDemo app for live demos.
SwiftyChat is especially well-suited for AI and chatbot interfaces. Built-in support for carousels, quick reply buttons, loading indicators, and link previews means you can build a rich conversational UI without custom cells:
// Show a loading indicator while the AI responds
messages.append(Message(user: bot, messageKind: .loading))
// Replace with the actual response
messages[messages.count - 1] = Message(
user: bot,
messageKind: .text("Here's what I found...")
)
// Offer follow-up options as quick replies
messages.append(Message(
user: bot,
messageKind: .quickReply([
QuickReplyItem(title: "Tell me more"),
QuickReplyItem(title: "Something else"),
])
))Building a ChatGPT-style app, a customer support bot, or an in-app assistant? SwiftyChat gives you the UI layer so you can focus on the AI logic.
Contributions are welcome! Whether it's a bug fix, new feature, documentation improvement, or a new theme — we'd love your help.
See CONTRIBUTING.md for guidelines.
Inspired by MessageKit (UIKit) and Nio (SwiftUI).
SwiftyChat is available under the Apache 2.0 license. See the LICENSE file for details.






