Featurevisor

Ship it

Configuration

Every project has a featurevisor.config.js at its root, next to package.json. Every option has a default, so an empty object is a valid configuration. This page lists them all.

A typical configuration

The project from the Quick start, once Targets gives it a datafile for web and one for mobile, needs only its tags:

featurevisor.config.js
module.exports = {
tags: ['web', 'mobile'],
}

A project with environments lists them too:

featurevisor.config.js
module.exports = {
tags: ['web', 'mobile'],
environments: ['staging', 'production'],
}

The scaffold's file starts with a @type comment, /** @type {import('@featurevisor/core').ProjectConfig} */, so editors suggest every option as you type. Keep it when you edit the file.

The rest of the options are for larger projects, custom layouts and stricter linting. Each section below gives the default.

Entities

tags

The tags that features, global variables and targets may use. Anything else fails lint. Defaults to ['all'], which nothing uses until you tag a definition with it.

environments

The environments a project's rules, force entries and exposure are grouped by. Leave it out for a project without environments, where features list their rules directly. If present, it needs at least one unique name without surrounding spaces. An empty array fails.

sets

Set to true to split the project into independent sets, each in its own directory under sets/. Defaults to false.

promotionFlows

Restricts which promotions are allowed between sets. Each entry has exactly a from and a to:

featurevisor.config.js
module.exports = {
sets: true,
promotionFlows: [
{ from: 'dev', to: 'staging' },
{ from: 'staging', to: 'production' },
],
}

Without it, any set can be promoted to any other.

reservedKeys

Keys that features, global variables and feature variables may not use. The default protects feature, variation and variable, which generated code and OpenFeature providers rely on. Setting the option replaces the whole list, and an empty array turns the check off. Matching is exact and case sensitive, so checkout.variable does not match variable.

allowFeatureAndVariableKeyCollisions

By default, a feature and a global variable cannot share a key. Set this to true only when the overlap is intentional.

defaultBucketBy

The build uses this bucketBy for a feature that leaves it out. Linting still requires bucketBy on every feature, so in practice each feature sets its own. Defaults to 'userId'.

Layout

namespaceCharacter

Joins the directories of a namespaced feature, segment or global variable into its key. With the default ., features/checkout/express.yml becomes checkout.express.

Attributes cannot be namespaced, and their names before the configured file extension cannot contain dots. Keep their definition files directly in the configured attributes directory. Dots in object attribute paths such as geo.country are independent of this separator.

Directories

Each directory can move. Paths may start with <rootDir>, the project's root:

OptionDefault
attributesDirectoryPath<rootDir>/attributes
segmentsDirectoryPath<rootDir>/segments
featuresDirectoryPath<rootDir>/features
variablesDirectoryPath<rootDir>/variables
schemasDirectoryPath<rootDir>/schemas
targetsDirectoryPath<rootDir>/targets
testsDirectoryPath<rootDir>/tests
setsDirectoryPath<rootDir>/sets
datafilesDirectoryPath<rootDir>/datafiles
stateDirectoryPath<rootDir>/.featurevisor
catalogDirectoryPath<rootDir>/catalog

stateDirectoryPath holds the state files to commit, and catalogDirectoryPath is where catalog export writes the Catalog.

catalogBasePath

The URL path the Catalog is served from, such as /flags/. Defaults to /:

featurevisor.config.js
module.exports = {
catalogBasePath: '/flags/',
}

It applies to assets, data requests and navigation, and does not change the output directory. Use an absolute path whose parts contain letters, numbers, dots, underscores and hyphens. . and .. on their own are rejected, and a trailing slash is added if missing. For a GitHub Pages project site, use /<repository-name>/ and export with --hash-router. Without it, the host must serve the Catalog's HTML for every path under the prefix.

Build output

datafileNamePattern

How each datafile is named, with %s replaced by the target key. Defaults to featurevisor-%s.json.

revisionFileName

The file in datafiles/ that records the revision. Defaults to REVISION.

prettyState

Writes state files indented, which keeps their diffs readable in pull requests. Defaults to true.

prettyDatafile

Writes datafiles indented. Defaults to false, since applications download them.

stringify

Stores condition expressions in datafiles as strings. Set stringify: false to keep structured expressions instead. This changes their representation, not their meaning, so measure datafile size and evaluation time with your own workload before changing it. Defaults to true.

precomputeMutations

Decides when global variable mutations are applied. Defaults to true, which resolves override trees without continue: true during the build and stores complete values:

Override treetruefalse
Mutations, no continueBuildSDK
Any continue: trueSDKSDK
Plain values onlyBuildBuild

These rows describe ordinary global variables. Composed overrides always emit overrideProgram and run in the SDK, including plain replacements with true. Their base is assembled from evaluated sources, not a static default.

false can shrink datafiles that repeat large values, at the cost of work in the SDK. It does not enable continue or change which override wins, and feature variable mutations always resolve during the build. Older SDKs need upgrading first, as the migration order explains.

Lint rules

enforceCatchAllRule

Requires every feature to end with a rule for conditions: '*', in every environment. Defaults to false.

requireOverrideKeysInFeatures

Requires a key on every variable override in feature rules and variations. Keys show up in detailed evaluations and let promotions protect a single override. Defaults to false.

disallowOperators

Operators that linting and building reject in attribute and variable conditions and test checks, including nested ones:

featurevisor.config.js
module.exports = {
disallowOperators: [
'isNull',
'notNull',
'empty',
'notEmpty',
],
}

Names are case sensitive. The option restricts what projects may write. It does not change how SDKs evaluate.

allowedConditions

Limits which kinds of condition each location accepts. A location you leave out accepts every kind, which is the default:

featurevisor.config.js
module.exports = {
allowedConditions: {
rules: ['segment'],
segments: ['attribute'],
},
}

Here rules can only name segments, and segments can only compare attributes. Audiences are written once, as segments, and rules reuse them by name.

LocationConditions it covers
segmentsA segment's conditions
featuresA feature's root conditions
rulesEach rule's conditions
forceEach force entry's conditions
featureVariableOverridesVariable overrides in feature rules and variations
variablesA global variable's root conditions, compositions included
variableOverridesGlobal variable overrides, nested ones included
KindCondition
attributeAn attribute comparison, such as { attribute: country, ... }
segmentA segment key, such as netherlands
feature{ feature }, with or without variation, and { feature, variable }
variableA global variable comparison, such as { variable: maintenanceMode, ... }

conditions: '*' is always allowed. Conditions inside and, or and not are checked one by one. Lint reports each condition a location does not accept with disallowed_condition, and suggests where it can go instead. Archived definitions are not checked.

Each location is checked on its own. A rule may name a segment that reads a feature, unless segments leaves out feature too.

Building and SDKs ignore this option. Keep the v3 shape gives the configuration matching what v3 allowed.

Variable size limits

Cap the size of variable values, to keep datafiles small. The limits apply to feature variables and global variables alike, including defaults and overrides. Lint reports a value over the limit with its length and the option's name. All default to no limit:

OptionLimits
maxVariableStringLengthCharacters in a string
maxVariableArrayStringifiedLengthCharacters of an array as JSON
maxVariableObjectStringifiedLengthCharacters of an object as JSON
maxVariableJSONStringifiedLengthCharacters of a json value

Extending

parser

The format of definition files. Defaults to yml. Set parser: 'json' for JSON, or pass a custom parser.

plugins

Plugins that add commands to the CLI. Defaults to [].

adapter

The datasource adapter that reads and writes definitions. Defaults to the filesystem.

Previous
Projects