Introducing the FeedbackKit Swift SDK
Today we are releasing Swift SDK 1.0, the Swift package that brings FeedbackKit into your app. It gives an iPhone, iPad, Mac or Vision Pro app a board where people read what others have asked for, vote for what they want, comment, and file their own requests, without leaving the app. Your team then reads, sorts and answers those requests in the FeedbackKit admin app.
The short version
- Three SwiftUI views:
FeedbackListView,SubmitFeedbackViewandFeedbackDetailView. - Voting and comments are built in, and each request shows one of six statuses: Pending, Approved, In Progress, TestFlight, Completed or Rejected.
- Your app can pass each user's MRR, so your team can rank requests by the revenue behind them.
- Colours, badges, buttons and the email prompts are configurable.
- It needs iOS 26, macOS 26 or visionOS 26, and Xcode 26.
What is in Swift SDK 1.0
Three views
FeedbackListView is the board. It loads the project's requests and shows each one as a card with its status, category, title, the start of its description, a comment count and a vote button. A toolbar menu sorts by votes, newest or oldest. Pull to refresh works on iPhone and iPad, and Command-R refreshes on the Mac. A plus button opens the submit form, and an empty project shows a prompt to file a request.
SubmitFeedbackView is the form: a title, a description, a category (Feature Request, Bug Report, Improvement or Other) and an optional email. On the Mac, Command-Return submits.
FeedbackDetailView shows one request in full, with its vote button and its comments. Comments your team writes are labelled as coming from the team.
Voting
A tap on the vote button casts a vote and a second tap removes it. Set allowUndoVote to false to make votes stick, or showVoteCount to false to hide the counts. Voting stops when a request reaches Completed or Rejected. When someone votes and the SDK has no email for them, a small dialog asks for one, with a "Notify me of status changes" toggle. Both are optional, and Skip votes without an email. If your app already knows the address, set userEmail and the dialog does not appear.
A client for your own screens
Everything the views do is also available on the configured client: getFeedback(), getFeedback(id:), submitFeedback(title:description:category:email:), vote(for:), unvote(for:), getComments(for:) and addComment(to:content:). Calls are async and throw a SwiftlyFeedbackError, which separates an invalid API key, a conflict such as a repeat vote, a missing item and a server error.
Users and revenue
The SDK gives each install a user id and keeps it in the Keychain, so it survives a reinstall. If your app has accounts, call updateUser(customID:) with your own id. To weigh requests by revenue, pass what each user pays with updateUser(payment:), as a weekly, monthly, quarterly or yearly amount. The SDK converts it to a monthly figure, and clearUserPayment() removes it.
Theming and configuration
SwiftlyFeedback.theme holds the colours: a primary colour, which can follow your app's accent colour or adapt to light and dark mode, plus a colour per status and per category. SwiftlyFeedback.config holds the switches, for badges, the email field, the comment section, the plus button and the sort menu. allowFeedbackSubmission = false turns filing off with a message of your choice while voting stays open, which suits a paid tier. The SDK also records an event when one of its screens opens; set enableAutomaticViewTracking to false to stop that.
Getting started
Add the package in Xcode with File > Add Package Dependencies and the Up to Next Major Version rule, with 1.0.0 as the lower bound:
https://github.com/Swiftly-Developed/SwiftlyFeedbackKit-Swift-SDK.git
A note on installing 1.0. The 1.0.0 tag points at a commit of our whole workspace, with no Package.swift at its root, so Swift Package Manager cannot resolve it as an exact version. Up to Next Major Version from 1.0.0 installs the latest 1.x release, 1.3.0, and the code below also compiles against that release.
Then configure it once with your project's API key, which you find in the FeedbackKit admin app under the project's settings, and show the board:
import SwiftUI
import SwiftlyFeedbackKit
@main
struct TrailmateApp: App {
init() {
SwiftlyFeedback.configure(
with: "sf_your_api_key",
baseURL: URL(string: "https://api.feedbackkit.prod.swiftly-developed.com/api/v1")!
)
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State private var showingIdeas = false
var body: some View {
Button("Suggest a feature", systemImage: "lightbulb") {
showingIdeas = true
}
.sheet(isPresented: $showingIdeas) {
FeedbackListView()
}
}
}
The explicit production address matters. configure(with:) on its own points at a server on localhost, which is for running FeedbackKit yourself, and configureAuto(with:) sends DEBUG builds there too. The Swift SDK 1.0 tutorial walks through the rest: the submit form, the detail screen, user ids, MRR, the vote dialog and testing. The reference is in the Swift SDK docs.
How FeedbackKit fits in
The SDK is the part your users see. Your team works in the FeedbackKit admin app for iPhone, iPad and Mac: read new requests, merge duplicates, reply in the comments, sort by votes or by the MRR behind them, and move a request through Approved, In Progress and TestFlight to Completed. When a request's status changes, the person who filed it and left an email can be told by email. On Pro and up, requests can go to GitHub, Linear, Notion, ClickUp or Monday.com, and new ones can be posted to Slack. See pricing for what each plan includes.
Here is how the board looks in FeedbackKit, with sample data from a fictional hiking app:
Votes from inside the app
What comes next
Later releases each have their own post, beginning with Swift SDK 1.1. If you are starting today, the current SwiftUI tutorial covers the latest version.
Every plan includes the Swift SDK. Start free, create a project, and put the board in your next build.