Client-side feature flags

Did you know you can use Flipper to create and manage feature flags for your client-side app, even though Flipper is a Ruby gem and doesn't have client libraries in other languages? (Yet!)

In one of our apps, we created a custom Flipper API that returns the value of all enabled feature flags for the authenticated user. A client can consume this API, sharing the current state of feature flags between client and server.

A diagram illustrating how client-side code can access a Rails controller at `/features.json` to retrieve a server-generated list of enabled features as a JSON file and a small JavaScript conditional using an `isEnabled` function that uses the results to determine if a flag is enabled.
Adding a /features.json endpoint that can return a list of enabled features provides a straightforward way to access feature flags in client-side code. 

Create a custom Flipper API

First generate your new controller:

$ rails generate controller Flipper

…and add a route to make it accessible:

# config/routes.rb
resources :features, controller: "flipper", only: [:index]

…and add a method to your controller that returns the value of all feature flags for the current user:

class FlipperController < ApplicationController
  # Returns the value of all feature flags for the current user
  def index
    # Get a list of all features and their values for the current user
    features = Flipper.features.map do |feature|
      [feature.key, Flipper.enabled?(feature.key, current_user)]
    end

    # Return the feature list as JSON
    render json: features.to_h
  end
end

This simple controller gets a list of all defined features and their values for the current user and returns the list as JSON, which will render something like:

{
  "feature1": true,
  "feature2": false
}

Or, if any of your feature flags are sensitive, the response could only return the enabled feature flags so that any disabled flags aren't leaked to end users.

Use the API in your client

Now that you have an API that returns the value all feature flags, you can use it in your client to determine which features are enabled for the current user.

For example, for an app written in JavaScript, you could create a flipper.js module that uses fetch to load the value of all feature flags:

// flipper.js
const features = fetch("/features.json").then(response => response.json());

export async function isEnabled(key) {
  return await features.then(features => features[key]);
};

Now use this module to determine if a feature is enabled:

import { isEnabled } from "./flipper.js";

if (await isEnabled("new_feature")) {
  // render new feature
} else {
  // render old feature
}

You can also use this simple API with Vue or React.

That's all, folks!

That's it! Whether you're app uses JavaScript, Swift, Java, C#, or any other language you want, you now have a simple way to manage feature flags for both your server and client-side apps. When you're ready to launch new features, just flip it in one place and your server and client apps will be in sync.