In this page you will learn how to setup the CLI to connect it to your CMS instance
You first need to connect the CLI to the Optimizely CMS API.
-
Go to your CMS instance
https://<something>.cms.optimizely.com→ Settings → API Keys. Click "Create API key" -
In the Create API dialog, give a name and click "Create API key"
-
You will see Client ID and Client Secret, which you will need in the next steps
Create an .env file in the root of your project with the following content:
OPTIMIZELY_CMS_CLIENT_ID=<the client id>
OPTIMIZELY_CMS_CLIENT_SECRET=<the client secret>Warning
Never commit your .env file with tokens to version control.
Use the command to check that the connection is correct:
npx @optimizely/cms-cli@latest login
Create a file optimizely.config.mjs in the root of your project. This configuration tells the CLI where to find your content type definitions.
Basic configuration:
import { buildConfig } from '@optimizely/cms-sdk';
export default buildConfig({
components: ['./src/components/**/*.tsx'],
});Your project structure should now look like this:
.
├── src/
│ ├── app/
│ └── components/
│ └── Article.tsx
├── public
├── .env
├── optimizely.config.mjs
└── ...
The components field accepts an array of glob patterns to locate your component files. You can use multiple patterns and negation to exclude specific files or directories.
Multiple patterns:
export default buildConfig({
components: ['./src/components/*.tsx', './src/components/**/*.tsx'],
});Excluding specific content types:
Use the ! prefix to exclude specific content types from being synced to the CMS. This is useful when you have components that define content types but shouldn't be pushed to the CMS (Like test content types).
export default buildConfig({
components: [
'./src/components/**/*.tsx',
'!./src/components/layouts/**', // Exclude layout components
'!./src/components/shared/**', // Exclude shared utility components
],
});Common exclusion patterns:
export default buildConfig({
components: [
'./src/components/**/*.tsx',
'!./src/components/internal/**', // Exclude internal-only components
'!./src/components/deprecated/**', // Exclude deprecated components
'!./src/components/Header.tsx', // Exclude specific files
],
});Negation patterns are processed in order, so place them after the inclusion patterns. The CLI uses these patterns to scan for content type definitions and display templates, then syncs only the matched files to your CMS instance.
Optional: Property Groups
Property groups help organize your content type properties in the CMS editor. Add them to your configuration if you want to group related fields together:
import { buildConfig } from '@optimizely/cms-sdk';
export default buildConfig({
components: ['./src/components/**/*.tsx'],
propertyGroups: [
{
key: 'seo',
displayName: 'SEO',
sortOrder: 1,
},
{
key: 'meta',
displayName: 'Metadata',
sortOrder: 2,
},
],
});Property group configuration:
key(required) - Unique identifier for the groupdisplayName(optional) - Name shown in the CMS editor (auto-generated from key if omitted)sortOrder(optional) - Display order (auto-assigned based on array position if omitted)
Reference these groups in your content type properties using the group field.
The CLI uses the production API endpoints by default (https://api.cms.optimizely.com). If you want to use a different domain (for example https://api.cmstest.optimizely.com), configure it using the environment variable OPTIMIZELY_CMS_API_URL:
OPTIMIZELY_CMS_API_URL=https://api.cmstest.optimizely.comNote
When connecting to a local CMS instance with self-signed certificates, add NODE_TLS_REJECT_UNAUTHORIZED="0" to your .env file to allow the CLI to establish a connection.
Read more about environment variables for the CLI
Now you are ready to start modelling your data.

