Skip to content

features-vote/features-vote-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

11 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

In-App Feature Requests, Roadmap & Changelog. Native for iOS & macOS.

Elastic License 2.0 Swift 5.9 Platforms

Let your users request, vote on, and follow features right inside your app β€” with drop-in SwiftUI views that just work ✨
Zero external dependencies. Apple-native frameworks only.

Feedback board and feedback form

Roadmap and changelog widgets

Index


SwiftUI

1. Add Features.Vote as a dependency in Xcode.

In Xcode β†’ File β†’ Add Package Dependencies, paste:

https://github.com/features-vote/features-vote-sdk.git

Or add it to your Package.swift:

.package(url: "https://github.com/features-vote/features-vote-sdk.git", from: "1.1.0")

2. Configure Features.Vote with your project slug.

No API key required β€” just the project slug you set up at features.vote.
import SwiftUI
import FeaturesVote

@main
struct MyApp: App {
    init() {
        FeaturesVote.configure(with: "your-project-slug")
    }

    var body: some Scene {
        WindowGroup { ContentView() }
    }
}

3. Now use the views wherever you want!

import SwiftUI
import FeaturesVote

struct ContentView: View {
    var body: some View {
        FeaturesVote.VotingBoardView()
    }
}
NOTE: Wrap a view in a NavigationStack if you want push navigation into feature details.

UIKit

1. Add Features.Vote as a dependency in Xcode.

https://github.com/features-vote/features-vote-sdk.git

2. Configure Features.Vote with your project slug.

import UIKit
import FeaturesVote

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        FeaturesVote.configure(with: "your-project-slug")
        return true
    }
}

3. Now present any of the view controllers.

import UIKit
import FeaturesVote

class HomeViewController: UIViewController {
    @objc func buttonTapped() {
        let board = FeaturesVote.votingBoardViewController
        present(UINavigationController(rootViewController: board), animated: true)
    }
}

Views

Five drop-in views cover the full feedback loop. Each has a SwiftUI struct and a matching UIKit view controller.

What it does SwiftUI UIKit
Voting board with filter & sort FeaturesVote.VotingBoardView() FeaturesVote.votingBoardViewController
Feature detail with comments & reactions FeaturesVote.FeatureDetailView(feature:) FeaturesVote.featureDetailViewController(for:)
Submit a new feature request FeaturesVote.CreateFeatureView() FeaturesVote.createFeatureViewController()
Changelog of shipped releases FeaturesVote.ChangelogView() FeaturesVote.changelogViewController
Kanban-style public roadmap FeaturesVote.RoadmapView() FeaturesVote.roadmapViewController
// SwiftUI
FeaturesVote.VotingBoardView()
FeaturesVote.ChangelogView()
FeaturesVote.RoadmapView()

// UIKit
present(FeaturesVote.votingBoardViewController, animated: true)

Theming

Theme Features.Vote to match your app's brand. 🎨

FeaturesVote.theme = Theme(
    // Buttons, accents, and the vote button
    primaryColor: Color(hex: "#7C3AED"),
    secondaryColor: .purple,

    // Surfaces
    backgroundColor: Color(hex: "#F3F4F6"),
    surfaceColor: .white,
    textPrimaryColor: .primary,
    textSecondaryColor: .secondary,

    // Status colors (pending / approved / in progress / done / rejected)
    pendingColor: Color(hex: "#718096"),
    approvedColor: Color(hex: "#06B6D4"),
    inProgressColor: Color(hex: "#F97316"),
    doneColor: Color(hex: "#10B981"),
    rejectedColor: Color(hex: "#EF4444"),

    // Layout
    cornerRadius: 16
)

You can also set fonts (titleFont, bodyFont, captionFont) and errorColor / successColor. Dark mode is supported out of the box. See DOCUMENTATION.md for every property.


Configuration

Toggle UI elements and behavior to fit your app.

FeaturesVote.config = Configuration(
    ui: Configuration.UI(
        showStatusBadge: true,       // e.g. pending, approved, done
        showCommentCount: true,
        showTags: true,
        showWatermark: true,         // "Powered by Features.Vote"
        enablePullToRefresh: true,
        maxDescriptionLines: 3,
        showAvatars: true
    ),
    behavior: Configuration.Behavior(
        allowAnonymousVoting: true,
        allowAnonymousComments: true,
        requireEmailForCreate: false,
        enableOptimisticUpdates: true,   // update UI instantly, revert on error
        cacheTimeout: 300,               // seconds
        confirmVoting: false,
        confirmUnsubscribe: true
    )
)

Vote, comment, share, subscribe, and create button icons are customizable too via Configuration.Buttons.


User Identification

πŸ’° Revenue indication: share how much a user is worth.

// Customer lifetime value β€” shown in your admin dashboard so you can
// prioritize a request with 2 votes and $299 behind it over one with 7 votes and $0.
FeaturesVote.updateUser(spend: 299.0)

πŸ“§ Identify your users (any combination).

FeaturesVote.updateUser(email: "user@example.com")
FeaturesVote.updateUser(name: "Jane Doe")
FeaturesVote.updateUser(imageUrl: "https://example.com/avatar.jpg")

// If you manage user IDs yourself, let Features.Vote track by your ID.
FeaturesVote.updateUser(customID: "user_123")

// For platforms that issue signed sessions.
FeaturesVote.setToken("your-jwt-token")

// Clear the session on logout.
FeaturesVote.clearUser()
If no user is set, the SDK generates an anonymous ID so votes still stay consistent on-device.

Localization

Localize any text by overriding the defaults.

FeaturesVote.localization = Localization(
    votingBoardTitle: "Feature Requests",
    openTab: "Open",
    doneTab: "Done",
    createFeatureTitle: "Suggest a Feature",
    submit: "Submit",
    cancel: "Cancel"
    // ...and every other user-facing string. See DOCUMENTATION.md.
)

// You can assign NSLocalizedString values too.
FeaturesVote.localization.openTab = NSLocalizedString("board.open", comment: "")

Platforms

  • iOS 16+
  • macOS 13+
  • Swift 5.9+ Β· Xcode 15+

Example Project

Check out the TestApp directory for a complete, working example app that exercises every view.

Documentation

  • DOCUMENTATION.md β€” full SDK reference: all configuration options, data models, and API.
  • ARCHITECTURE.md β€” internal architecture guide for contributors.

License

Elastic License 2.0 β€” you may use, copy, modify, and distribute the software, but you may not offer it as a hosted/managed service or competing product, or remove licensing notices. See LICENSE for full terms.

Support

About

Native Swift SDK for embedding feature voting and feedback tools in your iOS and macOS apps

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages