Skip to content
Go to file

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Configly iOS library

The iOS library for Configly: the modern config/static data key/value store that's updatable through a fancy web UI.


Table of Contents

What is Configly?

Configly is the place software developers put their static / config data—like copy, styling, and minor configuration values. They can then update that data directly from without having to wait for a deploy process app store review. Their app or webapp receives the data near instantly. Non-technical folks themselves can publish changes freeing developers to focus on hard software problems and not copy tweaks.

On the backend, Configly provides a read-optimized static-data key/value store built with the aim of being low-latency, and high-availability. The client libraries are made to be dead-simple, lean, and efficient (via enhancements like caching). There is a fancy web UI called the Configulator for setting and updating the configs as well as seeing things like change history.

There are a host of other benefits to using Configly (such as ensuring you do not have data duplicated across clients, reducing load on your primary DB, and providing better tolerance for traffic spikes), read more about the benefits at Configly.

Core Features

  • API to fetch Strings, JSON Blobs (arrays and objects), Booleans, and Numbers from the Configly backend
  • Web interface for modifying these values without having to deploy code (we call our beloved web interface the Configulator).
  • High availability, high-throughput, low-latency backend.
  • Smart caching on the client libraries to minimize server requests.
  • Client libraries available in an expanding amount of languages.

Concepts / Data Model

  • A Configly account contains a set of Configs.
  • A Config is a key-value pair along with associated metadata (like TTL).
  • The keys are strings.
  • The values are one of the following types:


Type notes Example(s)
string "I <3 Configly!"
number Can be integers or decimal; be aware some clients require you to specify which when fetching 31337, 1.618
boolean only true or false true, false
jsonBlob A JSON5 (more relaxed JSON) array or object. ["one", 5, true]`` * [License](#license)"text": "Buy now!", color: "#0F0"}
More jsonBlob examples

You can make arbitrarily complex JSON structures -- as long as the top level is an object or array. This is incredibly powerful as you can send a host of data with a single config:

A more complex array for a store inventory. Note that because we're using JSON5, quotes are optional for single words.

  "Simple T-shirt",
  "Basic hoodie",
    item: "Complex T-shirt",
    sizes: ['S', 'M', 'L'],
    price_us_cents: [1099, 1499, 1599],

And a more complex object showing how you can internationalize and set style:

  "welcome_message": {
    copy: {
      'en': 'Welcome!',
      'es': "¡Bienvenidos!",
    }, style: {
      color: '#0F0',
      fontWeight: '700',
  "buy_button" : {
    copy: {
      'en': 'Buy',
      'es': "Comprar",
    }, style: {
      backgroundColor: "#F00",
      border: "border-radius 10px",

Getting Started

In four easy steps!

1. Get your API Key

You'll need a Configly account. Registration is lightning quick—you can register via visiting .

After signing up, you can grab your API Key from . You'll need your API Key below to integrate the library into your app.

2. Create your first Config

From, create a new Config via the "Add" button: image

Consider creating a simple JSON Object or Array called greetings and give it the value of: [hello', 'hola', '你好', 'नमस्ते'] should look like this:


Be sure to save via clicking 'Send to Clients'. Now, we'll write client code to fetch this key.

3. Install the client library (via Swift Package Manager)

In your iOS project, go to File -> Swift Packages -> Add Package Dependency..., enter the Github repo URL:

4. Fetch the Config

Add the following code in the execution path. For simplicity, in an iOS app, you could add it to AppDelegate : func application(UIApplication, [UIApplication.LaunchOptionsKey: Any]?) -> Bool.

Place this import at the top of the file in which you'll call the Configly library.

import configly

And place this code snippet in the execution path:

Be sure to substitute your own API KEY If you created a Config named something other than 'greetings', be sure to change it below.

let client = CNGClient.setup(withApiKey: "YOUR_API_KEY")
client.stringArray(forKey: "greetings") { (error, value) -> () in
  guard let value = value else {
    print(" couldn't find that key. Did you create the 'greetings' Config as Step 2 of 'Getting Started' demonstrates?")
  print("Yay! A successful integration!\n greetings -> \(value)")

Execute the project and you should see the payload printed! Try changing some values on to confirm that the client is getting the updates.

Congratulations you have Configly working end-to-end! Now, feel free to use Configly with all your projects!


The golden rule of Configly library use is: do NOT assign the result of a et()to a long-lived variable; in order to check for new values from the server, you must call et()

The package needs to be configured with your account's API key, which is available in the Configly Configulator

Assume in Configly you have two keys with English and Spanish copy:

  'Configly allows you to put all your constants in the cloud',
  'This means you can make changes to your data super fast without waiting on a deploy',
  'Also, business people love the cloud, so win-win'

  'Nunca va a molestarme un hombre de negocio de cambiar el texto',
  '¡Tengo muchisímas ganas de usar Configly!',
  'No voy a poner datos constantes en mi codigo ya que conozco este sitio',

Now, based on the language of the user, you can fetch the proper translation:

    func setCopy(callback: (String, String, String) -> ()) {
        CNGClient.setup(withApiKey: "Dem0apiKEY")
        let copyKey = userSpeaksSpanish() ? "es_copy" : "en_copy"
        CNGClient.shared().stringArray(forKey: copyKey) { (error, value) in
            if (error != nil) {
                print("Failed with error \(error!.status): \(error!.message)")
            guard let copy = value else {
                print("Could not find this key. Are you using the right API Key?")

            // In the real world, we'd likely pass these variables for rendering.

            // callback(copy[0], copy[1], copy[2])
            // But, to demonstrate the idea, let's simply print them
            for el in copy {

    func userSpeaksSpanish() -> Bool {
        if let el =  [true, false].randomElement() {
            return el
        return false

Fetching String's, Booleans and Numbers

The API has methods that work identically for these types:

public func string(forKey: String, callback: (CNGError?, String?))
public func bool(forKey: String, callback: (CNGError?, Bool?))
public func double(forKey: String, callback: (CNGError?, Double?))
public func integer(forKey: String, callback: (CNGError?, Int?))

Fetching JSON

The library provides native methods for JSON string arrays ([String]):

public func stringArray(forKey: String, callback: (CNGError?, Int?))

and JSON String Dictionaries ([String:String])

public func stringDictionary(forKey: String,callback: (CNGError?, Int?))

For these methods, all keys / values must be strings or else the JSON will fail to parse!

For more complex, you need to define your own Decodable, as described next.

Fetching complex JSON Blobs

The Configly client allows you to send arbitrarily complex JSON via Swift's Decodable interface

Let's demonstrate through an example.

Assume we have the following JSON saved in []:

  has_sale: false,
  discount: 0.8,
  items: [ 'T Shirt', 'Hoodie', 'Ferrari', ],
  prices: [ 100, 250, 200000, ],

Define your own Decodable

struct StoreLandingPage: Decodable {
    var has_sale: Bool
    var discount: Double
    var items: [String]
    var prices: [Double]

Then, fetch the data:

let client = CNGClient.setup(withApiKey: "Dem0apiKEY")
client.object(forKey: "store_catalog") { (error, value: StoreLandingPage?) -> () in
    if (error != nil) {
        print("Failed with error \(error!.status): \(error!.message)")
    guard let payload = value else {
        print("Could not find this key. Are you using the right API Key?")

    var prices: [Double] = [];
    if (payload.has_sale) {
        for price in payload.prices {
            prices.append( Double(price) * value!.discount )
    } else {
        prices = payload.prices

    // Normally, you'd render these values to your app. But since this is an example, we'll just
    // print them and leave that part to you!
    if (payload.has_sale) {
        print("There is a sale!");
    for (index, item) in payload.items.enumerated() {
        let amount = String(format: "$%.02f", prices[index])
        print("\(item) costs \(amount)")


No description, website, or topics provided.




No packages published


You can’t perform that action at this time.