@softwareimaging/backstage
TypeScript icon, indicating that this package has built-in type declarations

3.2.0 • Public • Published

Backstage

Backstage is a headless environment & feature flag library that isn't tied to any specific service or format. It's a React based library that focuses on being easy to use and simple to integrate with any (and multiple) feature providers.

The current available providers are:


Usage

Install the main library first.

npm i @softwareimaging/backstage --save

And then any providers you want to use, e.g.

npm i @softwareimaging/backstage-local @softwareimaging/backstage-azure-config --save

See the @softwareimaging/backstage-local documentation on how to set up a local environment file.

Adopt and configure the provider as close to the top of component tree as possible.

// backstage-provider.jsx
import { Backstage } from '@softwareimaging/backstage'
import LocalProvider from '@softwareimaging/backstage-local'
import config from './backstage.local'

const BackstageProvider = ({ children }) => {
  const providers = [LocalProvider(1, { config })]

  return <Backstage providers={providers}>{children}</Backstage>
}

Backstage uses suspense to manage it's loading state. Provide a suspense boundary and a fallback state. See the React documentation for more information.

import { Suspense } from 'react'
import { BackstageProvider } from './backstage-provider'

const App = () => {
  return (
    <Suspense fallback="Loading...">
      <BackstageProvider>
        <RestOfApplication />
      </BackstageProvider>
    </Suspense>
  )
}

To use it in your components, use the useVariable and useFlag hooks.

import { useVariable, useFlag } from '@softwareimaging/backstage'
const Component = () => {
  const name = useVariable('name') // string
  const showBanner = useFlag('banner') // boolean

  return <div>{showBanner && <Banner>Hello {name}!</Banner>}</div>
}
const Component = () => {
  const name = useVariable('name') // string

  return (
    <div>
      <Flag name="banner">
        <Banner>Hello {name}!</Banner>
      </Flag>
    </div>
  )
}

Use with TypeScript

It's recommend for TypeScript projects to use an interface to define the known options for your configuration for all of the type-safe-goodness that comes with TypeScript.

Firstly, define your config interface.

// backstage-config.ts
export interface MyConfig extends BackstageConfig {
  variables: {
    apiKey: string
    name: string
  }
  flags: {
    banner: boolean
    promotion: boolean
  }
}

export type Variables = keyof MyConfig['variables']
export type Flags = keyof MyConfig['flags']

It's also worth defining an extra export of your possible variable & flag names. This will make typing your hook calls have less boilerplate.

While that may look a bit weird, it is simply just a type represents the keys in the object. In the example above Variables is equal to 'apiKey' | 'name' and Flags is equal to 'banner' | 'promotion'.

To use this in your components, add the type to your hook calls.

import { useFlag } from '@softwareimaging/backstage'
import { Flags } from './backstage-config'
const Text = () => {
  const promotion = useFlag<Flags>('promotion') // <- This key is typechecked.
  return promotion ? <p>Discount: £10!</p> : <p>Normal pricing: £100</p>
}

Provider Development

If you want to implement a new provider, please use the example and types below as a starting point.

// Please note the nested function, this allows for custom
// priorities at run time. Feel free to use additional arguments
// for configuration.
const provider: BackstageProvider = (priority: number = 0) => () => {
  return {
    priority,
    name: 'Example Provider',
    get: async () => {
      return {
        variables: {
          name: 'Website name',
          colour: '#29008a'
        },
        flags: {
          banner: true
        }
      }
    }
  }
}

Readme

Keywords

none

Package Sidebar

Install

npm i @softwareimaging/backstage

Weekly Downloads

102

Version

3.2.0

License

MIT

Unpacked Size

37.9 kB

Total Files

12

Last publish

Collaborators

  • james-si