• Stars
    star
    797
  • Rank 57,151 (Top 2 %)
  • Language
    Swift
  • License
    MIT License
  • Created almost 2 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Publish your roadmap inside your app and allow users to vote for upcoming features

RoadmapHeader Copy@1x

⚠️ The countAPI which we use in Roadmap to let users vote has been down for six weeks or so. They're looking into it, but currently roadmap is unfortunately not working. The provider of the countapi has let us know that they don't expect the API to be fixed anytime soon, so we are looking for alternatives.

Have a look at this PR for an alternative that we might introduce as the default soon! #71

Roadmap

Publish your roadmap inside your app and allow users to vote for upcoming features, without having to create a backend!

Example

RoadmapHeader@1x

Setting up Roadmap

Create a Roadmap JSON

Roadmap works with a remote JSON configuration listing all features and their statuses. We recommend hosting it on GitHub Pages or simplejsoncms.com.

An example JSON looks as follows:

[
    {
        "id": "1",
        "title": "Combine sentences",
        "status": "planned",
        "description" : "You can add a little bit of extra context here."
    },
    {
        "id": "2",
        "title": "Open with Finder support",
        "status": "planned"
    },
    {
        "id": "3",
        "title": "Initial Launch",
        "status": "finished",
        "description" : "Release v1 to the public.",
        "isFinished": true
    }
]

The keys id, title are mandatory and all have to be strings. You can use any value for status or description.

Support For Localization

If you are looking to support localization, then you need to add extra optional parameters in your JSON localizedTitle, localizedDescription and localizedStatus like:

[
  {
    "id": "0",
    "title": "Adding a map",
    "localizedTitle": [
      {
        "language": "ar",
        "value": "اضافة خارطة"
      },
      {
        "language": "en",
        "value": "Adding a map"
      }
    ],
    "status": "planned",
    "localizedStatus": [
      {
        "language": "ar",
        "value": "مجدولة"
      },
      {
        "language": "en",
        "value": "Planned"
      }
    ],
    "description": "some description",
    "localizedDescription": [
      {
        "language": "ar",
        "value": "اضافة خارطة لمعرفة الاماكن القريبة"
      },
      {
        "language": "en",
        "value": "Adding a map to view nearby places"
      }
    ]
  }
]

Keep a list of finished features

If you add isFinished as true to a feature in your JSON, the voting view will be hidden for the users & no API call will be made to fetch votes. This is an optional value and it's default value is false.

Add Roadmap using Swift Package Manager

Add https://github.com/AvdLee/Roadmap.git within Xcode's package manager.

Create a Roadmap Configuration instance

Create a new Roadmap configuration following the documentation:

let configuration = RoadmapConfiguration(
    roadmapJSONURL: URL(string: "https://simplejsoncms.com/api/k2f11wikc6")!
)

Optional you can also handover a request for more advanced endpoints, for example protected by OAuth:

var request = URLRequest(url: URL(string: "https://simplejsoncms.com/api/k2f11wikc6")!)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer 1234567890", forHTTPHeaderField: "Authorization")

let configuration = RoadmapConfiguration(
    roadmapRequest: request
)

Use the configuration to construct the view

And use the configuration inside the RoadmapView:

struct ContentView: View {
    let configuration = RoadmapConfiguration(
        roadmapJSONURL: URL(string: "https://simplejsoncms.com/api/k2f11wikc6")!,
        namespace: "yourappname" // Defaults to your apps bundle id
        allowVotes: true, // Present the roadmap in read-only mode by setting this to false
        allowSearching: false // Allow users to filter the features list by adding a searchbar
    )

    var body: some View {
        RoadmapView(configuration: configuration)
    }
}

Post Portrait@1x

Styling

By initializing the RoadmapConfiguration with a RoadmapStyle you can create your own styling.

public struct RoadmapStyle {
    /// The image used for the upvote button
    let upvoteIcon : Image
    
    /// The image used for the unvote button
    let unvoteIcon : Image
    
    /// The font used for the feature
    let titleFont : Font
    
    /// The font used for the count label
    let numberFont : Font
    
    /// The font used for the status views
    let statusFont : Font
    
    /// The tint color of the status view
    let statusTintColor: (String) -> Color
    
    /// The corner radius for the upvote button
    let radius : CGFloat
    
    /// The backgroundColor of each cell
    let cellColor : Color
    
    /// The color of the text and icon when voted
    let selectedForegroundColor : Color
    
    /// The main tintColor for the roadmap views.
    let tintColor : Color
    
    public init(upvoteIcon: Image,
                unvoteIcon: Image,
                titleFont: Font,
                numberFont: Font,
                statusFont: Font,
                statusTintColor: @escaping (String) -> Color = { _ in Color.primary },
                cornerRadius: CGFloat,
                cellColor: Color = Color.defaultCellColor,
                selectedColor: Color = .white,
                tint: Color = .accentColor) {
        
        self.upvoteIcon = icon
        self.titleFont = titleFont
        self.numberFont = numberFont
        self.statusFont = statusFont
        self.statusTintColor = statusTintColor
        self.radius = cornerRadius
        self.cellColor = cellColor
        self.selectedForegroundColor = selectedColor
        self.tintColor = tint
        
    }
}

Post Portrait Copy@1x

Templates

If you don't wan't to configure your own style you can also use one of the templates. You have the option between Standard, Playful, Classy and Technical so pick whichever works best for your app.

Example

struct ContentView: View {
    let configuration = RoadmapConfiguration(
        roadmapJSONURL: URL(string: "https://simplejsoncms.com/api/k2f11wikc6")!,
        namespace: "roadmap",
        style: RoadmapTemplate.playful.style, // You can also create your own RoadmapStyle
    )

    var body: some View {
        RoadmapView(configuration: configuration)
    }
}

Persisting Votes

By default, Roadmap will utilise the Free Counting API to store votes, you can check out their website for more information. A namespace is provided for you, utilising your application's bundle identifier, but you can override this when initalising the RoadmapConfiguration.

let configuration = RoadmapConfiguration(
    roadmapJSONURL: URL(string: "https://simplejsoncms.com/api/k2f11wikc6")!,
    namespace: "my-custom-namespace"
)

Defining Custom Voter Service

If you'd rather use your own API, you may create a new struct conforming to FeatureVoter. This has two required functions in order to retrieve the current vote count and to cast a new vote.

struct CustomFeatureVoter: FeatureVoter {
    var count = 0

    func fetch(for feature: RoadmapFeature) async -> Int {
        // query data from your API here
        return count
    }
    
    func vote(for feature: RoadmapFeature) async -> Int? {
        // push data to your API here
        count += 1
        return count
    }
}

You may then pass an instance of this struct to the RoadmapConfiguration.

let configuration = RoadmapConfiguration(
    roadmapJSONURL: URL(string: "https://simplejsoncms.com/api/k2f11wikc6")!,
    voter: CustomFeatureVoter()
)

FAQ

Does Roadmap prevent users from voting multiple times?

Yes, if a user has voted on a feature they won't be able to vote again from within your app. Users can intercept your network traffic and replay the api call if they're really desperate to manipulate your votes.

Can Roadmap be customized to fit the look and feel of my app?

Roadmap comes with four different preconfigured styles to match most apps. You can change the tintColor, upvote image and more.

What OS versions are supported?

To keep development of Roadmap easy and fun, we've decided to support iOS 15 & above and macOS Monterey & Ventura for now.

Can I sort my roadmap by most voted?

Right now the list of features is loaded in random order. Our thinking is that this will prevent bias for the top voted features. We'll look into ways to make this possible in the future but since the votes are retrieved after the view has been loaded we'll need to look into it.

Do I need to make changes to my app privacy report if I use Roadmap?

Roadmap does not do any analytics or tracking. If a user voted on a feature it will increment a number on the count api. No identifiers are stored, not even anonymous ones.

Is it possible for stupid people to manipulate my roadmap?

Yes, we wanted to keep Roadmap as simple as possible to setup. If you're worried about competitors (or a user that really wants a specific feature) messing with your priority list, maybe use something else.

Can I help contribute?

Yes, please! We would love to invite you to pick up any of the open issues. We'll review your Pull Requests accordingly.

Projects using Roadmap

If you've integrated Roadmap into your app and you want to add it to this list, please make a Pull Request.

Authors

This library is created in collaboration between Jordi Bruin, Hidde van der Ploeg, and Antoine van der Lee

License

Roadmap is available under the MIT license. See the LICENSE file for more info.

More Repositories

1

appstoreconnect-swift-sdk

The Swift SDK to work with the App Store Connect API from Apple.
Swift
1,431
star
2

CombineSwiftPlayground

A Swift playground explaining the concepts of the new Combine framework
Swift
1,102
star
3

SwiftUIKitView

Easily use UIKit views in your SwiftUI applications. Create Xcode Previews for UIView elements
Swift
710
star
4

Poes

A Swift command-line tool to easily send push notifications to the iOS simulator
Swift
453
star
5

RocketSimApp

Enhancing the iOS simulator for productivity
Swift
425
star
6

CoreDataBestPractices

Best Practices in Core Data explained within a demo application
Swift
413
star
7

WhatTheErrorCode

Convert unreadable errors into understandable descriptions
Swift
143
star
8

Moya-SwiftyJSONMapper

Map objects through SwiftyJSON in combination with Moya
Swift
115
star
9

AsyncOperations

Asynchronous Operations in Swift explained in a Swift Playground
Swift
92
star
10

QR-Code-Custom

A playground demonstrating a way to create a custom QR code with a custom color and logo in Swift.
Swift
42
star
11

TaskGroupsResultBuilder

A @resultBuilder to use to bundle tasks together.
Swift
36
star
12

AppUpdately

Fetch the update available status for iOS or macOS apps based on the bundle identifier.
Swift
36
star
13

CombineWorkshop

Contains all files needed for my Combine workshop.
Swift
32
star
14

appstoreconnect-app

A Mac App to control App Store Connect!
Swift
28
star
15

CustomSwiftOperators

Demonstrating custom Swift operators. Including prefix, postfix, infix, and compound assignment operators.
Swift
18
star
16

CombineExtensions

A collection of Combine Extensions
Swift
16
star
17

ALLocalizables

Localizable label and buttons directly from the interface builder
Ruby
14
star
18

ALDataRequestView

A view representation for data requests. Support for ReactiveSwift and RXSwift
Swift
13
star
19

StockAnalyzerApp

Public repo for tracking bugs and features for the Stock Analyzer app
Swift
7
star
20

DataRacesActors

Slides and content from my SwiftLeeds talk "Understanding Data Races and Actors in Swift 5.5"
Swift
7
star
21

UIControl-Blocks

Use blocks with UIControls
Objective-C
6
star
22

Moya-JASONMapper

Map objects through JASON in combination with Moya
Swift
5
star
23

ImageCollectionViewer

Get FB Albums and show them in a gallery
Objective-C
4
star
24

ImageGen

A library to generate images easily based on text input
4
star
25

MeetupRaffle

Raffle a member from a meetup event
Swift
3
star
26

organizing-conferences-checklist

General tips on organising conferences, based on feedback from the community
1
star