Larger projects
Sets
Sets split one repository into independent projects. Each set has its own definitions, tests, datafiles and state files. Only featurevisor.config.js is shared.
When to use sets#
Sets suit two situations:
- Separate surfaces that share nothing. A storefront and an admin tool live in one repository, but share no attributes, segments or users. Each becomes a set, so a change to one set's definitions cannot reach the other's users.
- Release lanes.
dev,stagingandproductioneach hold a complete tree, and changes move forward through promotions, so production receives what staging already ran. Environments compares this with environments.
For other needs, something smaller does the job. Use environments for different rules per environment, namespaces to group keys, and targets to split a project into several datafiles.
Set up sets#
Start a project with a storefront and an admin set, each with staging and production environments:
npx @featurevisor/cli@latest init --example=setsThe examples on this page leave those environments out, so each feature has a single list of rules. With environments, each set's features group their rules by environment, as Environments shows.
To convert an existing project, turn sets on in the configuration:
module.exports = { sets: true,}Then move each directory of definitions and tests into sets/<name>/. With sets on, definitions at the top level are ignored without a warning, so make sure nothing is left behind.
Directory structure#
Each set has the layout of a whole project, and its directory name is its name:
sets/storefront/attributes/country.ymluserId.yml
segments/netherlands.yml
features/promoBanner.yml
targets/all.yml
tests/features/promoBanner.spec.yml
segments/netherlands.spec.yml
admin/attributes/role.ymluserId.yml
segments/support.yml
features/promoBanner.yml
targets/all.yml
tests/features/promoBanner.spec.yml
segments/support.spec.yml
- A set can also have
variables/andschemas/. - Every set needs at least one target of its own.
- Inside a set, directory names are fixed. Options such as
featuresDirectoryPathdo not apply, butsetsDirectoryPathmoves the wholesetsdirectory.
The same key in two sets#
Both sets define promoBanner, each with its own audience. The storefront shows it to Dutch visitors:
description: Storefront promotional bannerbucketBy: userIdrules: - key: netherlands conditions: netherlands percentage: 100 - key: everyone conditions: '*' percentage: 0The admin tool shows it to the support team, using an attribute the storefront does not have:
description: Support team membersconditions: - attribute: role operator: equals value: supportdescription: Admin promotional bannerbucketBy: userIdrules: - key: support conditions: support percentage: 100 - key: everyone conditions: '*' percentage: 0Sets cannot see each other. A storefront rule cannot use the admin's support segment, and role is not an attribute there.
Run commands per set#
lint, test and build run every set, under a heading for each. Pass --set to run one:
npx featurevisor test --set=adminnpx featurevisor build --set=storefrontAn unknown name fails and lists the sets that exist. Printing a datafile needs a set, plus --environment if the project has environments:
npx featurevisor build \ --set=storefront \ --json \ --prettyDatafiles, state and revisions#
Each set's datafiles go under its own directory:
tree datafilesdatafiles├── admin│ ├── featurevisor-all.json│ └── REVISION├── REVISION└── storefront ├── featurevisor-all.json └── REVISIONWith environments, the environment comes next, as in datafiles/storefront/production/featurevisor-all.json.
State files are kept per set in .featurevisor/sets/<set>/. The revision is shared. Every build moves it forward, and a build with --set leaves the other sets' datafiles at their previous revision. Build every set before you deploy the whole datafiles directory.
Load a set in your application#
Each application loads the datafile of its own set, such as storefront/featurevisor-all.json. If one application needs two sets, give each its own SDK instance. Loading both into one instance would merge them, and one set's promoBanner would replace the other's.
Move changes between sets#
When sets are release lanes, promotions copy definitions from one set to the next, and promotionFlows limits the direction they can go.

