Featurevisor

Ship it

Projects

A Featurevisor project is a Git repository of YAML definitions. Your team changes it through pull requests, and CI builds it into the datafiles your applications load. This page covers creating one, choosing its layout and what each directory holds.

Create a project

The CLI needs Node.js 24 or later. Run these in an empty directory:

Commands
npx @featurevisor/cli@latest init
npm install

The @latest tag makes npx fetch the current release, rather than reuse an older version it has cached.

You get a working project with one feature, one segment and one target:

Project
  • featurevisor.config.js project configuration
  • package.json the CLI and npm scripts
  • attributes/
    • country.yml
    • deviceId.yml
    • userId.yml
  • segments/
    • netherlands.yml
  • features/
    • showCookieBanner.yml
  • targets/
    • all.yml
  • tests/
    • features/
      • showCookieBanner.spec.yml
    • segments/
      • netherlands.spec.yml

package.json adds npm scripts for the common commands, so npm run lint, npm test and npm run build work as well as npx featurevisor lint, test and build. The Quick start adds a feature and a variable to this project.

Definitions are YAML by default. init --example=json and init --example=toml scaffold a project in JSON or TOML instead, and custom parsers read any other format.

Choose a layout

The layout decides how a change travels from staging to production. init takes an --example that sets up environments, sets, or both:

LayoutCommand
Neither, the defaultinit
Environmentsinit --example=with-environments
Sets for release lanesinit --example=environments
Sets and environmentsinit --example=sets
  • The default keeps one list of rules per feature, so a change reaches every application that loads the datafile. Start here unless you already know you need more.
  • Environments keep rules for staging and production side by side in each feature, and build a datafile for each. One pull request can change both, and a reviewer sees them together.
  • Sets keep a separate tree of definitions per release lane, such as dev, staging and production. A change starts in the first lane and moves on with a promotion.
  • Sets with environments combine both, for one repository holding several independent projects.

--example=environments uses sets, despite its name: each environment is a set. --example=no-environments is the same as the default. Environments helps you choose, and shows how to switch an existing project.

Directories

DirectoryHolds
attributes/Attributes, the context your apps pass
segments/Segments built from attribute conditions
features/Features with their rules and variables
variables/Global variables
schemas/Reusable schemas for variables
targets/Targets, one per datafile
tests/Test specs and scenarios
datafiles/Built datafiles, not committed
.featurevisor/State files, committed by CI

Create variables/ and schemas/ when you first need them. Subdirectories of features/, segments/ and variables/ become namespaces. Every path can be changed in the configuration.

The scaffold's .gitignore leaves out datafiles/, because CI builds them. .featurevisor/ records how variations were allocated, so the next build keeps users in the same variation. CI commits it after each deployment build. Leave it out of your own pull requests.

Keep it in its own repository

Put the project in its own Git repository, separate from your applications:

Commands
git init
git add .
git commit -m "Initial commit"

Configuration changes then go through their own pull requests, tests and history, and reach your applications without a release. See Decoupled releases.

Anyone who can open a pull request can propose a change, such as raising a rollout or adding a market, and the team reviews it like code. People who would rather not read YAML can browse the same project, with its tests and history, in the Catalog.

The CLI also works without Git, or inside an existing monorepo. Some features need Git history, such as Catalog's change history and featurevisor diff.

Your applications do not need Node.js

Only the project uses Node.js. What it produces is static JSON, which SDKs in many languages read. An application in Go, Swift or Python loads the same datafile as one in JavaScript.

Previous
Testing