If your branch name contains special characters like slashes or dots, URL-encode them in the query parameter. For example, feature/my-branch becomes ?branch=feature%2Fmy-branch.
## Embedding
If you're documenting components outside of Storybook, you may be able to [embed interactive stories](/docs/embed). This works on many platforms that support the oEmbed specification.
## Browse library
The library screen within the Chromatic web app visualizes the latest components on a branch-by-branch basis. Browse existing components to reuse or reference. Use the branch picker to find branch-specific components.
- Identify changes by comparing historical commits and branches
- Share the library with teammates
- Browse existing components for re-use

## Demo components
Components and their stories are securely indexed each commit and branch. Use the component screen to demo components without needing to switch branches, pull code, or Git. It's your window into the metadata and variations of the component. You can also share a link to this screen to get feedback.
- **Canvas**: Interact with the real component code to reproduce the behavior
- **Snapshot**: Verify the image [snapshots](/docs/snapshots) used for cross-browser [UI Tests](/docs#test-how-uis-look--function)

---
## Review
URL: https://chromatic.com/docs/review
> Learn how to get approval and feedback on visual changes from designers, product managers, and other key stakeholders with Chromatic's UI Review workflow.
# UI Review powered by snapshots
As Chromatic's second core workflow, UI Review streamlines the process of getting approval and feedback on visual changes from designers, product managers, and other key stakeholders. While [UI Tests](/docs#test-how-uis-look--function) safeguard you from unintentional bugs, UI Review is where you discuss intentional changes with your team, ensuring everyone aligns with their expectations before you ship.
Each UI Review is linked to a pull/merge request, streamlining the workflow. Here's how it works:
- **Automated trigger:** When you open a pull request and run a Chromatic build via CI, Chromatic starts the UI Review workflow.
- **Visual diffing:** Chromatic generates a changeset highlighting the exact visual differences between your feature branch and the main branch. You can use the same diffing tools from [UI Tests](/docs#test-how-uis-look--function) to evaluate these changes.
- **Collaborative review:** Easily assign one or more reviewers to provide feedback on the visual changes.
- **Checklist for clarity:** All change requests are tracked within a convenient checklist attached to the Review.

ℹ️ You must [set up CI](/docs/ci) so that Chromatic is able to run builds for each commit on the PR branch.
## Understanding the Review
Once a Review has been created—either manually or through CI—navigate to the Reviews tab and select the appropriate Review. You will then land on the Activity tab, which shows a timeline of [builds](/docs), active discussions, and Review status. This showcases what needs to be done in the Review process.

### Invite teammates
Invite other developers, designers, PMs, and stakeholders to help review changes. This closes the feedback loop between disciplines and helps you find the answer to “does this look right?”
If you [linked your project](/docs/access#linked-projects) to GitHub, Bitbucket, or GitLab, your project permissions are synced so collaborators can sign in to review immediately. If your [project is unlinked](/docs/access#unlinked-projects), use the project invite code to add collaborators.
### Assign reviewers
Use the Assign Reviewers link on the Review’s Activity screen to choose reviewers from the project’s collaborators. Reviewers will be emailed a link to the Review screen to begin their review.

### Default reviewers
If you find you’re always assigning the same reviewers, you can set default reviewers for your project. Default reviewers will be automatically assigned to new Review. You can also assign additional reviewers on a per-Review basis.
Add default reviewers on your project’s Manage page. Go to the Review section to add a default reviewer.

Remove a default reviewer by clicking "Remove" beside their name. This will remove them as default reviewer but not from the project.
When a new Review is created, Chromatic automatically assigns the project’s default reviewers to that Review. All assigned default reviewers must approve for the Review to pass, which prevents a Review from being “solo-approved” in practice.
Default reviewers can be unassigned from a specific Review if necessary. This does not remove them as default reviewers for future Reviews.
## Review the changes
The Review screen includes a Changeset tab showing a side-by-side view of all visual changes introduced on your head branch. It compares the UI on the head branch to the base branch.

💡 **Tip:** To hint at what UI changed, toggle the highlighted diff (in neon green) on and off.
### Discussions
Reviewers can request updates to the implementation via the comment box beneath each change. Discussions are threaded and attached to the specific snapshot represented by the change.

## UI checklist
At the bottom of the Review screen’s [activity tab](/docs/review#ui-checklist) is a list of tasks that must be completed before UI is ready to be signed off on. If changes are found, the Review will enter the **🟡 Pending** state. When changes are approved and checklist items are complete, the Review will be **🟢 Passed**. Here’s how to resolve these tasks:
1. Changeset must be approved → Assign reviewers or approve yourself.
2. Outstanding discussions must be resolved → Click 'Resolve' on discussions.
3. All assigned reviewers must approve → Click 'Approve' in the Review screen tab bar.
ℹ️ Step #3 is not required if you would like to close the Review.

---
## PR check for "UI Review"

You'll get a 'UI Review' status check for each PR that shows the state of the UI Checklist. Require the check in [GitHub](https://help.github.com/en/github/administering-a-repository/enabling-required-status-checks), [GitLab](https://docs.gitlab.com/ee/api/commits.html#post-the-build-status-to-a-commit), or [Bitbucket](https://confluence.atlassian.com/bitbucket/suggest-or-require-checks-before-a-merge-856691474.html) to ensure that impactful changes are considered by the team before merging.
[**Integrate Chromatic into your CI pipeline »**](/docs/ci)
## Pull requests from forks
Chromatic supports UI Test and UI Review across forks, but there's some caveats. First, it only works with [CI integration](/docs/ci#configure-ci) configured to also build PR branches from forks. Secondly, you must expose your project token so that forks can use it. The easiest way to do that is to simply include it in in your `package.json`, for example:
```json
{
"scripts": {
"chromatic": "chromatic --project-token "
}
}
```
If you use a CI provider other than GitHub, you can still use an environment variable. Just make sure your CI is configured to also build forked branches. The project token does not grant access to the project (it can only retrieve a strict set of insensitive data), but it does allow running new builds which can use snapshots.
---
## Frequently asked questions
When should I ask for UI Review?
You can initiate a UI Review at any time. However, we recommend doing it later in the development cycle, once baselines have been approved and UI Tests are green. Learn more about [PR workflow](/docs/in-pull-request).
Can I disable UI Review if I'd prefer not to use it?
Yes. Go to the manage page for your project where you can disable UI Review. Chromatic will no longer add status checks to your PRs for UI Review once it is disabled.
What commits does Chromatic use to calculate the UI changeset?
Similar to [GitHub code review](https://github.com/features/code-review/), Chromatic compares between the latest commit on the PR branch and the 'merge base' commit, that is the commit that is the shared ancestor between the PR branch and the branch it was created from. It is important that Chromatic has run a build on both commits outlined above. If you've recently enabled CI and have existing PRs that you would like to review, ensure Chromatic has run in CI for both branches of that PR.
The process might look something like:
1. Create a new PR to `main` adding Chromatic to CI
2. Merge that PR when everything works well.
3. Update your existing feature PR(s) w/ the latest from `main` (either merge or rebase from main).
Can I prevent people from auto-approving their own Review
No, you can't prevent people from auto-approving their own review.
However, you can [assign default reviewers](/docs/review#default-reviewers) to ensure that other teammates must approve of the review. Enable [mandatory pull request checks](/docs/mandatory-pr-checks/) for UI Review to require the reviewers you assign to approve.
Are UI reviews generated for draft pull requests?
Yes, Chromatic creates UI Reviews for draft pull requests, but you can configure your CI to skip running them if you prefer.
For example, in a GitHub Actions workflow, you can add a condition to skip Chromatic for drafts:
```yaml
- name: Run Chromatic
if: github.event.pull_request.draft == false
uses: chromaui/action@v1
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
```
In GitLab, you can use a condition like:
```yaml
chromatic:
stage: test
image: node:latest
script:
- npx chromatic --project-token=$CHROMATIC_PROJECT_TOKEN
only:
- merge_requests
except:
- draft
```
---
## Access control
URL: https://chromatic.com/docs/access
> Learn how to control who has access to your Chromatic project
# Access control
Learn how to manage access to your Chromatic account and projects.
## Authentication
Sign in to Chromatic via OAuth, email, or [SSO](/docs/access/sso).
#### OAuth
Chromatic supports the cloud versions of GitHub, GitLab, or Bitbucket on our [self-serve plans](https://www.chromatic.com/pricing).
If you use the on-premise or self-managed versions of GitHub, GitLab, or Bitbucket, we can support you via our [enterprise plan](https://www.chromatic.com/pricing). We recommend trialing Chromatic first by following these [instructions](/docs/faq/chromatic-sso-on-premises-other-git).
What OAuth scopes does Chromatic request?
Depending on your Git provider, Chromatic will request a set of OAuth scopes when you first sign in. Chromatic uses these permissions to enumerate your list of repositories, set PR statuses, and retrieve users for assignment to review. Chromatic will never read/write source code.
| Git provider | OAuth Scopes |
| ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- |
| [GitHub](https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/#available-scopes) | `['user:email', 'read:user', 'read:org', 'repo:status']` |
| [GitLab](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#limiting-scopes-of-a-personal-access-token) | `['api']` |
| [Bitbucket](https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html#OAuthonBitbucketCloud-Scopes) | `['account', 'repository', 'pullrequest', 'webhook']` |
For Enterprise customers using GitHub Enterprise Server and GitLab self-managed, the same scopes are required.
What do you need to link a project to a Git provider repository?
To link a project to a Git provider repository, you need:
- Membership in the organization that owns the repository.
- Write access to the repository, via one of the following roles:
| Git provider | Role |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------- |
| [GitHub](https://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/managing-repository-roles/repository-roles-for-an-organization#repository-roles-for-organizations) | `write`, `maintain`, or `admin` |
| [GitLab](https://docs.gitlab.com/ee/user/permissions.html#project-members-permissions) | `developer`, `maintainer`, or `owner` |
| [Bitbucket](https://support.atlassian.com/bitbucket-cloud/docs/grant-repository-access-to-users-and-groups/) | `admin`, or `write` |
What permissions does the GitHub App request?
Chromatic's GitHub App enables [UI Review](/docs/review) for pull requests. We need additional permissions to access pull request information and add PR checks.
- ✅ Read access to metadata
- ✅ Read and write access to checks and pull requests
- ✅ Read access to organization members (for collaborators)
- 🔒 We do not request access to your code
ℹ️ We recommend teams create a Chromatic “bot” or IT Service Account user on your Git provider. You can grant write permissions to that account for the repositories you want to link to Chromatic projects. This way, tokens aren’t tied to an individual user. And if a token expires, it’s straightforward for anyone on the team to validate a new one.
Does Chromatic access my source code?
No, Chromatic only uses the static Storybook build or Storybook source code (if the static build is not being used). The static build refers to a static web application that is generated from your Storybook that can be hosted by any web server.
**For unlinked projects:** Chromatic does not have access to your git provider
**For linked projects:** Chromatic requests data from your git provider without accessing your source code.
For GitHub, Chromatic only has access to repository metadata and merge request information.
However, GitLab and Bitbucket don't offer repository metadata and merge request information without full API access. Therefore, Chromatic has permission to access the source code on GitLab, but it doesn't actually access it.
How do I request access from my GitHub organization admin?
Chromatic requests the minimum permissions needed to use the tool. With GitHub, we request permissions for "OAuth" and "GitHub app" respectively. This allows organizations to expand permissions incrementally as they use more features.
If your GitHub organization requires an admin to approve apps, you'll need to request access inside of Chromatic and track their status inside of GitHub (below).
1. **Chromatic OAuth app**: Enables GitHub sign-in. Track your access request [here](https://github.com/settings/connections/applications/495b5c3cb5ae140436a0).
2. **Chromatic.com app**: Enables [UI Review](/docs/review). Track your access request [here](https://github.com/apps/chromatic-com).
Does Chromatic support custom GitHub roles?
**No, Chromatic doesn't support custom GitHub roles.**
Chromatic only receives the role name from GitHub, not the specific permissions associated with it. Custom role names prevent Chromatic from accurately determining permissions.
Is my forked repository subject to access restrictions?
When you have a fork of a private organization owned repository, that forked repository is going to be subject to that organization's access restrictions. For example, `org1/my-repo` is the original repository and you fork it to `org2/my-repo`. In this situation, the original repo `org1/my-repo` would need to approve Chromatic's OAuth App on their end. Once they do, you'll be able to use the forked repo `org2/my-repo` with Chromatic.
#### Email
Email and password authentication is available on all accounts. It's a popular authentication method for [external collaborators](/docs/access/collaborators#external-collaborators) like designers, PMs, and other stakeholders.
If you're setting up Chromatic for your team, there are some boundaries to be aware of:
- Email accounts can use Chromatic as normal
- [Collaborators](/docs/access/collaborators) are manually managed
- [Pull request checks](/docs/ci#pull-request-checks) are manually setup via your CI system
We recommend signing up with email for projects that **are not** on GitHub, Bitbucket, or GitLab. For example, projects on services like Azure DevOps, AWS, etc. Read the setup instructions for these types of projects [here](/docs/faq/chromatic-sso-on-premises-other-git).
#### Single Sign-On (SSO)
Single Sign-On (SSO) is available to enterprise customers. Learn more [here](/docs/access/sso).
## Organizations
A Chromatic organization mirrors its counterpart GitHub Organization, Bitbucket Group, or GitLab Team. Open the account menu to swap between organizations or add a new organization.

## Projects
There are two types of Chromatic projects: linked and unlinked.
#### Linked projects
Linked projects are associated with a repository on GitHub, Bitbucket, or GitLab. That allows Chromatic to [sync collaborators](/docs/access/collaborators#project-collaborators), badge pull requests, get pull request metadata for [UI Review](/docs/review), and keep track of [UI Test](/docs) baselines.
By creating a linked project in Chromatic, you automatically have at your disposal:
- [Collaborators](/docs/access/collaborators) synched automatically based on your Git provider.
- The [visibility](/docs/access/collaborators#visibility) of your published Storybook will be synced with the visibility of your GitHub repository
- UI test notifications are enabled via automated webhooks for third-party integrations.
- Automated PR badging is configured automatically via [OAuth permissions](#what-permissions-does-the-github-app-request) granted by the Git provider.
- Chromatic's GitHub App provides a faster UI review process and PR metadata retrieval.
- Improved handling of [rebasing](/docs/branching-and-baselines) and squash & merge commit strategies enabled with Chromatic's GitHub App.
You can link a project during the project creation process or afterward on the project's Manage page within the Collaborators tab.
Why is my linked project showing up as unknown?
If you encounter an `` project, this means Chromatic can no longer connect it to your Git repository.
Each project syncs using one collaborator's access token. Open the project's **Manage** page » **Configure** tab to see whose token it's using. That person can sign out of Chromatic and sign back in with the Git provider to refresh it.
Anyone with Developer access or higher and a connected Git account can take over instead, by selecting **Replace with your token** on the same tab.
My token is missing or invalid
In the Project's Manage tab, you may see that your repository details couldn't be synced due to the token. This typically occurs for one of two reasons:
1. For **GitHub**, an access token is required when you first set up your project to link Chromatic to your repository. If this step wasn’t completed, the token will be missing.
2. Tokens can expire or be deleted on your Git provider’s side, which revokes their permissions.
Another team member can **replace** the token, or you can **unlink** and relink the repository to fix the issue.
If this doesn’t help, contact us at support@chromatic.com or via our in-app live chat.
If [IP restrictions](/docs/faq/allowlist-ips-for-git-providers) are set on your Git provider account but you haven’t added Chromatic’s IPs to the allowlist, the token may show as **invalid** or **missing** too. Setting the IPs will resolve this specific case.
Using a service user for tokens
Using a **dedicated service user** (or "bot user") for your Chromatic integration with git providers ensures greater stability, security, and control for your team's workflows. **Benefits:**
- Integrations won't break if an individual team member leaves the company or has their access changed, since the token isn't tied to a personal account. Access changes can lead to tokens being missing or invalid.
- It helps meet company policies that prohibit the use of personal tokens for external service integrations and comply with the principle of least privilege.
- Access is managed through a dedicated account, providing better oversight and control than when scattered personal access tokens (PATs) are used for different Chromatic projects.
Why am I getting Could not retrieve repository ID error when trying to link a repository?
If your project is part of an organization, you need to have [your access request](#how-do-i-request-access-from-my-github-organization-admin) approved by an admin at the organization level.
Approval from a repository-level admin alone will not be sufficient. The actual scopes that Chromatic requires are listed [here](#what-oauth-scopes-does-chromatic-request).
How do I migrate from one Git provider to another (e.g., GitLab → GitHub)?
**For linked accounts**
To migrate your Chromatic projects to the new Git provider:
1. Connect your user account to the new git provider via the [Profile page](https://www.chromatic.com/profile). Under “Connected accounts,” link your new git provider. Ensure that everyone on your team does the same. _Warning:_ do not disconnect the old git provider yet since you may lose access.

1. In the upper-right corner of the dashboard, open the menu and click "Add" to create a new Chromatic organization account for your new Git provider. You'll now see both accounts in that list, each linked to different Git providers.
1. Unlink all existing projects from the old Git provider through the `Manage` tab.

1. Then link all projects to repositories from the new Git provider. Note that projects will automatically move to the new Chromatic organization level account.
If you have a paid account, use our in-app chat to get in touch, or email us at support@chromatic.com to move your subscription to the new Chromatic entity.
**For unlinked accounts**
Follow steps 1, 3, and 4 from the guide above, but you don't need to create a new Chromatic organization level account.
**Important**
Connecting one Chromatic entity to multiple Git providers is not yet supported.
#### Unlinked projects
An unlinked project is perfect for teams that self-host Git or have enterprise Git providers (that aren't on Chromatic's enterprise plan). Unlinked projects still require Git; they are just not linked to a repository on GitHub, Bitbucket, or GitLab. They do not automatically [sync collaborators](/docs/access/collaborators#project-collaborators) or badge pull requests.
The characteristics of an unlinked project include:
- Your code is in a local or self-hosted repository.
- You're using an email/password account OR a personal OAuth account.
- Chromatic runs as a [CI-only](/docs/ci) job.
- Collaborators are [manually managed](/docs/access/collaborators#external-collaborators) via an invite list.
- PR badging is manually configured in your CI provider.
- Notifications are manually setup via Chromatic's [custom webhooks](/docs/custom-webhooks).
Learn how to create an unlinked project [here](/docs/faq/chromatic-sso-on-premises-other-git).
---
### Troubleshooting
How do I create an unlinked project on my existing GitHub, Bitbucket, or GitLab account?
- ❌ You can't create unlinked projects on GitHub org, Bitbucket workspace, or GitLab group connected accounts.
- ✅ You can create unlinked projects on personal GitHub, Bitbucket, or GitLab accounts.
- ✅ You can create unlinked projects on email/password accounts.
If your account is currently connected to a GitHub org, Bitbucket workspace, or GitLab group, you'll need to create a new email/password account to set up an unlinked project. Your teammates can access this account by sharing credentials (for example, with a password manager).
To share billing between an existing connected account and an email/password account, message us via in-app chat.
How do I link a project to a Git provider using my email/password account?
Email accounts are not connected to a Git provider by default. This means you can only create [unlinked projects](#unlinked-projects).
Follow these instructions to link your project to a Git provider:
1. Go to your profile (`/profile`) and connect to your Git provider.
2. Go to the project's Manage page » Collaborate tab.
3. Click to "sync collaborators with a Git repository".
This connects your Chromatic email/password account with your Git provider account, allowing you to set up a [linked project](#linked-projects).
Note: Your personal account must have access to the repository in order to connect in Chromatic. You may need to ask an administrator to grant you additional permissions.
Why am I getting an error when trying to access a GitHub SSO project that I see listed in Chromatic’s project list?
This error can occur when Chromatic isn't authorized for a GitHub organization that has SSO/SAML also configured. In order to grant access to a project, Chromatic uses that project’s token and your account’s GitHub token. During the login process for Chromatic you authenticate with GitHub and will be presented with a prompt inside of GitHub to authorize Chromatic for use in your organization.
You must click the **Authorize** button. If you don't click the **Authorize** button, but instead click the **Continue** button, you will not be able to access the project in Chromatic. If the person that set up the project previously logged into Chromatic with their GitHub credential but never authorized Chromatic for their organization, their teammates will also encounter this issue.
---
## Collaborators
URL: https://chromatic.com/docs/access/collaborators
> Learn how to add and manage collaborators
# Collaborators
Chromatic keeps track of UI feedback and tests in one place so that collaborators stays aligned without you having to do extra work.
## Permission layers
Chromatic has two separate permission layers, [organizations](#organization-collaborators) and [projects](#project-collaborators).
**Organization** roles govern account settings such as billing, and adding projects. Unless your organization uses [Teams](/docs/access/teams) on the Enterprise plan, `member` is the only organization role there is.
**Project** roles govern what you can do inside a given project — reviewing, approving, managing settings, and deleting. Project roles are Owner, Developer, Reviewer, and Viewer, and they're set per project, so you may hold different roles on different projects.
If you're looking for a permission you don't have, it's almost always a project role you need, not an organization one. See [Roles](#roles) for what each role covers.
## Organization collaborators
Manage organization collaborators via OAuth, email, or [SSO](/docs/access/sso).
#### OAuth
Chromatic mirrors access permissions with your GitHub Organization, Bitbucket Group, or GitLab Team. Users who have access to your organization will also have access to your Chromatic organization.
| Permission level | What collaborators can do |
| ---------------------- | -------------------------------------------- |
| Organization: `member` | View / change account settings, add projects |
Unless your organization uses [Teams](/docs/access/teams) on the Enterprise plan, `member` is the only organization role — see [Roles](#roles) for how it sits alongside the project roles.
Organization collaborators can manage billing and account status but may not have access to projects. You need to be a [project collaborator](#project-collaborators) to view and manage projects.
Go to your organization's Settings page to view collaborators.

> Not seeing your organization when you try to add it? See [Why doesn't my organization appear when I try to add it or link a project?](/docs/faq/org-not-appearing)
#### Email
Email and password accounts don't have the concept of organization-level collaborators. If you want other teammates to access an account, you'll need to sync the account with a [Git provider](#organization-collaborators) or share login credentials (for example, via a password manager).
However, projects _within_ an organization do support [project-level collaborators](#project-collaborators).
#### Single Sign-On (SSO) for organizations
Single Sign-On (SSO) is available to enterprise customers. Learn more [here](/docs/access/sso).
### Billing and usage
Collaborate on billing, usage, and permissions by syncing your organization with GitHub, Bitbucket, or GitLab.
For email and password accounts, the user who created the account is the only one who can sign in to manage billing. On SSO accounts and unlinked organization accounts, the Billing role is set by Chromatic — see below.
How can I give someone billing access?
If you have an unlinked organization or SSO account and need billing access for someone, email us at **support@chromatic.com** with their email address.
**Note:**
- Billing users cannot be added to Git-linked accounts. Linked accounts rely on the connected Git provider to manage permissions. Users would need org-level permissions granted within the git provider to access billing.
- Git-linked users cannot be set as Billing users for unlinked accounts. Git-linked user permissions depend on git providers.
- On SSO accounts with directory sync, roles come from your identity provider. If your IdP later changes someone's role, it overwrites the role we set, so assigning the Billing role in your IdP is the durable option.
## Project collaborators
#### OAuth
Chromatic syncs access permissions with your GitHub, Bitbucket, or GitLab repository. Users who have access to your code will also have access to your project.
| Permission level | What collaborators can do |
| ---------------- | --------------------------------------------------------------------- |
| Repo: `read` | View project, auto-assigned the [Viewer](#roles) role |
| Repo: `write` | Review and manage project, auto-assigned the [Developer](#roles) role |
If your project is hosted in Bitbucket, ensure that you and your team members have the contributor role.
Project collaborators can view and manage the project based on their [role](#roles). Go to your project's Manage page to view collaborators and assign roles.

You can add or remove a collaborator by adjusting their access in your Git repository. The permission changes in your upstream repository are mirrored downstream in Chromatic.
Manually override the mirrored permissions by adjusting collaborator [roles](#roles) or [inviting external collaborators](#external-collaborators) on an ad hoc basis.

#### Email
If you signed up via email and password, Chromatic won't have a Git repo to sync with. You'll need to manage project collaborators manually via external collaborators [below](#external-collaborators).
#### Single Sign-On (SSO) for projects
Chromatic syncs access permissions with your SSO provider. Learn more [here](/docs/access/sso).
### External collaborators
Projects can also have external collaborators. These are stakeholders like PMs, designers, and consultants who don't commit code but contribute to the sign off process. They can also be fellow developers who don't have repo access or use a different Git provider.
External collaborators are added and removed manually. Once they create an account, they'll get access to your project. There are two ways to add collaborators:
- Invite link: Share a URL with stakeholders. They are auto-assigned a `developer` role.
- Invite email: Send individual invites via email. You can fine tune roles before sending.

#### Limitations of external collaborator accounts
External collaborator accounts cannot link the project to a repository on GitHub, Bitbucket, or GitLab.
### Roles
Roles give you fine-grained control over who can do what. They belong to one of the two [permission layers](#permission-layers): the organization role and the four project roles.
Each project has a unique set of roles that are managed by the project owner. For example, you can be a "developer" in one project and a "viewer" in another.
| Role | Layer | What you can do |
| ------------------- | ------------ | -------------------------------------------------------------------------------------------------------------- |
| Member | Organization | View / change account settings and add projects. Doesn't grant access to any project's contents. |
| Owner | Project | Can manage, delete the project, and manage/assign roles to collaborators. |
| Developer (default) | Project | Can manage the project, review tests, approve PRs, and assign reviewers. Cannot assign roles to collaborators. |
| Reviewer | Project | Can leave comments, review tests, and approve PRs they're assigned to. Cannot assign others or self-approve. |
| Viewer | Project | Read-only access to the project. |
On the Enterprise plan with SSO and directory sync (SCIM), additional organization roles are available. See [Teams](/docs/access/teams#organization-roles) for the full list and what each one covers.
#### Project ownership
Projects must have at least one owner. The `owner` role is automatically assigned to the first user in a Chromatic project.
Transfer ownership by assigning another collaborator as an owner and then reassigning yourself another role.
This transfers a single project. Chromatic accounts have no owner role — see [how do I transfer account ownership to another user?](/docs/faq/transfer-ownership/)
#### View your role
Go to your project's Manage page to view your role and it's capabilities.

#### Roles for open source projects
Open source projects are viewable to all users even if they're not listed as a collaborator or have a Chromatic account. But in order to manage or review the open source project, collaborators must have explicit access and the corresponding role.
### Visibility
By default, published Storybooks on Chromatic are private. They can only be accessed by collaborators who are signed in to Chromatic and have permission to view components and builds.
However, published Storybooks for [linked projects](/docs/access#linked-projects) with public repositories will be set to public.
When you set Storybook visibility to public, it will be accessible to visitors without signing in. Anyone with a link can access. Your private information like Chromatic library, tests, settings, Git provider, and any associated metadata will remain private. A public Storybook only shares information that is contained in that Storybook.

---
### Troubleshooting
Why does my role say Member?
Member is your **organization** role, not your project role. Outside the Enterprise plan it's the only organization role there is, so seeing it doesn't mean you've been downgraded or assigned the wrong thing.
What you can do inside a project — reviewing, approving, changing settings, deleting the project — comes from your **project** role instead: Owner, Developer, Reviewer, or Viewer. Go to the project's Manage page to see which one you hold. If you need a permission you don't have, ask a project Owner to change your project role.
See [Permission layers](#permission-layers) for how the two fit together.
Why can't my teammates access a project?
Chromatic syncs permissions at the account _and_ repo level. Check that your teammates are listed as collaborators in your GitHub, GitLab, or Bitbucket repository.
If they aren't listed, please add them and try accessing the Chromatic project again (you may have to sign in again). Learn more about [access control](/docs/access).
---
## Single Sign-On (SSO)
URL: https://chromatic.com/docs/access/sso
> Configure SAML-based SSO, manage user identity matching, SCIM provisioning, and troubleshoot
# Single Sign-On (SSO)
Single Sign-On (SSO) is available to [**enterprise customers**](/pricing). It allows your team to authenticate using your corporate identity provider (IdP) and access Chromatic via a custom subdomain (e.g., `mycompany.chromatic.com`). If you don’t know the Chromatic URL for your team, ask the account or project owner or contact support via chat or [support@chromatic.com](mailto:support@chromatic.com).
## Supported SSO providers
Chromatic works with any **SAML 2.0** compliant Identity Provider, including:
- Okta
- Microsoft Entra ID (Azure AD)
- Google Workspace
- OneLogin
- PingOne
- JumpCloud
- Keycloak
- CyberArk
- Generic SAML 2.0 IdP
- Generic OIDC IdP
If your provider is not listed, contact [support@chromatic.com](mailto:support@chromatic.com) or use in-app chat to discuss compatibility.
## Logging in with SSO
Once SSO is enabled, collaborators can log in two ways:
1. **Direct subdomain link** – `https://{YOUR-SUBDOMAIN}.chromatic.com/start`
Replace `{YOUR-SUBDOMAIN}` with the subdomain assigned to your organization.
2. **IdP dashboard** – Click the Chromatic application tile in your SSO provider’s portal.
When you add or remove collaborators in your SSO provider, changes will be reflected in Chromatic automatically.
To control which projects collaborators can access, use [Teams](/docs/access/teams). Teams are synced from your identity provider’s directory groups via SCIM and can be assigned to specific projects, each with a project role.
#### Troubleshooting login issues
- Ensure your user has been provisioned to the Chromatic application within your SSO provider. Confirm your user group has the necessary permissions.
- Double-check that you are using the correct subdomain in the login URL. It must exactly match the one assigned to your organization.
- Login issues are often caused by stale cookies or cached data. Try clearing your browser’s cache and cookies or using a private/incognito window to log in.
- If your organization has enabled IP restrictions, ensure you are connected to your corporate network (e.g., via a VPN) as required by your company’s policy.
- If your organization limits access by domain and you use a different email domain than your colleagues (e.g., you’re a contractor), ask your team to issue you an email address on an approved domain or contact us to add your current domain to the company’s allow list.
## How Chromatic matches SAML users
Chromatic identifies existing users using **two methods** in order:
1. **Primary identifier** – The SAML `NameID` (or `idp_id` attribute).
This is typically a persistent, immutable user ID from your IdP.
2. **Fallback identifier** – A combination of `email`, `firstName`, and `lastName` attributes.
This requires that your IdP sends these three attributes in the SAML assertion.
#### What happens when the `NameID` (or `idp_id`) changes?
If the `NameID` changes but the `email`, `firstName`, and `lastName` remain the same, Chromatic attempts to match the user using these attributes as a fallback. If successful, the existing user account is preserved and their history and permissions remain intact.
If the `NameID` changes and any of the `email`, `firstName`, or `lastName` attributes also change, the fallback match will fail. In this case, Chromatic treats the user as a new entity and creates a new user account. This results in the loss of the user’s previous history and permissions.
If the `NameID` changes and the `email`, `firstName`, or `lastName` attributes are not mapped in the SAML assertion, the fallback mechanism has no attributes to compare. Consequently, a new user account is created, again leading to the loss of historical data and permissions.
> ✅ **Best practice:** Use a **persistent, unchanging NameID (or `idp_id` attribute)**.
#### What happens when the corporate domain changes (e.g., from @oldcompany.com to @newcompany.com)?
When planning to change user email addresses — for example, from `user@old.com` to `user@new.com` — there is a significant risk if your SAML `NameID` is set to the user’s email address because the `NameID` serves as the primary identifier, Chromatic will see both a new `NameID` (the new email) and a new email attribute. As a result, the fallback matching mechanism may fail, and a duplicate user account will be created, losing the original user’s history and permissions.
To avoid this, configure your Identity Provider (IdP) to send a persistent, immutable `NameID` that does not change. Additionally, ensure that `email`, `firstName`, and `lastName` are sent as separate SAML attributes. With this setup, even after a domain change, users will be correctly matched, preventing account duplication. Finally, contact Chromatic support to let them know about the new email (and subdomain if needed).
> ✅ **Best practice:** Change one test user’s identifier and verify they can log in to their existing Chromatic account.
How can I invite external collaborators to my SAML account?
SAML accounts do not directly support **external collaborators**. However, we have an allowlist of email domains that can access Chromatic with SSO.
We can add any email domain to the allowlist, as long as it is not a generic email address (e.g., @gmail.com or @yahoo.com). For example, if you have a contractor with an email like `person@storybook.org`, we can add `storybook.org` to the allowlist for your SAML account.
Many companies add contractors as external users by creating specific domains for them, such as `person@chromatic-ext.com`, and then adding `chromatic-ext.com` to the allowlist.
Send us the list of external collaborators via our **in-app chat** or email us at [support@chromatic.com](mailto:support@chromatic.com).
## User provisioning: JIT vs SCIM
Chromatic supports two provisioning methods for managing user accounts via **Single Sign-On (SSO)**. The first is **Just-in-Time (JIT)** provisioning, where a user account is automatically created in Chromatic the first time the user logs in via SSO—no pre‑provisioning or administrative setup is required beforehand.
The second is **SCIM** (System for Cross-domain Identity Management) provisioning, which allows users and groups to be pushed from your identity provider (IdP) to Chromatic before their first login. **SCIM** enables automated role assignment (e.g., setting permissions based on group membership) and automated de-provisioning (e.g., removing access when a user is disabled in your IdP). Directory groups pushed via SCIM become [Teams](/docs/access/teams) in Chromatic, which you can assign to specific projects.
In short, **JIT** is simpler and requires no upfront configuration but offers less control over pre‑login access, while **SCIM** provides full lifecycle management and automation at the cost of additional setup.
## Role management
SCIM allows you to manage Chromatic roles (`Owner`, `Developer`, `Reviewer`, `Viewer`) directly from your IdP. **Requirements:**
- Configure groups in your IdP that contain a `roles` or `role` attribute. Without this attribute, Chromatic won't be able to identify the correct role and will fall back to `Developer`.
- Attribute values must match exactly: `"owner"`, `"developer"`, `"reviewer"`, `"viewer"`.
**Limitation:** The role attribute sets the same role for a user across **all projects**. To grant project-specific roles, assign a SCIM-synced [team](/docs/access/teams) to individual projects in Chromatic and choose a role for each assignment.
When SCIM is not implemented or groups are not set correctly, all users are assigned the `Developer` role.
### Access control
- Users are automatically added to accounts and projects that match their **SSO subdomain** at creation time.
- Role assignment via group mapping **does not** depend on email domain.
- If your organization restricts login by email domain or has several domains, contact Chromatic support to add new domains to the allowlist.
## SSO certificate
An **SSO certificate** is an X.509 digital certificate used by your Identity Provider (IdP) to sign SAML assertions or encrypt communication between the IdP and the service provider (e.g., Chromatic). It ensures that authentication responses are authentic and haven't been tampered with.
### Change the SSO certificate
- **Preferred method:** Provide a **metadata URL** from your IdP. Chromatic can then automatically fetch and update the certificate when it changes, avoiding any manual intervention.
- **If no metadata URL is available:** Send the new certificate to [priority-support@chromatic.com](mailto:priority-support@chromatic.com) with:
- The requested change date, time, and timezone
- A PEM-encoded X.509 certificate (accepted formats: `.pem`, `.key`, `.crt`, `.cer`, `.cert`)
> ✅ **Best practice:** Manual updates require scheduling to prevent authentication downtime. Perform the change during low‑usage hours; users may need to re‑authenticate after the certificate is rotated.
---
## Frequently asked questions
Is SSO available on the Starter and Pro plans, and for free users?
No. Single Sign-on (SSO) is not available on self-serve plans like Starter or Pro, nor for free users. It's only available on Enterprise plans.
If you're interested in SSO, contact us via in-app chat or email to discuss your requirements.
How does Chromatic handle IdP‑initiated (unsolicited) SAML?
Chromatic does **not** support IdP‑initiated (unsolicited) SAML.
When you enable SSO for your organization, Chromatic creates a SAML entity for your team and provides a configuration link. Your identity provider administrator uses that link to complete the integration.
Does Chromatic support using two IdPs (for example, Okta and PingOne together)?
No. Chromatic supports only **one Identity Provider (IdP)** per Enterprise account at a time. You cannot connect both Okta and PingOne simultaneously to the same Chromatic organization.
If you need to transition from one IdP to another (e.g., migrating from PingOne to Okta), contact Chromatic support to coordinate the switch. During the migration, you can schedule a maintenance window where the old IdP is disconnected and the new one is configured. Be aware that users will need to re‑authenticate after the change.
How do I migrate from one IdP to another (e.g., from Okta to PingOne)?
Because Chromatic only allows one active IdP per account, the migration process involves creating a new account and merging your data. Here's how it works:
1. **Request migration** – Contact Chromatic support to initiate the process. Provide details about your current IdP and the new one you wish to use.
2. **New account created** – Chromatic creates a new account for your organization and generates a fresh SSO configuration link for the **new IdP**.
3. **Configure the new IdP** – Your identity administrator completes the setup using the provided configuration link. Chromatic verifies that the new IdP is properly connected and functional.
4. **Billing and apps migration** – Chromatic transfers your billing details and all apps from the old account to the new account.
5. **Delete the old account** – Once the merge is confirmed and users can successfully authenticate via the new IdP, Chromatic permanently deletes the old account.
> ⚠️ **Important considerations:**
>
> - Users will need to re‑authenticate after the migration is complete.
> - Schedule the migration during low‑usage hours to minimize disruption.
> - Ensure your new IdP sends the same persistent `NameID` (or other unique identifier) to preserve user history and permissions. If identifiers change, duplicate accounts may be created.
Contact [priority-support@chromatic.com](mailto:priority-support@chromatic.com) to start a migration.
Does Chromatic support non‑email NameID formats?
Yes. Chromatic follows SAML 2.0 standards and accepts any NameID format (e.g., persistent, transient, username, or custom identifier).
Will changing the NameID invalidate active user sessions?
Yes, most likely. Users will need to re-authenticate after the NameID format or value is changed in your IdP.
What happens if a user’s NameID changes but I have SCIM enabled?
SCIM updates the user’s identifier in Chromatic if the IdP pushes the change. However, if the NameID changes before SCIM syncs, the user may be unable to log in. Always coordinate changes carefully.
Does Chromatic support IP restrictions for SSO?
Yes. Your organization can restrict SSO logins to specific IP ranges. Refer to [this article](/docs/faq/allowlist-ips-for-git-providers).
How do I request a custom SSO subdomain?
Contact [priority-support@chromatic.com](mailto:priority-support@chromatic.com). Subdomains are usually assigned during enterprise onboarding.
Can SSO accounts be integrated with Git providers?
Yes, you can use our standard integration with GitHub, GitLab and BitBucket, or integrate with GitHub Enterprise Server or GitLab self-managed.
How do I link my project to GitHub Enterprise Server or GitLab self-managed?
For Enterprise plans, we support connecting on-premise versions of GitHub Enterprise and GitLab. Please reach out to us via Support to get access.
You also need to have some information from your Git Provider setup ready
1. The URL to your Git Provider (e.g. https://chromatic.github.com, https://gitlab.custom.com)
2. The Name of Your Repository (e.g. chromatic/ux)
3. Access Token (See docs for [GitHub](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) and [GitLab](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html))
Depending on your Git Provider, the relevant docs for creating an access token can be found below. When you create your token, please ensure that you enable the proper scopes.
| Git provider | Permission Scopes |
| ------------ | -------------------------------------------------------- |
| GitHub | `['user:email', 'read:user', 'read:org', 'repo:status']` |
| GitLab | `['api']` |
Once you have access and the prerequisite details, follow these instructions to link your project to GitHub Enterprise Server or GitLab self-managed:
1. Go to the manage (`/manage`) page for the app that you want to connect.
2. Click the Configure tab.
3. In the Connected Application section, find the "Sync project with a Git repository" area and click "Add on-prem Git Provider" to enter the details for your repository.
If your organization restricts IP addresses for git access, make sure to [add Chromatic's IP addresses to the allow list](/docs/faq/allowlist-ips-for-git-providers/#my-organization-restricts-ip-addresses-for-git-access-should-i-add-chromatic-to-the-allowlist).
---
## Teams
URL: https://chromatic.com/docs/access/teams
> Use Teams to manage which groups of users can access which projects in your Chromatic organization
# Teams
Teams are available to organizations on the [Enterprise plan](/pricing). They let you control which users can access which projects in your Chromatic organization. Instead of assigning individuals to projects one by one, you assign groups synced from your identity provider (e.g., "Engineering" or "QA") to projects, while membership is managed centrally in your identity provider.
ℹ️ Teams are not enabled by default. To turn them on for your organization, contact us via in-app chat or email [support@chromatic.com](mailto:support@chromatic.com?Subject=Enable%20Teams).
## How it works
An **organization** is the top-level container in Chromatic that holds:
- **Member:** user who belongs to the organization, each with an organization-level role.
- **Project:** app being tested.
- **Team:** group of users synced from a directory group in your identity provider (IdP). Teams are the primary mechanism for granting groups of users access to groups of projects.
## Setting up teams
Teams must be enabled for your organization by Chromatic support, and they require [SSO with directory sync (SCIM)](/docs/access/sso). Each team in Chromatic corresponds to a directory group in your identity provider (IdP), such as Okta. Teams are provisioned automatically from the directory groups your IdP pushes via SCIM; they cannot be created or edited manually in Chromatic.
When a directory group is synced via SCIM:
- The team and its name are defined by the group in your IdP.
- Membership is controlled by the IdP and is read-only in Chromatic. When a user is added to or removed from the group in your IdP, they are automatically added to or removed from the team in Chromatic.
- A directory group maps to a single team, and a team maps to a single directory group.
### Assigning teams to projects
Team-to-project assignments are managed in Chromatic. Admins can assign a team to one or more projects and choose a [project role](#project-roles) for each assignment.
To assign a team to a project:
1. Go to the project's **Manage page » Collaborate tab**.
2. Under **Teams**, click **Add team**, select the team, and choose a role.

## Roles and permissions
A team is assigned to one or more projects with a specific [project role](#project-roles). Any user who is a member of that team automatically gets that role on those projects.

### How a user's effective project role is resolved
A user can receive project access from multiple sources. The **highest role** always wins.
1. **Organization Admin:** Admins have implicit Owner access on all projects.
2. **Direct project assignment:** A role assigned to the user on the specific project.
3. **Team membership:** The role granted by any team the user belongs to that is assigned to the project. If the user is in multiple teams with different roles on the same project, the highest applies.
Roles can only be elevated through this process, never reduced. For example, if a user's direct assignment grants `developer` and a team assignment grants `owner`, the user receives `owner`.
### Organization roles
Organization roles control what a member can do at the org level.
| Role | What they can do |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Admin** | Full access to all settings, billing, SSO/SCIM configuration, team-to-project assignments, and all projects (implicit Owner on every project). Can manage members. Every organization must have at least one member with the Admin role. |
| **Member** | Standard membership. Can view organization details and member list. Project access is determined by team membership or direct assignment. |
| **Billing** | Full access to billing management (invoices, payment methods, subscription). Cannot manage teams or projects. Intended for finance team members who manage payments but don't need project access. |
| **Viewer** | Read-only at the organization level. Can view organization details and the member list, but cannot change account settings, manage billing, or add projects. Project access is determined by team membership or direct assignment. |
### Project roles
Project roles determine what a member can do within a specific project.
| Role | What they can do |
| ------------- | -------------------------------------------------------------------------------------- |
| **Owner** | Full project access: settings, token management, collaborator management, Git linking. |
| **Developer** | Run builds, approve/reject changes in UI Review, manage baselines. |
| **Reviewer** | Approve/reject changes in UI Review. Cannot run builds. |
| **Viewer** | Read-only access to builds, stories, and review status. |
| **None** | No access. The project is not visible to the user. |
## What SCIM manages vs. what you manage manually
There is a clear boundary between what your IdP automates via SCIM and what you set manually in Chromatic.
| Managed via SCIM | Managed manually in Chromatic |
| ------------------------------------------- | ------------------------------------- |
| Organization membership (who is in the org) | Team-to-project assignments and roles |
| Organization roles (Admin, Member, etc.) | Direct project member assignments |
| Team creation and naming | |
| Team membership | |
---
## Automate Chromatic with Azure
URL: https://chromatic.com/docs/azure-pipelines
> Learn how to configure Chromatic with Azure
# Automate Chromatic with Azure Pipelines
Chromatic’s automation can be included as part of your [multistage Azure Pipelines](https://docs.microsoft.com/en-us/azure/devops/pipelines/process/stages?view=azure-devops&tabs=yaml) workflow with relative ease.
## Setup
To integrate Chromatic with your existing pipeline, you'll need to add the following:
{/* prettier-ignore-start */}
```yml title="azure-pipelines.yml"
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
stages:
- stage: UI_Tests
displayName: "UI Tests"
jobs:
- job: Chromatic
variables:
npm_config_cache: $(Pipeline.Workspace)/.npm
steps:
- checkout: self
displayName: "Get Full Git History"
fetchDepth: 0
- task: UseNode@1
displayName: "Install Node.js"
inputs:
version: "24.19.0"
- task: Cache@2
displayName: "Install and cache dependencies"
inputs:
key: 'npm | "$(Agent.OS)" | package-lock.json'
restoreKeys: |
npm | "$(Agent.OS)"
path: $(npm_config_cache)
- script: npm ci
condition: ne(variables.CACHE_RESTORED, 'true')
- task: CmdLine@2
displayName: "Run Chromatic"
inputs:
script: npx chromatic
env:
CHROMATIC_PROJECT_TOKEN: $(CHROMATIC_PROJECT_TOKEN)
```
```yml title="azure-pipelines.yml"
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
stages:
- stage: UI_Tests
displayName: "UI Tests"
jobs:
- job: Playwright
displayName: "Run Playwright"
container: mcr.microsoft.com/playwright:v1.62.0-noble
steps:
- checkout: self
displayName: "Get Full Git History"
fetchDepth: 0
- task: UseNode@1
displayName: "Install Node.js"
inputs:
version: "24.19.0"
- task: Cache@2
displayName: "Install and cache dependencies"
inputs:
key: 'npm | "$(Agent.OS)" | package-lock.json'
restoreKeys: |
npm | "$(Agent.OS)"
path: $(npm_config_cache)
- script: npm ci
condition: ne(variables.CACHE_RESTORED, 'true')
- task: CmdLine@2
displayName: "Run Playwright tests"
inputs:
script: npx playwright test
env:
CI: "true"
- task: PublishPipelineArtifact@1
inputs:
# Chromatic automatically defaults to the test-results directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
targetPath: test-results
artifact: test-results
publishLocation: "pipeline"
condition: succeededOrFailed()
- job: Chromatic
dependsOn: Playwright
displayName: "Run Chromatic"
variables:
npm_config_cache: $(Pipeline.Workspace)/.npm
steps:
- checkout: self
displayName: "Get Full Git History"
fetchDepth: 0
- task: UseNode@1
displayName: "Install Node.js"
inputs:
version: "24.19.0"
- task: Cache@2
displayName: "Install and cache dependencies"
inputs:
key: 'npm | "$(Agent.OS)" | package-lock.json'
restoreKeys: |
npm | "$(Agent.OS)"
path: $(npm_config_cache)
- script: npm ci
condition: ne(variables.CACHE_RESTORED, 'true')
- task: DownloadPipelineArtifact@2
inputs:
buildType: "current"
artifactName: "test-results"
targetPath: "$(System.DefaultWorkingDirectory)/test-results"
- task: CmdLine@2
displayName: "Run Chromatic"
inputs:
script: npx chromatic --playwright
env:
CHROMATIC_PROJECT_TOKEN: $(CHROMATIC_PROJECT_TOKEN)
CHROMATIC_ARCHIVE_LOCATION: "test-results"
```
```yml title="azure-pipelines.yml"
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
stages:
- stage: UI_Tests
displayName: "UI Tests"
jobs:
- job: Cypress
displayName: "Run Cypress"
container: cypress/browsers:node-24.19.0-chrome-151.0.7922.75-1-ff-153.0.3-edge-151.0.4129.59-1
variables:
npm_config_cache: $(Pipeline.Workspace)/.npm
steps:
- checkout: self
displayName: "Get Full Git History"
fetchDepth: 0
- task: UseNode@1
displayName: "Install Node.js"
inputs:
version: "24.19.0"
- task: Cache@2
displayName: "Install and cache dependencies"
inputs:
key: 'npm | "$(Agent.OS)" | package-lock.json'
restoreKeys: |
npm | "$(Agent.OS)"
path: $(npm_config_cache)
- script: npm ci
condition: ne(variables.CACHE_RESTORED, 'true')
- task: CmdLine@2
displayName: "Run Cypress tests"
inputs:
script: |
npm run dev &
npx cypress run
env:
ELECTRON_EXTRA_LAUNCH_ARGS: --remote-debugging-port=9222
- task: PublishPipelineArtifact@1
inputs:
# Chromatic automatically defaults to the cypress/downloads directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
targetPath: cypress/downloads
artifact: test-results
publishLocation: "pipeline"
condition: succeededOrFailed()
- job: Chromatic
dependsOn: Cypress
displayName: "Run Chromatic"
variables:
npm_config_cache: $(Pipeline.Workspace)/.npm
steps:
- checkout: self
displayName: "Get Full Git History"
fetchDepth: 0
- task: UseNode@1
displayName: "Install Node.js"
inputs:
version: "24.19.0"
- task: Cache@2
displayName: "Install and cache dependencies"
inputs:
key: 'npm | "$(Agent.OS)" | package-lock.json'
restoreKeys: |
npm | "$(Agent.OS)"
path: $(npm_config_cache)
- script: npm ci
condition: ne(variables.CACHE_RESTORED, 'true')
- task: DownloadPipelineArtifact@2
inputs:
buildType: "current"
artifactName: "test-results"
targetPath: "$(System.DefaultWorkingDirectory)/cypress/downloads"
- task: CmdLine@2
displayName: "Run Chromatic"
inputs:
script: npx chromatic --cypress
env:
CHROMATIC_PROJECT_TOKEN: $(CHROMATIC_PROJECT_TOKEN)
CHROMATIC_ARCHIVE_LOCATION: "cypress/downloads"
```
{/* prettier-ignore-end */}
We recommend saving the project token as a secret environment variable named `CHROMATIC_PROJECT_TOKEN` for security reasons. In your Azure pipeline configuration, forward it using the `env` option. When the Chromatic CLI is executed, it will read the environment variable automatically without any additional flags. Refer to the official Azure [environment variables documentation](https://learn.microsoft.com/en-us/azure/devops/pipelines/process/set-secret-variables?view=azure-devops&tabs=yaml%2Cbash) to learn more about it.
### Run Chromatic on specific branches
If you need to customize your workflow to run Chromatic on specific branches, adjust your pipeline like so:
```yml title="azure-pipelines.yml"
# 👇 Event to trigger pipeline execution
trigger:
branches:
include:
- main # 👈 Filters the execution to run only on the main branch
exclude:
- example
# 👇 Configures pipeline execution on pull requests
pr:
branches:
include:
- main # 👈 Filters the execution to run only on the pull requests for the main branch
exclude:
- example
# Additional pipeline configurations
```
Read the official Azure [conditional pipeline documentation](https://docs.microsoft.com/en-us/azure/devops/pipelines/build/triggers?view=azure-devops).
Now your pipeline will only run Chromatic in the `main` branch.
### Run Chromatic on large projects
Chromatic is prepared to handle large file uploads (with a limit of 5000 files, including stories and assets). If your project exceeds this limit, we recommend adjusting your pipeline and run the `chromatic` command with the `--zip` flag to compress your build before uploading it. For example:
```yml title="azure-pipelines.yml"
# Other configurations
# Pipeline stages
stages:
- stage: UI_Tests
displayName: 'UI Tests'
# Job list
jobs:
- job: Chromatic
displayName: 'Run Chromatic'
steps:
# Other steps in the pipeline
# 👇 Adds Chromatic as a step in the pipeline
- task: CmdLine@2
displayName: 'Run Chromatic'
inputs:
# 👇 Runs Chromatic with the flag to compress the build output.
script: npx chromatic --zip
env:
CHROMATIC_PROJECT_TOKEN: $(CHROMATIC_PROJECT_TOKEN)
```
### Run Chromatic on monorepos
Chromatic can be run on monorepos that have multiple subprojects. Each subproject will need its own project token set as an environment variable.
#### Prerequisites
1. Ensure that you're in the correct working directory for the subproject.
2. Have `build-storybook` npm script in the subproject's `package.json` file OR explicitly name the script using the `--build-script-name` CLI flag and make sure the script is listed in the subproject's `package.json` file.
If you've already built your Storybook in a separate CI step, you can adjust your workflow to include the `--storybook-build-dir` CLI flag to point to the build output directory.
```yml title="azure-pipelines.yml"
# Other configurations
# Pipeline stages
stages:
- stage: UI_Tests
displayName: 'UI Tests'
# 👇 Adds Chromatic as a step in the pipeline
jobs:
# 👇 Runs Chromatic sequentially for each monorepo subproject.
- job: Chromatic_Deploy_1
displayName: 'Publish Project 1 to Chromatic'
steps:
# Other steps in the pipeline
- task: CmdLine@2
displayName: 'Publish Project 1 to Chromatic'
inputs:
script: cd packages/project_1 && npx chromatic
env:
CHROMATIC_PROJECT_TOKEN: $(CHROMATIC_PROJECT_TOKEN_1)
- job: Chromatic_Deploy_2
displayName: 'Publish Project 2 to Chromatic'
steps:
# Other steps in the pipeline
- task: CmdLine@2
displayName: 'Publish Project 2 to Chromatic'
inputs:
script: cd packages/project_2 && npx chromatic
env:
CHROMATIC_PROJECT_TOKEN: $(CHROMATIC_PROJECT_TOKEN_2)
```
Additional paralellization can be achieved when configuring your workflow to run Chromatic on multiple subprojects. Read the official Azure DevOps [documentation](https://learn.microsoft.com/en-us/azure/devops/pipelines/licensing/concurrent-jobs?view=azure-devops&tabs=ms-hosted).
### Enable TurboSnap
TurboSnap is an advanced Chromatic feature implemented to improve the build time for large projects, disabled by default once you add Chromatic to your CI environment. To enable it, you'll need to adjust your existing workflow and run the `chromatic` command with the `--only-changed` flag as follows:
```yml title="azure-pipelines.yml"
# Other configurations
# Pipeline stages
stages:
- stage: UI_Tests
displayName: 'UI Tests'
# Job list
jobs:
- job: Chromatic_Deploy
displayName: 'Run Chromatic'
steps:
# Other steps in the pipeline
# 👇 Adds Chromatic as a step in the pipeline
- task: CmdLine@2
displayName: 'Run Chromatic'
inputs:
# 👇 Enables Chromatic's TurboSnap feature.
script: npx chromatic --only-changed
env:
CHROMATIC_PROJECT_TOKEN: $(CHROMATIC_PROJECT_TOKEN)
```
TurboSnap is highly customizable and can be configured to fit your requirements. For more information, read our [documentation](/docs/turbosnap).
### Overriding Chromatic's branch detection
If your Azure pipeline includes a set of rules for branches (e.g., renames the branch, creates ephemeral, or temporary branches) it can lead to unforeseen build errors.
In this case, you can adjust your workflow and include the `--branch-name` flag. This flag overrides Chromatic's default branch detection in favor of the specified branch:
```yml title="azure-pipelines.yml"
# Other configurations
# Pipeline stages
stages:
- stage: UI_Tests
displayName: 'UI Tests'
# Job list
jobs:
- job: Chromatic
displayName: Run Chromatic
steps:
# Other steps in the pipeline
# 👇 Adds Chromatic as a step in the pipeline
- task: CmdLine@2
displayName: Run Chromatic
inputs:
# 👇 Runs Chromatic with the --branch-name flag to override the baseline branch
script: npx chromatic --branch-name=${YOUR_BRANCH}
env:
CHROMATIC_PROJECT_TOKEN: $(CHROMATIC_PROJECT_TOKEN)
```
Chromatic will now detect the correct branch and run your workflow. You can also apply this when fixing cross-fork UI comparisons.
### UI Test and UI Review
[UI Tests](/docs#test-how-uis-look--function) and [UI Review](/docs/review) rely on [branch and baseline](/docs/branching-and-baselines) detection to keep track of [snapshots](/docs/snapshots). We recommend the following configuration.
#### Command exit code for "required" checks
If you are using pull request statuses as required checks before merging, you may not want your pipeline to fail if test snapshots render without errors (but with changes). To achieve this, pass the flag `--exit-zero-on-changes` to the `chromatic` command, and your step will continue in such cases. For example:
```yml title="azure-pipelines.yml"
# Other configurations
# Pipeline stages
stages:
- stage: UI_Tests
displayName: 'UI Tests'
# Job list
jobs:
- job: Chromatic
displayName: 'Run Chromatic'
steps:
# Other steps in the pipeline
# 👇 Adds Chromatic as a step in the pipeline
- task: CmdLine@2
displayName: 'Run Chromatic'
inputs:
#👇Runs Chromatic with the flag to prevent pipeline failure
script: npx chromatic --exit-zero-on-changes
env:
CHROMATIC_PROJECT_TOKEN: $(CHROMATIC_PROJECT_TOKEN)
```
Read our [configuration reference documentation](/docs/configure#options).
When using `--exit-zero-on-changes` your pipeline execution still stop and fail if your Storybook contains stories that error. If you'd prefer Chromatic _never_ to block your pipeline, you can use `npx chromatic || true`.
#### Re-run failed builds after verifying UI test results
Builds that contain visual changes need to be [verified](/docs/quickstart#4-review-changes). They will fail if you are not using `--exit-zero-on-changes`. Once you accept all the changes, re-run the pipeline and the `Run Chromatic` step will pass.
If you deny any change, you will need to make the necessary code changes to fix the test (and thus start a new build) to get Chromatic to pass again.
#### Maintain a clean "main" branch
A clean `main` branch is a development **best practice** and **highly recommended** for Chromatic. This means testing your `main` branch to ensure builds are passing. It's important to note that baselines will not persist through branching and merging unless you test your `main` branch.
If the builds are a result of direct commits to `main`, you will need to accept changes to keep the main branch clean. If they're merged from `feature-branches`, you will need to make sure those branches are passing _before_ you merge into `main`.
#### Azure squash/rebase merge and the "main" branch
Azure's squash/rebase merge functionality creates new commits that have no association to the branch being merged. If you are already using this option, then we will automatically detect this situation and bring baselines over (see [Branching and Baselines](/docs/branching-and-baselines#how-do-baselines-get-preserved-during-squash-and-rebase-merging) for more details).
If you’re using this functionality but notice the incoming changes were not accepted as baselines in Chromatic, then you'll need to adjust the pipeline and include the `--auto-accept-changes` flag. For example:
```yml title="azure-pipelines.yml"
# Other configurations
# Pipeline stages
stages:
- stage: UI_Tests
displayName: 'UI Tests'
# Job list
jobs:
- job: Chromatic
displayName: 'Run Chromatic'
steps:
# Other steps in the pipeline
# 👇 Checks if the branch is main and runs Chromatic with the flag to accept all changes.
- task: CmdLine@2
displayName: 'Run Chromatic and auto accept changes'
condition: and(succeeded(), eq(variables['build.sourceBranch'], 'refs/heads/main'))
inputs:
script: npx chromatic --auto-accept-changes
env:
CHROMATIC_PROJECT_TOKEN: $(CHROMATIC_PROJECT_TOKEN)
# 👇 Checks if the branch is not main and runs Chromatic
- task: CmdLine@2
displayName: 'Run Chromatic'
condition: eq(variables['Build.Reason'], 'PullRequest')
inputs:
script: npx chromatic
env:
CHROMATIC_PROJECT_TOKEN: $(CHROMATIC_PROJECT_TOKEN)
```
Read our [configuration reference documentation](/docs/configure#options).
Including the `--auto-accept-changes` flag ensures all incoming changes will be accepted as baselines. Additionally, you'll maintain a clean `main` branch.
If you want to test the changes introduced by the rebased branch, you can adjust your workflow and include a new step with the `ignore-last-build-on-branch` flag. For example:
```yml title="azure-pipelines.yml"
# Other configurations
# Pipeline stages
stages:
- stage: UI_Tests
displayName: 'UI Tests'
# Job list
jobs:
- job: Chromatic
displayName: 'Run Chromatic'
steps:
# Other steps in the pipeline
# 👇 Option to skip the last build on target branch
- task: CmdLine@2
displayName: 'Run Chromatic'
inputs:
script: npx chromatic --ignore-last-build-on-branch=my-branch
env:
CHROMATIC_PROJECT_TOKEN: $(CHROMATIC_PROJECT_TOKEN)
```
Read our [configuration reference documentation](/docs/configure#options).
Including the `--ignore-last-build-on-branch` flag ensures the latest build for the specific branch is not used as a baseline.
#### Run Chromatic on external forks of open source projects
You can enable PR checks for external forks by sharing your project token where you configured the Chromatic command (often in `package.json` or in the pipeline step).
Sharing project tokens allows contributors and others to run Chromatic builds on your project, which can use snapshots. They cannot access your account, settings, or accept baselines. This can be an acceptable tradeoff for open source projects that value community contributions.
#### Skipping builds for certain branches
Sometimes you might want to skip running a build for a certain branch, but still have Chromatic mark the latest commit on that branch as "passed". Otherwise pull requests could be blocked due to required checks that remain pending. To avoid this issue, you can run `chromatic` with the `--skip` flag. This flag accepts a branch name or glob pattern.
One use case for this feature is skipping builds for branches created by a bot. For instance, Renovate automatically updates a projects dependencies. Although some dependencies can result in UI changes, you might not find it worthwhile to run Chromatic for every single dependency update. Instead, you could rely on Chromatic running against the `main` or `develop` branch.
To skip builds for `renovate` branches, use the following:
```shell
npx chromatic --skip 'renovate/**'
```
Read our [configuration reference documentation](/docs/configure#options).
To apply this to multiple branches, use an "extended glob". See the [globs guide] for details.
```shell
npx chromatic --skip '@(renovate/**|your-custom-branch/**)'
```
[globs guide]: /docs/globs
---
## Troubleshooting
Why don't Azure Pipelines fetch the complete git history even when `fetchDepth: 0` is set?
Setting `fetchDepth: 0` means "don't apply depth limits to git operations," but **it doesn't ensure the repository isn't already shallow**. The git history may be shallow for the following reasons:
1. **Initial cloning with `--depth=1`** (single commit) occurs regardless of `fetchDepth: 0`. The `fetchDepth` setting applies to subsequent fetches, not the initial clone. This typically happens when using self-hosted agents with workspace reuse.
2. **Cached shallow workspace** – if a previous pipeline used shallow cloning, the cached workspace might already be shallow. New pipelines checking out to the same workspace inherit the shallow state.
3. **Persistent shallow configuration** – the `.git/shallow` file persists in the workspace, and subsequent operations remain limited by it.
**How to resolve this:**
**1. Using `git fetch --unshallow`**
```yaml
steps:
- checkout: self
fetchDepth: 0 # Still recommended
- script: | # Fetch complete history
git fetch --unshallow
displayName: 'Fetch complete history'
```
**2. Clean workspace strategy**
```yaml
resources:
repositories:
- repository: self
fetchDepth: 0
jobs:
- job: build
workspace:
clean: all # Forces fresh clone
```
---
## Automate Chromatic with BitBucket
URL: https://chromatic.com/docs/bitbucket-pipelines
> Learn how to configure Chromatic with BitBucket Pipelines
# Automate Chromatic with BitBucket Pipelines
Chromatic’s automation can be included as part of your BitBucket pipeline workflow with relative ease.
## Setup
To integrate Chromatic with your existing pipeline, you'll need to add the following:
{/* prettier-ignore-start */}
```yml title="bitbucket-pipelines.yml"
image: node:krypton
definitions:
caches:
npm: $HOME/.npm
pipelines:
default:
- stage:
name: "UI Tests"
steps:
- step:
name: "Run Chromatic"
caches:
- npm
- node
script:
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- npm ci
- npx chromatic
```
```yml title="bitbucket-pipelines.yml"
image: node:krypton
definitions:
caches:
npm: $HOME/.npm
pipelines:
default:
- stage:
name: "UI Tests"
steps:
- step:
name: "Playwright"
image: mcr.microsoft.com/playwright:v1.62.0-noble
caches:
- npm
- node
script:
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- npm ci
- npx playwright test
artifacts:
# Chromatic automatically defaults to the test-results directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
- test-results/**
- step:
name: "Run Chromatic"
caches:
- npm
- node
script:
- npm ci
- npx chromatic --playwright
```
```yml title="bitbucket-pipelines.yml"
image: node:krypton
definitions:
caches:
npm: $HOME/.npm
cypress: $HOME/.cache/Cypress
pipelines:
default:
- stage:
name: "UI Tests"
steps:
- step:
name: "Cypress"
# Configure the ELECTRON_EXTRA_LAUNCH_ARGS environment variable in your project settings to run Cypress tests with Chromatic.
image: cypress/browsers:node-24.19.0-chrome-151.0.7922.75-1-ff-153.0.3-edge-151.0.4129.59-1
caches:
- npm
- node
- cypress
script:
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- npm ci
- npm run dev &
- npx cypress run
artifacts:
# Chromatic automatically defaults to the cypress/downloads directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
- cypress/downloads/**
- step:
name: "Run Chromatic"
caches:
- npm
- node
script:
- npm ci
- npx chromatic --cypress
```
{/* prettier-ignore-end */}
We recommend saving the project token as a secured environment variable named `CHROMATIC_PROJECT_TOKEN` for security reasons. When the Chromatic CLI is executed, it will read the stored value automatically without any additional flags or configuration. Refer to the official BitBucket [environment variables documentation](https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/) to learn more about it.
### Run Chromatic on specific branches
If you need to customize your workflow to run Chromatic on specific branches, adjust your pipeline like so:
```yml title="bitbucket-pipelines.yml"
# A sample pipeline implementation
pipelines:
default:
# Other steps in the pipeline
branches:
# 👇 The example branch will display the message in the console instead of running Chromatic.
main:
- step:
script:
- npm ci
- npx chromatic
```
Read the official BitBucket [conditional pipeline documentation](https://support.atlassian.com/bitbucket-cloud/docs/configure-bitbucket-pipelinesyml/).
Now your pipeline will only run Chromatic in the `main` branch.
### Run Chromatic on large projects
Chromatic is prepared to handle large file uploads (with a limit of 5000 files, including stories and assets). If your project exceeds this limit, we recommend adjusting your pipeline and run the `chromatic` command with the `--zip` flag to compress your build before uploading it. For example:
```yml title="bitbucket-pipelines.yml"
# A sample pipeline implementation
pipelines:
default:
# Other steps in the pipeline
# 👇 Adds Chromatic as a step in the pipeline
- step:
name: 'Run Chromatic'
# Other pipeline configuration
script:
- npm ci
# 👇 Runs Chromatic with the flag to compress the build output.
- npx chromatic --zip
```
### Run Chromatic on monorepos
Chromatic can be run on monorepos that have multiple subprojects. Each subproject will need it's own project token stored as an environment variable.
#### Prerequisites
1. Ensure that you're in the correct working directory for the subproject.
2. Have `build-storybook` npm script in the subproject's `package.json` file OR explicitly name the script using the `--build-script-name` CLI flag and make sure the script is listed in the subproject's `package.json` file.
If you've already built your Storybook in a separate CI step, you can adjust your workflow to include the `--storybook-build-dir` CLI flag to point to the build output directory.
```yml title="bitbucket-pipelines.yml"
# A sample pipeline implementation
pipelines:
default:
# Other steps in the pipeline
# 👇 Runs Chromatic sequentially for each monorepo subproject.
- step:
name: 'Publish Project 1 to Chromatic'
# Other pipeline configuration
script:
- CHROMATIC_PROJECT_TOKEN=$CHROMATIC_PROJECT_TOKEN_1
- npm ci
- cd packages/project_1
- npx chromatic
- step:
name: 'Publish Project 2 to Chromatic'
# Other pipeline configuration
script:
- CHROMATIC_PROJECT_TOKEN=$CHROMATIC_PROJECT_TOKEN_2
- npm ci
- cd packages/project_2
- npx chromatic
```
If you want to run Chromatic in parallel for each subproject, you can use this snippet below.
```yml title="bitbucket-pipelines.yml"
# A sample pipeline implementation
pipelines:
default:
# Other steps in the pipeline
# 👇 Runs Chromatic in parallel for each monorepo subproject.
- parallel:
- step:
name: 'Publish Project 1 to Chromatic'
# Other pipeline configuration
script:
- npm ci
- cd packages/project_1
- npx chromatic --project-token $CHROMATIC_PROJECT_TOKEN_1
- step:
name: 'Publish Project 2 to Chromatic'
# Other pipeline configuration
script:
- npm ci
- cd packages/project_2
- npx chromatic --project-token $CHROMATIC_PROJECT_TOKEN_2
```
### Enable TurboSnap
TurboSnap is an advanced Chromatic feature implemented to improve the build time for large projects, disabled by default once you add Chromatic to your CI environment. To enable it, you'll need to adjust your existing workflow and run the `chromatic` command with the `--only-changed` flag as follows:
```yml title="bitbucket-pipelines.yml"
# A sample pipeline implementation
pipelines:
default:
# Other steps in the pipeline
# 👇 Adds Chromatic as a step in the pipeline
- step:
name: 'Run Chromatic'
# Other pipeline configuration
script:
- npm ci
# 👇 Enables Chromatic's TurboSnap feature.
- npx chromatic --only-changed
```
TurboSnap is highly customizable and can be configured to fit your requirements. For more information, read our [documentation](/docs/turbosnap).
### UI Test and UI Review
[UI Tests](/docs#test-how-uis-look--function) and [UI Review](/docs/review) rely on [branch and baseline](/docs/branching-and-baselines) detection to keep track of [snapshots](/docs/snapshots). We recommend the following configuration.
#### Command exit code for "required" checks
If you are using pull request statuses as required checks before merging, you may not want your pipeline to fail if test snapshots render without errors (but with changes). To achieve this, pass the flag `--exit-zero-on-changes` to the `chromatic` command, and your step will continue in such cases. For example:
```yml title="bitbucket-pipelines.yml"
# A sample pipeline implementation
pipelines:
default:
# Other steps in the pipeline
# 👇 Adds Chromatic as a step in the pipeline
- step:
name: 'Run Chromatic'
# Other pipeline configuration
script:
- npm ci
# 👇 Runs Chromatic with the flag to prevent pipeline failure
- npx chromatic --exit-zero-on-changes
```
Read our [configuration reference documentation](/docs/configure#options).
When using `--exit-zero-on-changes` your pipeline execution still stop and fail if your Storybook contains stories that error. If you'd prefer Chromatic _never_ to block your pipeline, you can use `npx chromatic || true`.
#### Re-run failed builds after verifying UI test results
Builds that contain visual changes need to be [verified](/docs/quickstart#4-review-changes). They will fail if you are not using `--exit-zero-on-changes`. Once you accept all the changes, re-run the pipeline and the `Run Chromatic` step will pass.
If you deny any change, you will need to make the necessary code changes to fix the test (and thus start a new build) to get Chromatic to pass again.
#### Maintain a clean "main" branch
A clean `main` branch is a development **best practice** and **highly recommended** for Chromatic. This means testing your `main` branch to ensure builds are passing. It's important to note that baselines will not persist through branching and merging unless you test your `main` branch.
If the builds are a result of direct commits to `main`, you will need to accept changes to keep the main branch clean. If they're merged from `feature-branches`, you will need to make sure those branches are passing _before_ you merge into `main`.
#### BitBucket squash/rebase merge and the "main" branch
BitBucket's squash/rebase merge functionality creates new commits that have no association to the branch being merged. If you are already using this option, then we will automatically detect this situation and bring baselines over (see [Branching and Baselines](/docs/branching-and-baselines#how-do-baselines-get-preserved-during-squash-and-rebase-merging) for more details).
If you’re using this functionality but notice the incoming changes were not accepted as baselines in Chromatic, then you'll need to adjust the pipeline and include the `--auto-accept-changes` flag. For example:
```yml title="bitbucket-pipelines.yml"
# A sample pipeline implementation
pipelines:
default:
# 👇 Checks if the branch is main and runs Chromatic with the flag to accept all changes.
- step:
name: 'Run Chromatic and auto accept changes'
caches:
- node
script:
- npm ci
- npx chromatic --auto-accept-changes
pull-requests:
# 👇 Checks if the branch is not main and runs Chromatic
your-branch:
- step:
name: 'Run Chromatic'
script:
- npm ci
- npx chromatic
```
Read our [configuration reference documentation](/docs/configure#options).
Including the `--auto-accept-changes` flag ensures all incoming changes will be accepted as baselines. Additionally, you'll maintain a clean `main` branch.
If you want to test the changes introduced by the rebased branch, you can adjust your workflow and include a new step with the `ignore-last-build-on-branch` flag. For example:
```yml title="bitbucket-pipelines.yml"
# A sample pipeline implementation
pipelines:
default:
# Other steps in the pipeline
# 👇 Adds Chromatic as a step in the pipeline
- step:
name: 'Run Chromatic'
# Other pipeline configuration
script:
- npm ci
# 👇 Option to skip the last build on target branch
- npx chromatic --ignore-last-build-on-branch=my-branch
```
Read our [configuration reference documentation](/docs/configure#options).
Including the `--ignore-last-build-on-branch` flag ensures the latest build for the specific branch is not used as a baseline.
#### BitBucket pipelines and patch builds
If you're creating a [patch build](/docs/branching-and-baselines#what-happens-when-the-merge-base-build-isnt-found-patch-builds) in Chromatic to fix a missing pull request comparison, you'll need to adjust your existing pipeline to the following:
```yml title="bitbucket-pipelines.yml"
pipelines:
pull-requests:
# 👇 Will run as default for any branch not elsewhere defined
'**':
- step:
# 👇 Adds Chromatic as a step in the pipeline
name: 'Run Chromatic'
caches:
- node
script:
# 👇 Brings over the changes from the BitBucket repo
- git fetch origin main:main
# 👇 Option to update the build based on the changes obtained
- npm ci
- npx chromatic --patch-build=$your-branch...main
```
Including the `git` command prior to running Chromatic prevents unwanted build errors when Chromatic retrieves the information from your BitBucket repo.
This is based on how BitBucket's pipeline infrastructure handles cloning and branching. By default when the pipeline runs it will not do a full repository clone. Instead it will only fetch the current branch and omit all other existing ones.
Now you'll be able to to see the UI changeset for PRs and perform [UI Review](/docs/review) as normal.
See the following [BitBucket issue](https://community.atlassian.com/t5/Bitbucket-Pipelines-questions/pipeline-doesnt-recognize-origin-master/qaq-p/968614) for a detailed explanation.
#### Run Chromatic on external forks of open source projects
You can enable PR checks for external forks by sharing your project token where you configured the Chromatic command (often in `package.json` or in the pipeline step).
Sharing project tokens allows contributors and others to run Chromatic builds on your project, which can use snapshots. They cannot access your account, settings, or accept baselines. This can be an acceptable tradeoff for open source projects that value community contributions.
#### Skipping builds for certain branches
Sometimes you might want to skip running a build for a certain branch, but still have Chromatic mark the latest commit on that branch as "passed". Otherwise pull requests could be blocked due to required checks that remain pending. To avoid this issue, you can run `chromatic` with the `--skip` flag. This flag accepts a branch name or glob pattern.
One use case for this feature is skipping builds for branches created by a bot. For instance, Renovate automatically updates a projects dependencies. Although some dependencies can result in UI changes, you might not find it worthwhile to run Chromatic for every single dependency update. Instead, you could rely on Chromatic running against the `main` or `develop` branch.
To skip builds for `renovate` branches, use the following:
```shell
npx chromatic --skip 'renovate/**'
```
Read our [configuration reference documentation](/docs/configure#options).
To apply this to multiple branches, use an "extended glob". See the [globs guide] for details.
```shell
npx chromatic --skip '@(renovate/**|your-custom-branch/**)'
```
[globs guide]: /docs/globs
---
## Automate with CI
URL: https://chromatic.com/docs/ci
> Learn how to configure Chromatic with your continuous integration service
# Automate visual tests with CI
Configure CI to run your visual tests whenever you push code and get pull request badges to get notified about the test and review results.

## Configure CI
Before we begin, make sure you set the `CHROMATIC_PROJECT_TOKEN` environment variable (sometimes referred to as "secrets") in your CI service's configuration. Add a `chromatic` script to your `package.json` if you don't have one already, and make sure `chromatic` is listed in `devDependencies`.
{/* prettier-ignore-start */}
```json
"scripts": {
"chromatic": "chromatic --exit-zero-on-changes"
}
```
```json
"scripts": {
"chromatic": "chromatic --playwright --exit-zero-on-changes"
}
```
```json
"scripts": {
"chromatic": "chromatic --cypress --exit-zero-on-changes"
}
```
```json
"scripts": {
"chromatic": "chromatic --vitest --exit-zero-on-changes"
}
```
{/* prettier-ignore-end */}
Integrate with popular CI tools like you would any other job. Run `npm run chromatic` to start a Chromatic build. If [UI Test](/docs) or [UI Review](/docs/review) are enabled, it will return a non-zero exit code when there are changes. For example:
```yml
- run:
command: npm install # install dependencies
- run:
command: npx playwright test # run your playwright tests
- run:
command: npm run chromatic # run visual tests
```
Here's how we recommend configuring Chromatic for popular CI services:
- [GitHub Actions](/docs/github-actions)
- [GitLab Pipelines](/docs/gitlab)
- [Bitbucket Pipelines](/docs/bitbucket-pipelines)
- [CircleCI](/docs/circleci)
- [Travis CI](/docs/travisci)
- [Jenkins](/docs/jenkins)
- [Azure Pipelines](/docs/azure-pipelines)
- [Semaphore](/docs/semaphore)
- [Other CI providers](/docs/custom-ci-provider)
## Pull request checks
When a build runs it will automatically add a PR status check to the current pull request indicating the state of the build. By default, you'll see UI Tests and Storybook Publish. If you enabled UI Review you'll also see a check for it.
GitHub, Bitbucket, or GitLab projects that are [linked to a repository](/docs/access) get this feature out of the box. If you use other version control services to host your code, you can write a custom CI script to add a check for Chromatic (via your CI provider).
Require checks in [GitHub](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule#creating-a-branch-protection-rule), [GitLab](https://docs.Gitlab.com/ee/api/commits.html#post-the-build-status-to-a-commit), or [Bitbucket](https://confluence.atlassian.com/bitbucket/suggest-or-require-checks-before-a-merge-856691474.html) to ensure they are completed before merging.
[Learn how to enable mandatory Chromatic PR checks »](/docs/mandatory-pr-checks)

---
## Frequently asked questions
Is Docker supported?
Yes. Docker is supported, but there’s a caveat: the Docker image must have git installed, and the installed git version must be `≥2.28.0`. If the version is lower, Chromatic won't work correctly.
Can I hide the CI messages in the web app?
Chromatic detects CI test runs for most services. But it's not possible for every system, which results in users seeing persistent "Setup CI / Automation" messages in the UI.
If this is happening to you, prepend `CI=true` to your test command like so `CI=true yarn chromatic...` to hide the "Setup CI" messages in Chromatic. [Learn more](/docs).
Why aren't pull request checks syncing with my Git provider?
Pull/merge request checks show the status of your UI Tests and UI Review in GitHub, Bitbucket, or GitLab. If you find that your status checks are out of sync between Chromatic and your Git provider, try the solutions below.
**1. Check that your project is linked to a Git provider**
Go to your Project » Manage » Configure tab under the "Connected Applications". Then confirm that there is a repository connected to your project and that the access token is valid.
**2. Check whether commits are successfully linked to builds**
Chromatic runs builds for each commit to power UI Tests and UI Review. We expect the build commit in Chromatic to match the commit in your repository. But some CI environments and Git providers create an "ephemeral" merge commit if your feature branch is not up to date with your default base branch (master, main, develop, etc).
You can verify that you're in this situation by going to the Build page and noting the commit hash. If your project is "linked" to a Git provider, you can also click on the commit to go straight to the Git provider website. If you get a "Not Found" page indicating the commit doesn't exist then this issue applies to you.
The way to fix this is to set the Chromatic [environment variables](/docs/configure#environment-variables): `CHROMATIC_SHA`, `CHROMATIC_BRANCH`, `CHROMATIC_SLUG`. Note that you must set all three.
**3. Check if your environment variables are set correctly**
Another possibility is that your environment variables `CHROMATIC_SHA`, `CHROMATIC_BRANCH`, `CHROMATIC_SLUG` are not configured correctly.
The most likely reason is that you are pulling the incorrect value from your CI provider to set the variables or you are working on a forked repository and have not configured the variables to match the base repository.
If none of these situations apply to you, [email](mailto:support@chromatic.com) support and attach the full job that includes `chromatic` for your particular CI environment.
---
## Automate Chromatic with CircleCI
URL: https://chromatic.com/docs/circleci
> Learn how to configure Chromatic with CircleCI
# Automate Chromatic with CircleCI
Chromatic's automation can be included as part of your CircleCI job with relative ease.
## Setup
To integrate Chromatic with your existing workflow, you'll need to add the following:
{/* prettier-ignore-start */}
```yml title=".circleci/config.yml"
version: 2.1
executors:
chromatic-ui-testing:
docker:
- image: cimg/node:24.19.0
working_directory: ~/repo
jobs:
Chromatic:
executor: chromatic-ui-testing
steps:
- checkout
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package-lock.json" }}
- v1-dependencies-
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- run: npm ci
- run: npx chromatic
- save_cache:
name: Save NPM cache
paths:
- ~/.npm
key: v1-dependencies-{{ checksum "package-lock.json" }}
workflows:
UI_Tests:
jobs:
- Chromatic
```
```yml title=".circleci/config.yml"
version: 2.1
executors:
pw-noble-development:
docker:
- image: mcr.microsoft.com/playwright:v1.62.0-noble
working_directory: ~/repo
chromatic-ui-testing:
docker:
- image: cimg/node:24.19.0
working_directory: ~/repo
jobs:
Playwright:
executor: pw-noble-development
steps:
- checkout
- restore_cache:
name: Restore NPM cache
keys:
- v1-dependencies-{{ checksum "package-lock.json" }}
- v1-dependencies-
- run:
name: "Install Playwright dependencies"
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
command: npm ci
- save_cache:
name: Save NPM cache
paths:
- ~/.npm
key: v1-dependencies-{{ checksum "package-lock.json" }}
- run:
name: "Run Playwright tests"
command: npx playwright test
when: always
- store_artifacts:
# Chromatic automatically defaults to the test-results directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
path: ./test-results
- persist_to_workspace:
root: .
paths:
- test-results
Chromatic:
executor: chromatic-ui-testing
steps:
- checkout
- restore_cache:
name: Restore NPM cache
keys:
- v1-dependencies-{{ checksum "package-lock.json" }}
- v1-dependencies-
- run: npm ci
- attach_workspace:
at: .
- run:
name: "Run Chromatic"
command: npx chromatic --playwright
environment:
CHROMATIC_ARCHIVE_LOCATION: "test-results"
workflows:
UI_Tests:
jobs:
- Playwright
- Chromatic:
requires:
- Playwright
```
```yml title=".circleci/config.yml"
version: 2.1
executors:
cypress:
docker:
- image: cypress/browsers:node-24.19.0-chrome-151.0.7922.75-1-ff-153.0.3-edge-151.0.4129.59-1
working_directory: ~/repo
chromatic-ui-testing:
docker:
- image: cimg/node:24.19.0
working_directory: ~/repo
jobs:
Cypress:
executor: cypress
steps:
- checkout
- restore_cache:
name: Restore NPM cache
keys:
- v1-dependencies-{{ checksum "package-lock.json" }}
- v1-dependencies-
- run:
name: "Install Cypress dependencies"
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
command: npm ci
- save_cache:
name: Save NPM cache
paths:
- ~/.npm
- ~/.cache
key: v1-dependencies-{{ checksum "package-lock.json" }}
- run:
name: "Run development server"
command: npm run dev
background: true
- run:
name: "Run Cypress tests"
command: npx cypress run
environment:
ELECTRON_EXTRA_LAUNCH_ARGS: "--remote-debugging-port=9222"
when: always
- store_artifacts:
# Chromatic automatically defaults to the cypress/downloads directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
path: ./cypress/downloads
- persist_to_workspace:
root: .
paths:
- cypress/downloads
Chromatic:
executor: chromatic-ui-testing
steps:
- checkout
- restore_cache:
name: Restore NPM cache
keys:
- v1-dependencies-{{ checksum "package-lock.json" }}
- v1-dependencies-
- run: npm ci
- attach_workspace:
at: .
- run:
name: "Run Chromatic"
command: npx chromatic --cypress
environment:
CHROMATIC_ARCHIVE_LOCATION: "cypress/downloads"
workflows:
UI_Tests:
jobs:
- Cypress
- Chromatic:
requires:
- Cypress
```
{/* prettier-ignore-end */}
We recommend saving the project token as an environment variable named `CHROMATIC_PROJECT_TOKEN` for security reasons. When the Chromatic CLI is executed, it will read the environment variable automatically without any additional flags. Refer to the official CircleCI [environment variables documentation](https://circleci.com/docs/env-vars/) to learn more about it.
### Run Chromatic on specific branches
If you need to customize your workflow to run Chromatic on specific branches, adjust your workflow like so:
```yml title=".circleci/config.yml"
# Other required configuration
jobs:
# Other jobs implemented in the workflow
workflows:
# 👇 Adds Chromatic to the workflow
UI_Tests:
jobs:
- Chromatic:
filters: # 👈 Filters the execution to run only on the main branch
branches:
only: main
```
Read the official CircleCI [conditional job execution documentation](https://circleci.com/docs/2.0/configuration-reference/#filters).
Now Chromatic will only run in the `main` branch.
### Run Chromatic on large projects
Chromatic is prepared to handle large file uploads (with a limit of 5000 files, including stories and assets). If your project exceeds this limit, we recommend adjusting your workflow and run the `chromatic` command with the `--zip` flag to compress your build before uploading it. For example:
```yml title=".circleci/config.yml"
# Other required configuration
jobs:
# Other jobs
# 👇 Adds Chromatic as a job
Chromatic:
# Other configuration
steps:
# Other job steps
# 👇 Runs Chromatic with the flag to compress the build output.
- run: npx chromatic --zip
# Workflows here
```
### Run Chromatic on monorepos
Chromatic can be run on monorepos that have multiple subprojects. Each subproject will need it's own project token stored as an environment variable.
#### Prerequisites
1. Ensure that you're in the correct working directory for the subproject.
2. Have `build-storybook` npm script in the subproject's `package.json` file OR explicitly name the script using the `--build-script-name` CLI flag and make sure the script is listed in the subproject's `package.json` file.
If you've already built your Storybook in a separate CI step, you can adjust your workflow to include the `--storybook-build-dir` CLI flag to point to the build output directory.
```yml title=".circleci/config.yml"
# Other required configuration
jobs:
# Other jobs
# 👇 Adds Chromatic as a job
Chromatic:
# Other configuration
steps:
# Other job steps
# 👇 Runs Chromatic sequentially for each monorepo subproject.
- run:
command: cd packages/project_1 && npx chromatic
environment:
CHROMATIC_PROJECT_TOKEN: $CHROMATIC_PROJECT_TOKEN_1
- run:
command: cd packages/project_2 && npx chromatic
environment:
CHROMATIC_PROJECT_TOKEN: $CHROMATIC_PROJECT_TOKEN_2
# Workflows here
```
Additional paralellization can be achieved when configuring your workflow to run Chromatic on multiple subprojects. Read the official CircleCI [documentation](https://circleci.com/docs/parallelism-faster-jobs).
### Enable TurboSnap
TurboSnap is an advanced Chromatic feature implemented to improve the build time for large projects, disabled by default once you add Chromatic to your CI environment. To enable it, you'll need to adjust your existing workflow and run the `chromatic` command with the `--only-changed` flag as follows:
```yml title=".circleci/config.yml"
# Other required configuration
jobs:
# Other jobs
# 👇 Adds Chromatic as a job
Chromatic:
# Other configuration
steps:
# Other job steps
# 👇 Enables Chromatic's TurboSnap feature.
- run: npx chromatic --only-changed
# Workflows here
```
TurboSnap is highly customizable and can be configured to fit your requirements. For more information, read our [documentation](/docs/turbosnap).
### External Pull Requests
See this [CircleCI documentation](https://circleci.com/blog/triggering-trusted-ci-jobs-on-untrusted-forks/) for workflows related to pull requests from forked repositories.
### Advanced configuration
For a more complex workflow configuration, checkout this [Chromatic CircleCI Orb](https://circleci.com/orbs/registry/orb/wave/chromatic) made by a customer.
In there you'll find various scenarios that you can use depending on your needs.
### UI Test and UI Review
[UI Tests](/docs#test-how-uis-look--function) and [UI Review](/docs/review) rely on [branch and baseline](/docs/branching-and-baselines) detection to keep track of [snapshots](/docs/snapshots). We recommend the following configuration.
#### Command exit code for "required" checks
If you are using pull request statuses as required checks before merging, you may not want your Circle CI job to fail if test snapshots render without errors (but with changes). To achieve this, pass the flag `--exit-zero-on-changes` to the `chromatic` command, and your job will continue in such cases. For example:
```yml title=".circleci/config.yml"
# Other required configuration
jobs:
# Other jobs
# 👇 Adds Chromatic as a job
Chromatic:
# Other configuration
steps:
# Other job steps
# 👇 Runs Chromatic with the flag to prevent workflow failure
- run: npx chromatic --exit-zero-on-changes
# Workflows here
```
Read our [configuration reference documentation](/docs/configure#options).
When using `--exit-zero-on-changes` your job will still stop and fail if your Storybook contains stories that error. If you'd prefer Chromatic _never_ to block your job, you can use `npx chromatic || true`.
#### Re-run failed builds after verifying UI test results
Builds that contain visual changes need to be [verified](/docs/quickstart#4-review-changes). They will fail if you are not using `--exit-zero-on-changes`. Once you accept all the changes, re-run the workflow and the `chromatic-deployment` job will pass.
If you deny any change, you will need to make the necessary code changes to fix the test (and thus start a new build) to get Chromatic to pass again.
#### Maintain a clean "main" branch
A clean `main` branch is a development **best practice** and **highly recommended** for Chromatic. This means testing your `main` branch to ensure builds are passing. It's important to note that baselines will not persist through branching and merging unless you test your `main` branch.
If the builds are a result of direct commits to `main`, you will need to accept changes to keep the main branch clean. If they're merged from `feature-branches`, you will need to make sure those branches are passing _before_ you merge into `main`.
#### Squash/rebase merge and the "main" branch
We use GitHub, GitLab, and Bitbucket APIs respectively to detect squashing and rebasing so your baselines match your expectations no matter your Git workflow (see [Branching and Baselines](/docs/branching-and-baselines#how-do-baselines-get-preserved-during-squash-and-rebase-merging) for more details).
If you’re using this functionality but notice the incoming changes were not accepted as baselines in Chromatic, then you'll need to adjust the `chromatic` command and include the `--auto-accept-changes` flag. For example:
```shell title=".circleci/config.yml"
# Other required configuration
# 👇 Checks if the current branch is not the main and runs Chromatic
if [ "${CIRCLE_BRANCH}" != "main" ];
then
npx chromatic
else
# 👇 Checks if the current branch is main and runs Chromatic with the flag to accept all changes
npx chromatic --auto-accept-changes
fi
```
Read our [configuration reference documentation](/docs/configure#options).
Including the `--auto-accept-changes` flag ensures all incoming changes will be accepted as baselines. Additionally, you'll maintain a clean `main` branch.
If you want to test the changes introduced by the rebased branch, you can adjust your workflow and include a new step with the `ignore-last-build-on-branch` flag. For example:
```yml title=".circleci/config.yml"
# Other required configuration
jobs:
# Other jobs
# 👇 Adds Chromatic as a job
Chromatic:
# Other configuration
steps:
# Other job steps
# 👇 Option to skip the last build on target branch
- run: npx chromatic --ignore-last-build-on-branch=my-branch
# Workflows here
```
Including the `--ignore-last-build-on-branch` flag ensures the latest build for the specific branch is not used as a baseline.
#### Run Chromatic on external forks of open source projects
You can enable PR checks for external forks by sharing your project token where you configured the Chromatic command (often in `package.json` or in the pipeline step).
Sharing project tokens allows contributors and others to run Chromatic builds on your project, which can use snapshots. They cannot access your account, settings, or accept baselines. This can be an acceptable tradeoff for open source projects that value community contributions.
#### Skipping builds for certain branches
Sometimes you might want to skip running a build for a certain branch, but still have Chromatic mark the latest commit on that branch as "passed". Otherwise pull requests could be blocked due to required checks that remain pending. To avoid this issue, you can run `chromatic` with the `--skip` flag. This flag accepts a branch name or glob pattern.
One use case for this feature is skipping builds for branches created by a bot. For instance, Dependabot automatically updates a projects dependencies. Although some dependencies can result in UI changes, you might not find it worthwhile to run Chromatic for every single dependency update. Instead, you could rely on Chromatic running against the `main` or `develop` branch.
To skip builds for `dependabot` branches, use the following:
```shell
npx chromatic --skip 'dependabot/**'
```
Read our [configuration reference documentation](/docs/configure#options).
To apply this to multiple branches, use an "extended glob". See the [globs guide] for details.
```shell
npx chromatic --skip '@(renovate/**|dependabot/**)'
```
[globs guide]: /docs/globs
---
## Automate Chromatic with your custom CI provider
URL: https://chromatic.com/docs/custom-ci-provider
> Learn how to configure Chromatic with a custom provider
# Automate Chromatic with a custom provider
Chromatic automation can be included as part of any CI provider with relative ease. We're here for you. Contact us through our in-app chat for further assistance.
## Setup
To integrate Chromatic with your existing CI provider, you'll need to add the following to your workflow:
{/* prettier-ignore-start */}
```yml title="your-workflow.yml"
image: node:krypton
- run:
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
command: npm ci
- run:
command: npm test
- run:
# 👇 Publish Storybook and run visual tests in Chromatic
command: npx chromatic
```
```yml title="your-workflow.yml"
image: node:krypton
- run:
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
command: npm ci
- run:
name: "Playwright"
displayName: "Run Playwright tests"
container: mcr.microsoft.com/playwright:v1.62.0-noble
options:
artifacts:
# Chromatic automatically defaults to the test-results directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
- test-results
command: npx playwright test
- run:
name: "Chromatic"
displayName: "Run Chromatic"
requires: [Playwright]
environment:
CHROMATIC_ARCHIVE_LOCATION: "test-results"
command: npx chromatic --playwright
```
```yml title="your-workflow.yml"
image: node:krypton
- run:
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
command: npm ci
- run:
name: "Cypress"
displayName: "Run Cypress tests"
container: cypress/browsers:node-24.19.0-chrome-151.0.7922.75-1-ff-153.0.3-edge-151.0.4129.59-1
environment:
ELECTRON_EXTRA_LAUNCH_ARGS: "--remote-debugging-port=9222"
options:
artifacts:
# Chromatic automatically defaults to the cypress/downloads directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
- cypress/downloads
command:
- npm run dev &
- npx cypress run
- run:
name: "Chromatic"
displayName: "Run Chromatic"
requires: [Cypress]
environment:
CHROMATIC_ARCHIVE_LOCATION: "cypress/downloads"
command: npx chromatic --cypress
```
{/* prettier-ignore-end */}
We recommend saving the project token as a (secret) environment variable named `CHROMATIC_PROJECT_TOKEN` for security reasons. When the Chromatic CLI is executed, it will read the environment variable automatically without any additional flags. See your provider's documentation for reference.
### Run Chromatic on specific branches
Depending on the CI provider you're using, running Chromatic from a specific branch will not be a issue. Refer to your CI documentation for further details.
### Run Chromatic on large projects
Chromatic is prepared to handle large file uploads (with a limit of 5000 files, including stories and assets). If your project exceeds this limit, we recommend adjusting your workflow and run the `chromatic` command with the `--zip` flag to compress your build before uploading it. For example:
```yml title="your-workflow.yml"
- run:
# 👇 Runs Chromatic with the flag to compress the build output.
command: npx chromatic --zip
```
### Run Chromatic on monorepos
Chromatic can be run on monorepos that have multiple subprojects. Each subproject will need it's own project token stored as an environment variable.
#### Prerequisites
1. Ensure that you're in the correct working directory for the subproject.
2. Have `build-storybook` npm script in the subproject's `package.json` file OR explicitly name the script using the `--build-script-name` CLI flag and make sure the script is listed in the subproject's `package.json` file.
If you've already built your Storybook in a separate CI step, you can adjust your workflow to include the `--storybook-build-dir` CLI flag to point to the build output directory.
```yml title="your-workflow.yml"
# 👇 Runs Chromatic sequentially for each monorepo subproject.
- run:
command: cd packages/project_1 && npx chromatic
environment:
CHROMATIC_PROJECT_TOKEN: $CHROMATIC_PROJECT_TOKEN_1
- run:
command: cd packages/project_2 && npx chromatic
environment:
CHROMATIC_PROJECT_TOKEN: $CHROMATIC_PROJECT_TOKEN_2
```
If you want to run Chromatic in parallel for each subproject, you can use this snippet below.
```yml title="your-workflow.yml"
# 👇 Runs Chromatic in parallel for each monorepo subproject.
- parallel:
- run:
command: cd packages/project_1 && npx chromatic
environment:
CHROMATIC_PROJECT_TOKEN: $CHROMATIC_PROJECT_TOKEN_1
- run:
command: cd packages/project_2 && npx chromatic
environment:
CHROMATIC_PROJECT_TOKEN: $CHROMATIC_PROJECT_TOKEN_2
```
### Enable TurboSnap
TurboSnap is an advanced Chromatic feature implemented to improve the build time for large projects, disabled by default once you add Chromatic to your CI environment. To enable it, you'll need to adjust your existing workflow and run the `chromatic` command with the `--only-changed` flag as follows:
```yml title="your-workflow.yml"
- run:
# 👇 Enables Chromatic's TurboSnap feature.
command: npx chromatic --only-changed
```
TurboSnap is highly customizable and can be configured to fit your requirements. For more information, read our [documentation](/docs/turbosnap).
### Overriding Chromatic's branch detection
If your worflow includes a set of rules for branches (e.g., renames the branch, creates ephemeral, or temporary branches) it can lead to unforeseen build errors.
In this case, you can adjust your workflow and include the `--branch-name` flag. This flag overrides Chromatic's default branch detection in favor of the specified branch:
```yml title="your-workflow.yml"
- run:
# 👇 Runs the Chromatic CLI with the --branch-name flag to override the baseline branch
command: npx chromatic --branch-name=${YOUR_BRANCH}
```
Chromatic will now detect the correct branch and run your workflow. You can also apply this when fixing cross-fork UI comparisons.
### UI Test and UI Review
[UI Tests](/docs#test-how-uis-look--function) and [UI Review](/docs/review) rely on [branch and baseline](/docs/branching-and-baselines) detection to keep track of [snapshots](/docs/snapshots). We recommend the following configuration.
#### Command exit code for "required" checks
If you are using pull request statuses as required checks before merging, you may not want your build to fail if test snapshots render without errors (but with changes). To achieve this, pass the flag `--exit-zero-on-changes` to the `chromatic` command, and your job will continue in such cases. For example:
```yml title="your-workflow.yml"
# Your custom CI implementation
- run:
# 👇 Runs Chromatic with the flag to prevent stage failure
command: npx chromatic --exit-zero-on-changes
```
Read our [configuration reference documentation](/docs/configure#options).
When using `--exit-zero-on-changes` your job will still stop and fail if your Storybook contains stories that error. If you'd prefer Chromatic _never_ to block your job, you can use `npm run chromatic || true`.
#### Re-run failed builds after verifying UI test results
Builds that contain visual changes need to be [verified](/docs/quickstart#4-review-changes). They will fail if you are not using `--exit-zero-on-changes`. Once you accept all the changes, re-run the workflow and the job will pass.
If you deny any change, you will need to make the necessary code changes to fix the test (and thus start a new build) to get Chromatic to pass again.
#### Maintain a clean "main" branch
A clean `main` branch is a development **best practice** and **highly recommended** for Chromatic. This means testing your `main` branch to ensure builds are passing. It's important to note that baselines will not persist through branching and merging unless you test your `main` branch.
If the builds are a result of direct commits to `main`, you will need to accept changes to keep the main branch clean. If they're merged from `feature-branches`, you will need to make sure those branches are passing _before_ you merge into `main`.
#### Squash/rebase merge and the "main" branch
We use GitHub, GitLab, and Bitbucket APIs respectively to detect squashing and rebasing so your baselines match your expectations no matter your Git workflow (see [Branching and Baselines](/docs/branching-and-baselines#how-do-baselines-get-preserved-during-squash-and-rebase-merging) for more details).
If you’re using this functionality but notice the incoming changes were not accepted as baselines in Chromatic, then you'll need to adjust the `chromatic` command and include the `--auto-accept-changes` flag. For example:
```yml title="your-workflow.yml"
# Your custom CI implementation
- run:
# 👇 Checks if the current branch is not main and runs Chromatic
if: branch != main
command: npx chromatic
# 👇 Checks if the current branch is main and accepts all changes in Chromatic
else:
command: npx chromatic --auto-accept-changes
```
Read our [configuration reference documentation](/docs/configure#options).
Including the `--auto-accept-changes` flag ensures all incoming changes will be accepted as baselines. Additionally you'll maintain a clean `main` branch.
#### Run Chromatic on external forks of open source projects
You can enable PR checks for external forks by sharing your project token where you configured the Chromatic command (often in `package.json` or in the pipeline step).
Sharing project tokens allows contributors and others to run Chromatic builds on your project, which can use snapshots. They cannot access your account, settings, or accept baselines. This can be an acceptable tradeoff for open source projects that value community contributions.
#### Skipping builds for certain branches
Sometimes you might want to skip running a build for a certain branch, but still have Chromatic mark the latest commit on that branch as "passed". Otherwise pull requests could be blocked due to required checks that remain pending. To avoid this issue, you can run `chromatic` with the `--skip` flag. This flag accepts a branch name or glob pattern.
One use case for this feature is skipping builds for branches created by a bot. For instance, Dependabot automatically updates a projects dependencies. Although some dependencies can result in UI changes, you might not find it worthwhile to run Chromatic for every single dependency update. Instead, you could rely on Chromatic running against the `main` or `develop` branch.
To skip builds for `dependabot` branches, use the following:
```shell
npx chromatic --skip 'dependabot/**'
```
Read our [configuration reference documentation](/docs/configure#options).
To apply this to multiple branches, use an "extended glob". See the [globs guide] for details.
```shell
npx chromatic --skip '@(renovate/**|dependabot/**)'
```
[globs guide]: /docs/globs
---
## Automate Chromatic with GitHub Actions
URL: https://chromatic.com/docs/github-actions
> Learn how to configure Chromatic with GitHub Actions
# Automate Chromatic with GitHub Actions
Chromatic provides a [GitHub Action](https://github.com/marketplace/actions/publish-to-chromatic) to help you automate your visual regression tests and publish Storybook.
## Workflow setup
In your `.github/workflows` directory, create a new file called `chromatic.yml` and add the following:
{/* prettier-ignore-start */}
```yml title=".github/workflows/chromatic.yml"
name: "Chromatic"
on: push
jobs:
chromatic:
name: Run Chromatic
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-node@v7
with:
node-version: 24.19.0
- name: Install dependencies
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
run: npm ci
- name: Run Chromatic
uses: chromaui/action@latest
with:
# ⚠️ Make sure to configure a `CHROMATIC_PROJECT_TOKEN` repository secret
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
```
```yaml title=".github/workflows/chromatic.yml"
name: "Chromatic"
on: push
jobs:
playwright:
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.62.0-noble
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-node@v7
with:
node-version: 24.19.0
- name: Install dependencies
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
run: npm ci
- name: Run Playwright tests
run: npx playwright test
env:
HOME: /root
- uses: actions/upload-artifact@v7
if: always()
with:
# Chromatic automatically defaults to the test-results directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
name: test-results
path: ./test-results
retention-days: 30
chromatic:
name: Run Chromatic
needs: playwright
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-node@v7
with:
node-version: 24.19.0
- name: Install dependencies
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
run: npm ci
- name: Download Playwright test results
uses: actions/download-artifact@v8
with:
name: test-results
path: ./test-results
- name: Run Chromatic
uses: chromaui/action@latest
with:
# ⚠️ Enable Playwright
playwright: true
# ⚠️ Make sure to configure a `CHROMATIC_PROJECT_TOKEN` repository secret
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
# ⚠️ Optionally configure the archive location with env vars
env: CHROMATIC_ARCHIVE_LOCATION=./test-results
```
```yaml title=".github/workflows/chromatic.yml"
name: "Chromatic"
on: push
jobs:
cypress:
name: Run Cypress
runs-on: ubuntu-latest
container:
image: cypress/browsers:node-24.19.0-chrome-151.0.7922.75-1-ff-153.0.3-edge-151.0.4129.59-1
options: --user 1001
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-node@v7
with:
node-version: 24.19.0
- name: Install dependencies
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
run: npm ci
- name: Run Cypress tests
uses: cypress-io/github-action@v7
env:
ELECTRON_EXTRA_LAUNCH_ARGS: "--remote-debugging-port=9222"
with:
start: npm run dev
- uses: actions/upload-artifact@v7
with:
# Chromatic automatically defaults to the cypress/downloads directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
name: test-results
path: ./cypress/downloads
retention-days: 30
chromatic:
name: Run Chromatic
needs: cypress
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-node@v7
with:
node-version: 24.19.0
- name: Install dependencies
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
run: npm ci
- name: Download Cypress test results
uses: actions/download-artifact@v8
with:
name: test-results
path: ./cypress/downloads
- name: Run Chromatic
uses: chromaui/action@latest
with:
# ⚠️ Enable Cypress
cypress: true
# ⚠️ Make sure to configure a `CHROMATIC_PROJECT_TOKEN` repository secret
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
# ⚠️ Optionally configure the archive location with env vars
env:
CHROMATIC_ARCHIVE_LOCATION: ./cypress/downloads
```
{/* prettier-ignore-end */}
This is a fairly basic setup. More advanced options are explained below.
### Project token secret
To securely provide the projectToken to Chromatic, you must configure a GitHub repository secret. First, find your project on Chromatic.com and go to **Manage** and then **Configure**. Copy the project token.

On GitHub, go to the **Settings** tab on your repository. Under **Security**, find **Secrets and variables** and then **Actions**. Click **New repository secret**.

Set `CHROMATIC_PROJECT_TOKEN` as the **Name** and paste the project token as the **Secret**. Click **Add secret** to save the value.
Read the official [GitHub secrets documentation](https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets).
### Forked repositories
GitHub secrets work at a repository level. Forked repositories will not have access to them. If you want to run Chromatic on cross-repository (forked) PRs, you'll have to expose the `projectToken` by including it as plaintext in your `chromatic.yml` workflow file. Be aware that anyone with access to this file will be able to run Chromatic builds on your project, which can use snapshots. You can reset the project token on the Manage > Configure screen at any time if you think it may have been compromised.
### Pinning the CLI version
While the CLI follows [semantic versioning](https://semver.org/), the GitHub Action typically auto-upgrades to the latest version. However, it's possible to pin the CLI version by changing the tag:
- To automatically receive all new updates, use `chromaui/action@latest` (the default).
- To automatically receive new features and bugfixes but avoid breaking changes, use `chromaui/action@vX` where `vX` is a major version number (e.g. `v10`).
- To not receive any updates but pin the action to a specific CLI version, use `chromaui/action@vX.Y.Z` where `vX.Y.Z` is a full semver version (e.g. `v10.0.0`).
The full list of tags is [available on GitHub](https://github.com/chromaui/action/tags).
## Configuration
For more information on the available options, refer to our [configuration reference documentation](/docs/configure#options).
### Outputs
Chromatic's GitHub Action returns some information about your build in the form of outputs. The table below lists what's currently available. Read the official [GitHub documentation](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#onworkflow_calloutputs) for more information about outputs.
| Name | Type | Description |
| -------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------- |
| **url** | `string` | An alias for the build URL.
`https://www.chromatic.com/build?appId=example-app-id&number=100` |
| **buildUrl** | `string` | The build URL.
`https://www.chromatic.com/build?appId=example-app-id&number=100` |
| **storybookUrl** | `string` | The Storybook preview URL for your current branch / Pull Request.
`https://main--example-app-id.chromatic.com` |
| **code** | `string` | The exit code for the current run of the Chromatic [CLI](/docs/cli#exit-codes). |
| **actualCaptureCount** | `number` | The number of captured snapshots. |
| **changeCount** | `number` | The number of tests with visual changes, including any inherited changes (e.g., due to [TurboSnap]). |
| **componentCount** | `number` | The number of components in the published Storybook. |
| **errorCount** | `number` | The number of tests with error(s), including any inherited errors (e.g., due to [TurboSnap]). |
| **inheritedCaptureCount** | `number` | The number of inherited (not captured) snapshots (e.g., due to [TurboSnap]). |
| **interactionTestFailuresCount** | `number` | The number of stories with interaction test failures. |
| **specCount** | `number` | The number of stories in the published Storybook. |
| **testCount** | `number` | The number of tests on the build. |
### Run Chromatic on specific branches
If you need to customize your workflow to run Chromatic on specific branches, adjust your workflow like so:
```yml title=".github/workflows/chromatic.yml"
name: 'Chromatic'
# 👇 Workflow event to trigger execution
on:
push:
branches-ignore:
- 'example' # 👈 Excludes the example branch
```
Read the official [GitHub branch workflow documentation](https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#example-ignoring-branches-and-tags).
Now Chromatic will run for any branch except `example`.
Other branches, such as the ones created by the Renovate bot, can also be included.
### Run Chromatic on large projects
Chromatic is prepared to handle large file uploads (with a limit of 5000 files, including stories and assets). If your project exceeds this limit, we recommend enabling the `zip` option in your workflow to compress your build before uploading it. For example:
```yml title=".github/workflows/chromatic.yml"
jobs:
chromatic:
steps:
# ... other steps
- uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
# 👇 Runs Chromatic with the option to compress the build output.
zip: true
```
### Run Chromatic on monorepos
Chromatic can be run on monorepos that have multiple subprojects. Each subproject will need its project token.
#### Prerequisites
1. Ensure that you're in the correct working directory for the subproject.
2. Have the `build-storybook` npm script in the subproject's `package.json` file OR explicitly name the script using the `buildScriptName` parameter and ensure the script is listed in the subproject's `package.json` file.
If you've already built your Storybook in a separate CI step, you can alternatively point the action at the build output using the `storybookBuildDir` parameter.
```yml title=".github/workflows/chromatic.yml"
jobs:
chromatic:
runs-on: ubuntu-latest
steps:
# ... other steps
- name: Publish Project 1 to Chromatic
uses: chromaui/action@latest
with:
# 👇 Chromatic projectToken, refer to the manage page to obtain it.
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN_1 }}
workingDir: packages/project_1
- name: Publish Project 2 to Chromatic
uses: chromaui/action@latest
with:
# 👇 Chromatic projectToken, refer to the manage page to obtain it.
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN_2 }}
workingDir: packages/project_2
```
If you want to run Chromatic in parallel for each subproject, you will need to create separate workflow files.
```yml title=".github/workflows/chromatic-1.yml"
# 👇 Customize the workflow name
name: 'Chromatic 1'
on: push
jobs:
chromatic:
steps:
# ... other steps
- name: Run Chromatic
uses: chromaui/action@latest
with:
# 👇 Chromatic projectToken, refer to the manage page to obtain it.
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN_1 }}
workingDir: packages/project_1
```
```yml title=".github/workflows/chromatic-2.yml"
# 👇 Customize the workflow name
name: 'Chromatic 2'
on: push
# List of jobs
jobs:
chromatic:
steps:
# ... other steps
- name: Run Chromatic
uses: chromaui/action@latest
with:
# 👇 Chromatic projectToken, refer to the manage page to obtain it.
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN_2 }}
workingDir: packages/project_2
```
### Enable TurboSnap
TurboSnap is an advanced Chromatic feature implemented to improve the build time for large projects. By default, it is disabled in your CI environment. To enable it, add the `onlyChanged` option to the workflow as follows:
```yml title=".github/workflows/chromatic.yml"
jobs:
chromatic:
steps:
# ... other steps
- name: Run Chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
onlyChanged: true # 👈 Required option to enable TurboSnap
```
TurboSnap is highly customizable and can be configured to fit your requirements. For more information, read our [documentation](/docs/turbosnap).
#### Trigger full rebuilds
By default, TurboSnap relies on Webpack's dependency graph to determine which files changes since the last build. If you're working with files processed outside the scope of Webpack (e.g., fonts, images, CSS, external libraries), you can use the `externals` option to tell Chromatic to rebuild the entire project when a file matching the pattern is changed. For example:
```yml title=".github/workflows/chromatic.yml"
# Other necessary configuration
jobs:
chromatic:
steps:
# ... other steps
- name: Run Chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
onlyChanged: true # 👈 Required option to enable TurboSnap
externals: packages/(icons/icons|tokens/src)/**
```
Multiple file patterns can also be provided as follows:
```yml title=".github/workflows/chromatic.yml"
# ... other config
- name: Run Chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
onlyChanged: true # 👈 Required option to enable TurboSnap
externals: |
*.sass
public/**
```
The `externals` option also accept additional glob patterns defined via [picomatch](https://github.com/micromatch/picomatch?tab=readme-ov-file#globbing-features). See the [globs guide] for more info.
### Support for environment variables
Environment variables are supported in Chromatic. You can use them to customize your workflow execution or provide project-related variables (e.g., API URLs). Add the `env` key in the workflow file and provide the necessary variables to enable them. For example:
```yml title=".github/workflows/chromatic.yml"
jobs:
chromatic:
steps:
# ... other steps
- uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
env:
# 👇 Sets environment variables
CHROMATIC_RETRIES: 5
LOG_LEVEL: 'error'
```
For more information on the environment variables supported by Chromatic, refer to our [configuration reference documentation](/docs/configure#environment-variables).
It comes with a caveat if you need to provide project-specific environment variables. We recommend that you prefix each variable with the `STORYBOOK` keyword and adjust your workflow to the following:
```yml title=".github/workflows/chromatic.yml"
jobs:
chromatic:
steps:
# ... other steps
- uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
env:
# 👇 Sets the environment variable
STORYBOOK_SOME_ENV_VAR: ${{ secrets.STORYBOOK_SOME_ENV_VAR }}
```
Read the official [Storybook environment variable's documentation](https://storybook.js.org/docs/configure/environment-variables).
### Fail workflow if changes are found
If you are using pull request statuses as required checks before merging, you may want your workflow step to fail if test snapshots show changes. By default, Chromatic exits with code `0` if changes are detected. We expect users to review these changes and decide whether to accept or reject them. However, if you prefer the workflow to fail when changes are found, you can use the `exitZeroOnChanges` option. For example:
```yml title=".github/workflows/chromatic.yml"
# Other necessary configuration
jobs:
chromatic:
steps:
# ... other steps
- name: Run Chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
exitZeroOnChanges: false # 👈 Fail workflow if changes are found
```
Read about the [available options](/docs/configure#options).
#### Re-run failed builds after verifying UI test results
Builds that contain visual changes need to be [verified](/docs/quickstart#4-review-changes). The task will fail if `exitZeroOnChanges` option is set to false. Once you accept all the changes, re-run the workflow, and the `chromatic` job will pass.
If you deny any change, you will need to make the necessary code changes to fix the test (and thus start a new run) to get Chromatic to pass again.
### Recommended configuration for build events
GitHub's Actions, like other CI systems, can run based on any type of event. Our recommendation is to run Chromatic's step on `push` events.
While the `pull_request` event also works, it can cause Chromatic's baselines to be lost in certain scenarios or cause Chromatic to use an unexpected baseline from the `main` branch.
GitHub allows workflows to execute on commits pushed to a branch in a pull request or on "merge" commits between that branch and the base branch (main). These merge commits do not persist in your repository's history. When a GitHub action is triggered on `pull_request`, GitHub creates an ephemeral branch and merges the PR branch into the latest from `main`. For details, refer to the [pull request workflow docs](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request) to understand what `GITHUB_SHA` and `GITHUB_REF` are set to.
This means the latest build on main will be an ancestor of this ephemeral branch, even though it is not an ancestor of the actual PR branch. Therefore, it'll use the incorrect baseline for comparison. That's why we recommend running Chromatic using the `push` event.
If you decide to use the `pull_request` event, we recommend creating a separate workflow for Chromatic using the following strategy for the checkout step:
```yml
- uses: actions/checkout@v7
with:
fetch-depth: 0
# 👇 Tells the checkout which commit hash to reference
ref: ${{ github.event.pull_request.head.ref }}
env:
CHROMATIC_BRANCH: ${{ github.event.pull_request.head.ref || github.ref_name }}
CHROMATIC_SHA: ${{ github.event.pull_request.head.sha || github.ref }}
CHROMATIC_SLUG: ${{ github.repository }}
```
**NOTE:** The `ref` on the checkout step is required for TurboSnap to correctly detect changed files.
The pull_request event makes an ephemeral commit between latest main and the commit you have created.
This means our git diff will include everything that's happened on main since you branched. That's what the ref solution solves for.
Here is the scenario:

What's happened:
The user creates `P` off `A (main)` with 2 files changed.
When the GitHub Action runs on the pull_request event, by default it creates a new merge commit `P'`.
When we take the git diff between `P'` and the baseline from `main (A)` we are not going to just get the changes in `P` but also all the changes in `B`, `C` and `D`.
### UI Test and UI Review
[UI Tests](/docs#test-how-uis-look--function) and [UI Review](/docs/review) rely on [branch and baseline](/docs/branching-and-baselines) detection to keep track of [snapshots](/docs/snapshots). We recommend the following configuration.
#### Maintain a clean "main" branch
A clean `main` branch is a development **best practice** and **highly recommended** for Chromatic. This means testing your `main` branch to ensure builds are passing. It's important to note that baselines will not persist through branching and merging unless you test your `main` branch.
If the builds result from direct commits to `main`, you must accept changes to keep the main branch clean. If they're merged from `feature-branches`, you must ensure those branches are passing _before_ you merge into `main`.
#### GitHub squash/rebase merge and the "main" branch
GitHub's squash/rebase merge functionality creates new commits that have no association with the branch being merged. If you've enabled our GitHub application in the [UI Review](/docs/review) workflow, then we will automatically detect this situation and bring baselines over (see [Branching and Baselines](/docs/branching-and-baselines#how-do-baselines-get-preserved-during-squash-and-rebase-merging) for more details).
If you’re using this functionality but notice the incoming changes were not accepted as baselines in Chromatic, then you'll need to adjust the workflow to include a new step with the `autoAcceptChanges` option. For example:
```yml title=".github/workflows/chromatic.yml"
jobs:
chromatic:
steps:
# ... other steps
- name: Run Chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
autoAcceptChanges: 'main' # 👈 Option to accept all changes on main
```
Read about the [available options](/docs/configure#options).
Including the `autoAcceptChanges` option ensures all incoming changes will be accepted as baselines. Additionally, you'll maintain a clean `main` branch.
If you want to test the changes introduced by the rebased branch, you can adjust your workflow and include a new step with the `ignoreLastBuildOnBranch` option. For example:
```yml title=".github/workflows/chromatic.yml"
jobs:
chromatic:
steps:
# ... other steps
- name: Run Chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
ignoreLastBuildOnBranch: 'my-branch' # 👈 Option to ignore the last build on target branch
```
Read about the [available options](/docs/configure#options).
Including the `ignoreLastBuildOnBranch` option ensures the latest build for the specific branch is not used as a baseline.
#### Run Chromatic on external forks of open source projects
You can enable PR checks for external forks by sharing your project token where you configured the Chromatic command (often in `package.json` or in the pipeline step).
Sharing project tokens allows contributors and others to run Chromatic builds on your project, which can use snapshots. They cannot access your account, settings, or accept baselines. This can be an acceptable tradeoff for open source projects that value community contributions.
#### Skipping builds for certain branches
Sometimes you might want to skip running a build for a certain branch but still have Chromatic mark the latest commit on that branch as "passed". Otherwise, pull requests could be blocked due to required checks that remain pending. To avoid this issue, you can run `chromatic` with the `--skip` flag. This flag accepts a branch name or glob pattern.
For instance, Dependabot automatically updates the dependencies of a project. Although some dependencies can result in UI changes, you might not find it worthwhile to run Chromatic for every dependency update. Instead, you could rely on Chromatic running against the `main` or `develop` branch. One use case for this feature is skipping builds for branches created by a bot.
To skip builds for `dependabot` branches, use the following:
```yml title=".github/workflows/chromatic.yml"
jobs:
chromatic:
steps:
# ... other steps
- name: Run Chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
skip: 'dependabot/**' # 👈 Option to skip Chromatic for certain branches
```
To apply this to multiple branches, use an "extended glob". See the [globs guide] for details.
```yml
skip: '@(renovate/**|dependabot/**)'
```
Read about the [available options](/docs/configure#options).
[globs guide]: /docs/globs
[TurboSnap]: /docs/turbosnap
---
## Automate Chromatic with GitLab
URL: https://chromatic.com/docs/gitlab
> Learn how to configure Chromatic with GitLab
# Automate Chromatic with GitLab Pipelines
Chromatic’s automation can be included as part of your GitLab pipeline workflow with relative ease.
## Setup
To integrate Chromatic with your existing pipeline, you'll need to add the following:
{/* prettier-ignore-start */}
```yml title=".gitlab-ci.yml"
image: node:krypton
stages:
- UI_Tests
cache:
key: $CI_COMMIT_REF_SLUG-$CI_PROJECT_DIR
paths:
- .npm/
before_script:
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- npm ci
Chromatic:
stage: UI_Tests
script:
- npx chromatic
```
```yml title=".gitlab-ci.yml"
image: node:krypton
stages:
- UI_Tests
cache:
key: $CI_COMMIT_REF_SLUG-$CI_PROJECT_DIR
paths:
- .npm/
before_script:
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- npm ci
Playwright:
stage: UI_Tests
needs: []
image: mcr.microsoft.com/playwright:v1.62.0-noble
script:
- npx playwright test
allow_failure: true
artifacts:
when: always
paths:
# Chromatic automatically defaults to the test-results directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
- "test-results/"
expire_in: 4 weeks
Chromatic:
stage: UI_Tests
needs: [Playwright]
variables:
CHROMATIC_ARCHIVE_LOCATION: "test-results/"
script:
- npx chromatic --playwright
```
```yml title=".gitlab-ci.yml"
image: node:krypton
stages:
- UI_Tests
cache:
key: $CI_COMMIT_REF_SLUG-$CI_PROJECT_DIR
paths:
- .npm/
- cache/Cypress
before_script:
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- npm ci
Cypress:
stage: UI_Tests
needs: []
image: cypress/browsers:node-24.19.0-chrome-151.0.7922.75-1-ff-153.0.3-edge-151.0.4129.59-1
variables:
ELECTRON_EXTRA_LAUNCH_ARGS: "--remote-debugging-port=9222"
script:
- npm run dev &
- npx cypress run
allow_failure: true
artifacts:
when: always
paths:
# Chromatic automatically defaults to the cypress/downloads directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
- "cypress/downloads/"
expire_in: 4 weeks
Chromatic:
stage: UI_Tests
needs: [Cypress]
variables:
CHROMATIC_ARCHIVE_LOCATION: "cypress/downloads/"
script:
- npx chromatic --cypress
```
{/* prettier-ignore-end */}
We recommend saving the project token as a masked environment variable named `CHROMATIC_PROJECT_TOKEN` for security reasons. When the Chromatic CLI is executed, it will read the environment variable automatically without any additional flags. Refer to the official GitLab [environment variables documentation](https://docs.gitlab.com/ee/ci/variables/index.html#mask-a-cicd-variable) to learn more about it.
### Performance optimization
To improve the performance of your pipeline, you can use the [interruptible](https://docs.gitlab.com/ee/ci/yaml/#interruptible) option if a job should be canceled when a newer pipeline starts before the job completes. This is the recommended strategy as the external status checks won't update by default, even if you create a new build for the same branch.
This keyword has no effect if [automatic cancellation of redundant pipelines](https://docs.gitlab.com/ee/ci/pipelines/settings.html#auto-cancel-redundant-pipelines) is disabled. When enabled, a running job with `interruptible: true` is canceled when starting a pipeline for a new change on the same branch.
```yml title=".gitlab-ci.yml"
image: node:krypton
stages:
- UI_Tests
cache:
key: $CI_COMMIT_REF_SLUG-$CI_PROJECT_DIR
paths:
- .npm/
before_script:
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- npm ci
Chromatic:
stage: UI_Tests
script:
- npx chromatic
# The external Chromatic status checks won't be canceled when a newer pipeline starts before the job completes saving you build minutes
# You may get an increase in the number of builds, but they won't cancel each other.
interruptible: true
```
### Run Chromatic on specific branches
If you need to customize your workflow to run Chromatic on specific branches, adjust your pipeline like so:
```yml title=".gitlab-ci.yml"
# Additional pipeline configurations
# Sets the stages for the pipeline
stages:
- UI_Tests
# 👇 Adds Chromatic as a job
Chromatic:
stage: UI_Tests
script:
- npx chromatic
#👇Filters the execution to run only on the main branch.
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: always
```
Read the official GitLab [conditional pipeline documentation](https://docs.gitlab.com/ee/ci/yaml/#rules).
Now your pipeline will only run Chromatic in the `main` branch.
### Run Chromatic on large projects
Chromatic is prepared to handle large file uploads (with a limit of 5000 files, including stories and assets). If your project exceeds this limit, we recommend adjusting your pipeline and run the `chromatic` command with the `--zip` flag to compress your build before uploading it. For example:
```yml title=".gitlab-ci.yml"
# Additional pipeline configurations
# Sets the stages for the pipeline
stages:
- UI_Tests
# 👇 Adds Chromatic as a job
Chromatic:
stage: UI_Tests
# 👇 Runs Chromatic with the flag to compress the build output.
script:
- npx chromatic --zip
```
### Run Chromatic on monorepos
Chromatic can be run on monorepos that have multiple subprojects. Each subproject will need it's own project token.
#### Prerequisites
1. Ensure that you're in the correct working directory for the subproject.
2. Have `build-storybook` npm script in the subproject's `package.json` file OR explicitly name the script using the `--build-script-name` CLI flag and make sure the script is listed in the subproject's `package.json` file.
If you've already built your Storybook in a separate CI step, you can adjust your workflow to include the `--storybook-build-dir` CLI flag to point to the build output directory.
```yml title=".gitlab-ci.yml"
# Additional pipeline configurations
# Sets the stages for the pipeline
stages:
- UI_Tests
# 👇 Runs Chromatic in parallel for each monorepo subproject.
Chromatic_publish_project_1:
stage: UI_Tests
before_script:
# Other steps
- cd packages/project_1
script:
- npx chromatic
variables:
CHROMATIC_PROJECT_TOKEN: $CHROMATIC_PROJECT_TOKEN_1
chromatic_publish_project_2:
stage: UI_Tests
before_script:
# Other steps
- cd packages/project_2
script:
- npx chromatic
variables:
CHROMATIC_PROJECT_TOKEN: $CHROMATIC_PROJECT_TOKEN_2
```
Additional paralellization can be achieved when configuring your workflow to run Chromatic on multiple subprojects. Read the official GitLab [documentation](https://docs.gitlab.com/ee/ci/jobs/job_control.html#parallelize-large-jobs).
### Disable Shallow Cloning
GitLab performs a shallow clone by default, which can lead to required patch builds depending on how frequently you run builds between commits. In order to avoid this, adjust your workflow to include a `GIT_DEPTH` of `0`. This ensures Chromatic can fetch your entire git history, without having to adjust your general `Git strategy` settings within GitLab:
```yml title=".gitlab-ci.yml"
# Additional pipeline configurations
# 👇 Sets the depth to fetch all git history
variables:
GIT_DEPTH: 0
```
### Enable TurboSnap
TurboSnap is an advanced Chromatic feature implemented to improve the build time for large projects, disabled by default once you add Chromatic to your CI environment. To enable it, you'll need to adjust your existing workflow and run the `chromatic` command with the `--only-changed` flag as follows:
```yml title=".gitlab-ci.yml"
# Additional pipeline configurations
# Sets the stages for the pipeline
stages:
- UI_Tests
# 👇 Adds Chromatic as a job
Chromatic:
stage: UI_Tests
# 👇 Enables Chromatic's TurboSnap feature.
script:
- npx chromatic --only-changed
```
TurboSnap is highly customizable and can be configured to fit your requirements. For more information, read our [documentation](/docs/turbosnap).
### UI Test and UI Review
[UI Tests](/docs#test-how-uis-look--function) and [UI Review](/docs/review) rely on [branch and baseline](/docs/branching-and-baselines) detection to keep track of [snapshots](/docs/snapshots). We recommend the following configuration.
#### Command exit code for "required" checks
If you are using pull request statuses as required checks before merging, you may not want your pipeline to fail if test snapshots render without errors (but with changes). To achieve this, pass the flag `--exit-zero-on-changes` to the `chromatic` command, and your step will continue in such cases. For example:
```yml title=".gitlab-ci.yml"
# Additional pipeline configurations
# Sets the stages for the pipeline
stages:
- UI_Tests
# 👇 Adds Chromatic as a job
Chromatic:
stage: UI_Tests
# 👇 Runs Chromatic with the flag to prevent pipeline failure
script:
- npx chromatic --exit-zero-on-changes
```
Read our [configuration reference documentation](/docs/configure#options).
When using `--exit-zero-on-changes` your pipeline execution still stop and fail if your Storybook contains stories that error. If you'd prefer Chromatic _never_ to block your pipeline, you can use `npx chromatic || true`.
#### Re-run failed builds after verifying UI test results
Builds that contain visual changes need to be [verified](/docs/quickstart#4-review-changes). They will fail if you are not using `--exit-zero-on-changes`. Once you accept all the changes, re-run the pipeline and the `Run Chromatic` step will pass.
If you deny any change, you will need to make the necessary code changes to fix the test (and thus start a new build) to get Chromatic to pass again.
#### Maintain a clean "main" branch
A clean `main` branch is a development **best practice** and **highly recommended** for Chromatic. This means testing your `main` branch to ensure builds are passing. It's important to note that baselines will not persist through branching and merging unless you test your `main` branch.
If the builds are a result of direct commits to `main`, you will need to accept changes to keep the main branch clean. If they're merged from `feature-branches`, you will need to make sure those branches are passing _before_ you merge into `main`.
#### GitLab squash/rebase merge and the "main" branch
GitLab's squash/rebase merge functionality creates new commits that have no association to the branch being merged. If you are already using this option, then we will automatically detect this situation and bring baselines over (see [Branching and Baselines](/docs/branching-and-baselines#how-do-baselines-get-preserved-during-squash-and-rebase-merging) for more details).
If you’re using this functionality but notice the incoming changes were not accepted as baselines in Chromatic, then you'll need to adjust the pipeline and include the `--auto-accept-changes` flag. For example:
```yml title=".gitlab-ci.yml"
# Additional pipeline configurations
# Sets the stages for the pipeline
stages:
- UI_Tests
# 👇 Checks if the branch is not main and runs Chromatic
Chromatic_Auto_Accept_Changes:
stage: UI_Tests
script:
- npx chromatic --auto-accept-changes
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: always
# 👇 Checks if the branch is not main and runs Chromatic
Chromatic:
stage: UI_Tests
script:
- npx chromatic
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: always
allow_failure: true
```
Read our [configuration reference documentation](/docs/configure#options).
Including the `--auto-accept-changes` flag ensures all incoming changes will be accepted as baselines. Additionally, you'll maintain a clean `main` branch.
If you want to test the changes introduced by the rebased branch, you can adjust your workflow and include a new step with the `ignore-last-build-on-branch` flag. For example:
```yml title=".gitlab-ci.yml"
# Additional pipeline configurations
# Sets the stages for the pipeline
stages:
- UI_Tests
# 👇 Adds Chromatic as a job
Chromatic:
stage: UI_Tests
script:
# 👇 Option to skip the last build on target branch
- npx chromatic --ignore-last-build-on-branch=my-branch
```
Read our [configuration reference documentation](/docs/configure#options).
Including the `--ignore-last-build-on-branch` flag ensures the latest build for the specific branch is not used as a baseline.
#### Run Chromatic on external forks of open source projects
You can enable PR checks for external forks by sharing your project token where you configured the Chromatic command (often in `package.json` or in the pipeline step).
Sharing project tokens allows contributors and others to run Chromatic builds on your project, which can use snapshots. They cannot access your account, settings, or accept baselines. This can be an acceptable tradeoff for open source projects that value community contributions.
#### Skipping builds for certain branches
Sometimes you might want to skip running a build for a certain branch, but still have Chromatic mark the latest commit on that branch as "passed". Otherwise pull requests could be blocked due to required checks that remain pending. To avoid this issue, you can run `chromatic` with the `--skip` flag. This flag accepts a branch name or glob pattern.
One use case for this feature is skipping builds for branches created by a bot. For instance, Renovate automatically updates a projects dependencies. Although some dependencies can result in UI changes, you might not find it worthwhile to run Chromatic for every single dependency update. Instead, you could rely on Chromatic running against the `main` or `develop` branch.
To skip builds for `renovate` branches, use the following:
```shell
npx chromatic --skip 'renovate/**'
```
Read our [configuration reference documentation](/docs/configure#options).
To apply this to multiple branches, use an "extended glob". See the [globs guide] for details.
```shell
npx chromatic --skip '@(renovate/**|your-custom-branch/**)'
```
[globs guide]: /docs/globs
---
## Automate Chromatic with Jenkins
URL: https://chromatic.com/docs/jenkins
> Learn how to configure Chromatic with Jenkins
# Automate Chromatic with Jenkins
Chromatic’s automation can be included as part of your Jenkins pipeline with relative ease.
## Setup
To integrate Chromatic with your existing [multistage pipeline](https://www.jenkins.io/doc/tutorials/build-a-multibranch-pipeline-project/), you'll need to add the following:
{/* prettier-ignore-start */}
```groovy title="JenkinsFile"
pipeline {
/* Other pipeline configuration. */
stages {
/* Other pipeline stages */
/* 👇 Adds Chromatic as a stage */
stage('Run Chromatic') {
environment {
CHROMATIC_PROJECT_TOKEN = credentials('chromatic-project-token')
}
steps {
/* 👇 Runs the Chromatic CLI */
sh "npx chromatic"
}
}
}
}
```
```groovy title="JenkinsFile"
pipeline {
/* Other pipeline configuration. */
stages {
/* Other pipeline stages */
stage('Playwright') {
agent {
docker {
image 'mcr.microsoft.com/playwright:v1.62.0-noble'
reuseNode true
}
}
steps {
sh 'npm ci'
sh 'npx playwright test'
}
post {
always {
/*
Chromatic automatically defaults to the test-results directory.
Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
*/
archiveArtifacts 'test-results/**'
}
}
}
stage('Run Chromatic'){
environment {
CHROMATIC_PROJECT_TOKEN = credentials('chromatic-project-token')
CHROMATIC_ARCHIVE_LOCATION = 'test-results'
}
steps {
/* 👇 Runs the Chromatic CLI */
sh "npx chromatic --playwright"
}
}
}
}
```
```groovy title="JenkinsFile"
pipeline {
/* Other pipeline configuration. */
stages {
/* Other pipeline stages */
stage('Cypress') {
agent {
docker {
image 'cypress/browsers:node-24.19.0-chrome-151.0.7922.75-1-ff-153.0.3-edge-151.0.4129.59-1'
reuseNode true
}
}
environment {
ELECTRON_EXTRA_LAUNCH_ARGS = '--remote-debugging-port=9222'
}
steps {
sh 'npm ci'
sh 'npm run dev &'
sh 'npx cypress run'
}
post {
always {
/*
Chromatic automatically defaults to the cypress/downloads directory.
Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
*/
archiveArtifacts 'cypress/downloads/**'
}
}
}
stage('Run Chromatic'){
environment {
CHROMATIC_PROJECT_TOKEN = credentials('chromatic-project-token')
CHROMATIC_ARCHIVE_LOCATION = 'cypress/downloads'
}
steps {
/* 👇 Runs the Chromatic CLI */
sh "npx chromatic --cypress"
}
}
}
}
```
{/* prettier-ignore-end */}
We recommend saving the project token as a secret text environment variable named `CHROMATIC_PROJECT_TOKEN` for security reasons. When the Chromatic CLI is executed, it will read the environment variable automatically without any additional flags. Refer to the official official Jenkins [environment variables documentation](https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#handling-credentials) to learn more about it.
### Run Chromatic on specific branches
If you need to customize your workflow to run Chromatic on specific branches, adjust your `Jenkinsfile` like so:
```groovy title="JenkinsFile"
pipeline {
/* Other pipeline configuration. */
stages {
/* Other pipeline stages */
/* 👇 Adds Chromatic as a stage */
stage('Run Chromatic') {
when {
branch 'example' /* 👈 Filters the execution to run only on the main branch */
}
environment {
CHROMATIC_PROJECT_TOKEN = credentials('chromatic-project-token')
}
steps {
/* 👇 Runs the Chromatic CLI */
sh "npx chromatic"
}
}
}
}
```
Read the official Jenkins [conditional pipeline documentation](https://www.jenkins.io/doc/book/pipeline/syntax/).
Now your pipeline will only run Chromatic in the `example` branch.
### Run Chromatic on large projects
Chromatic is prepared to handle large file uploads (with a limit of 5000 files, including stories and assets). If your project exceeds this limit, we recommend adjusting your workflow and run the `chromatic` command with the `--zip` flag to compress your build before uploading it. For example:
```groovy title="JenkinsFile"
pipeline {
/* Other pipeline configuration. */
stages {
/* Other pipeline stages */
/* 👇 Adds Chromatic as a stage */
stage('Run Chromatic') {
environment {
CHROMATIC_PROJECT_TOKEN = credentials('chromatic-project-token')
}
steps {
/* 👇 Runs Chromatic with the flag to compress the build output. */
sh "npx chromatic --zip"
}
}
}
}
```
### Run Chromatic on monorepos
Chromatic can be run on monorepos that have multiple subprojects. Each subproject will need it's own project token stored as an environment variable.
#### Prerequisites
1. Ensure that you're in the correct working directory for the subproject.
2. Have `build-storybook` npm script in the subproject's `package.json` file OR explicitly name the script using the using the `--build-script-name` CLI flag and make sure the script is listed in the subproject's `package.json` file.
If you've already built your Storybook in a separate CI step, you can adjust your workflow to include the `--storybook-build-dir` CLI flag to point to the build output directory.
```groovy title="JenkinsFile"
pipeline {
/* Other pipeline configuration. */
stages {
/* Other pipeline stages */
/* 👇 Adds Chromatic as a stage */
stage('Run Chromatic') {
environment {
CHROMATIC_PROJECT_TOKEN_1 = credentials('chromatic-project-token-1')
CHROMATIC_PROJECT_TOKEN_2 = credentials('chromatic-project-token-2')
}
/* 👇 Runs Chromatic sequentially for each monorepo subproject. */
steps {
dir('packages/project_1/'){
sh "npx chromatic --project-token=${CHROMATIC_PROJECT_TOKEN_1}"
}
dir('packages/project_2/'){
sh "npx chromatic --project-token=${CHROMATIC_PROJECT_TOKEN_2}"}"
}
}
}
}
```
If you want to run Chromatic in parallel for each subproject, you can use this snippet below.
```groovy title="JenkinsFile"
pipeline {
/* Other pipeline configuration. */
stages {
/* Other pipeline stages */
/* 👇 Adds Chromatic as a stage */
stage('Run Chromatic') {
/* 👇 Runs Chromatic in parallel for each monorepo subproject. */
parallel {
stage('Publish Project 1 to Chromatic') {
environment {
CHROMATIC_PROJECT_TOKEN_1 = credentials('chromatic-project-token-1')
}
steps {
dir('packages/project_1/'){
sh "npx chromatic --project-token=${CHROMATIC_PROJECT_TOKEN_1}"
}
}
}
stage('Publish Project 2 to Chromatic') {
environment {
CHROMATIC_PROJECT_TOKEN_2 = credentials('chromatic-project-token-2')
}
steps {
dir('packages/project_2/'){
sh "npx chromatic --project-token=${CHROMATIC_PROJECT_TOKEN_2}"
}
}
}
}
}
}
}
```
### Enable TurboSnap
TurboSnap is an advanced Chromatic feature implemented to improve the build time for large projects, disabled by default once you add Chromatic to your CI environment. To enable it, you'll need to adjust your existing workflow and run the `chromatic` command with the `--only-changed` flag as follows:
```groovy title="JenkinsFile"
pipeline {
/* Other pipeline configuration. */
stages {
/* Other pipeline stages */
/* 👇 Adds Chromatic as a stage */
stage('Run Chromatic') {
environment {
CHROMATIC_PROJECT_TOKEN = credentials('chromatic-project-token')
}
steps {
/* 👇 Enables Chromatic's TurboSnap feature. */
sh "npx chromatic --only-changed"
}
}
}
}
```
TurboSnap is highly customizable and can be configured to fit your requirements. For more information, read our [documentation](/docs/turbosnap).
### Overriding Chromatic's branch detection
If your Jenkins pipeline includes a set of rules for branches (e.g., renames the branch, creates ephemeral, or temporary branches) it can lead to unforeseen build errors.
In this case, you can adjust your workflow and include the `--branch-name` flag. This flag overrides Chromatic's default branch detection in favor of the specified branch:
```groovy title="JenkinsFile"
pipeline {
/* Other pipeline configuration. */
stages {
/* Other pipeline stages */
/* 👇 Adds Chromatic as a stage */
stage('Run Chromatic') {
environment {
CHROMATIC_PROJECT_TOKEN = credentials('chromatic-project-token')
YOUR_BRANCH='your-branch'
}
steps {
/* 👇 Runs the Chromatic CLI --branch-name flag to override the baseline branch */
sh "npx chromatic --branch-name=${YOUR_BRANCH}"
}
}
}
}
```
Chromatic will now detect the correct branch and run your workflow. You can also apply this when fixing cross-fork UI comparisons.
### Recommended configuration for build events
Jenkins like CI systems offer the option of running builds for various types of events. For instance for commits pushed to a branch in a pull request. Or for "merge" commits between that branch and the base branch (main).
These specific types of commits (merge) don't persist in the history of your repository. That can cause Chromatic's baselines to be lost in certain situations.
If you're using the Jenkins [GitHub Pull Request plugin](https://github.com/jenkinsci/ghprb-plugin/blob/master/README.md), our recommendation for your pipeline is the following:
- Choose the `ghprbPullId` specifier for the `refspec`
- Ensure the Branch Specifier is set to `${ghprbActualCommit}`
If you're using other Jenkins plugins in your pipeline, refer to this [documentation](https://www.jenkins.io/doc/book/pipeline/multibranch/) for more information.
### UI Test and UI Review
[UI Tests](/docs#test-how-uis-look--function) and [UI Review](/docs/review) rely on [branch and baseline](/docs/branching-and-baselines) detection to keep track of [snapshots](/docs/snapshots). We recommend the following configuration.
#### Command exit code for "required" checks
If you are using pull request statuses as required checks before merging, you may not want your pipeline to fail if test snapshots render without errors (but with changes). To achieve this, pass the flag `--exit-zero-on-changes` to the `chromatic` command, and your pipeline will continue in such cases. For example:
```groovy title="JenkinsFile"
pipeline {
/* Other pipeline configuration. */
stages {
/* Other pipeline stages */
/* 👇 Adds Chromatic as a stage in the pipeline */
stage('Run Chromatic') {
environment {
CHROMATIC_PROJECT_TOKEN = credentials('chromatic-project-token')
}
steps {
/* 👇 Runs Chromatic with the flag to prevent stage failure */
sh "npx chromatic --exit-zero-on-changes"
}
}
}
}
```
Read our [configuration reference documentation](/docs/configure#options).
When using `--exit-zero-on-changes` your pipeline will still stop and fail if your Storybook contains stories that error. If you'd prefer Chromatic _never_ to block your pipeline, you can use `npx chromatic || true`.
#### Re-run failed builds after verifying UI test results
Builds that contain visual changes need to be [verified](/docs/quickstart#4-review-changes). They will fail if you are not using `--exit-zero-on-changes`. Once you accept all the changes, re-run the build and the `Run Chromatic` pipeline stage will pass.
If you deny any change, you will need to make the necessary code changes to fix the test (and thus start a new build) to get Chromatic to pass again.
#### Maintain a clean "main" branch
A clean `main` branch is a development **best practice** and **highly recommended** for Chromatic. This means testing your `main` branch to ensure builds are passing. It's important to note that baselines will not persist through branching and merging unless you test your `main` branch.
If the builds are a result of direct commits to `main`, you will need to accept changes to keep the main branch clean. If they're merged from `feature-branches`, you will need to make sure those branches are passing _before_ you merge into `main`.
#### Squash/rebase merge and the "main" branch
We use GitHub, GitLab, and Bitbucket APIs respectively to detect squashing and rebasing so your baselines match your expectations no matter your Git workflow (see [Branching and Baselines](/docs/branching-and-baselines#how-do-baselines-get-preserved-during-squash-and-rebase-merging) for more details).
If you’re using this functionality but notice the incoming changes were not accepted as baselines in Chromatic, then you'll need to adjust the pipeline and include a new Chromatic stage using the `--auto-accept-changes` flag. For example:
```groovy title="JenkinsFile"
pipeline {
/* Other pipeline configuration. */
stages {
/* Other pipeline stages */
/* 👇 Checks if the current branch is not main and runs Chromatic */
stage('Run Chromatic') {
when {
not {
branch 'main'
}
}
environment {
CHROMATIC_PROJECT_TOKEN = credentials('chromatic-project-token')
}
steps {
sh "npx chromatic"
}
}
/* 👇 Checks if the current branch is main and runs Chromatic with the flag to accept all changes */
stage('Run Chromatic and auto accept changes') {
when {
branch 'main'
}
environment {
CHROMATIC_PROJECT_TOKEN = credentials('chromatic-project-token')
}
steps {
sh "npx chromatic --auto-accept-changes"
}
}
}
}
```
Read our [configuration reference documentation](/docs/configure#options).
Including the `--auto-accept-changes` flag ensures all incoming changes will be accepted as baselines. Additionally, you'll maintain a clean `main` branch.
If you want to test the changes introduced by the rebased branch, you can adjust your workflow and include a new step with the `ignore-last-build-on-branch` flag. For example:
```groovy title="JenkinsFile"
pipeline {
/* Other pipeline configuration. */
stages {
/* Other pipeline stages */
/* 👇 Adds Chromatic as a stage in the pipeline */
stage('Run Chromatic') {
environment {
CHROMATIC_PROJECT_TOKEN = credentials('chromatic-project-token')
}
steps {
/* 👇 Option to skip the last build on target branch */
sh "npx chromatic --ignore-last-build-on-branch=my-branch"
}
}
}
}
```
Read our [configuration reference documentation](/docs/configure#options).
Including the `--ignore-last-build-on-branch` flag ensures the latest build for the specific branch is not used as a baseline.
#### Run Chromatic on external forks of open source projects
You can enable PR checks for external forks by sharing your project token where you configured the Chromatic command (often in `package.json` or in the pipeline step).
Sharing project tokens allows contributors and others to run Chromatic builds on your project, which can use snapshots. They cannot access your account, settings, or accept baselines. This can be an acceptable tradeoff for open source projects that value community contributions.
#### Skipping builds for certain branches
Sometimes you might want to skip running a build for a certain branch, but still have Chromatic mark the latest commit on that branch as "passed". Otherwise pull requests could be blocked due to required checks that remain pending. To avoid this issue, you can run `chromatic` with the `--skip` flag. This flag accepts a branch name or glob pattern.
One use case for this feature is skipping builds for branches created by a bot. For instance, Dependabot automatically updates a projects dependencies. Although some dependencies can result in UI changes, you might not find it worthwhile to run Chromatic for every single dependency update. Instead, you could rely on Chromatic running against the `main` or `develop` branch.
To skip builds for `dependabot` branches, use the following:
```shell
npx chromatic --skip 'dependabot/**'
```
Read our [configuration reference documentation](/docs/configure#options).
To apply this to multiple branches, use an "extended glob". See the [globs guide] for details.
```shell
npx chromatic --skip '@(renovate/**|dependabot/**)'
```
[globs guide]: /docs/globs
---
## Automate Chromatic with Semaphore
URL: https://chromatic.com/docs/semaphore
> Learn how to configure Chromatic with Semaphore
# Automate Chromatic with Semaphore
Chromatic's automation can be included as part of your Semaphore workflow with relative ease.
## Setup
To integrate Chromatic with your existing workflow, you'll need to add the following:
{/* prettier-ignore-start */}
```yml title=".semaphore/semaphore.yml"
version: v1.0
name: UI Tests
agent:
machine:
type: e2-standard-2
os_image: ubuntu2404
global_job_config:
prologue:
commands:
- sem-version node 24.19.0
- checkout
blocks:
- name: Chromatic
task:
secrets:
- name: CHROMATIC_PROJECT_TOKEN
jobs:
- name: Run Chromatic
commands:
- cache restore npm-$SEMAPHORE_GIT_BRANCH-$(checksum package-lock.json)-$(checksum .semaphore/semaphore.yml)
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- npm ci
- npx chromatic
```
```yml title=".semaphore/semaphore.yml"
version: v1.0
name: UI Tests
agent:
machine:
type: e2-standard-2
os_image: ubuntu2404
global_job_config:
prologue:
commands:
- checkout
blocks:
- name: Playwright
dependencies: []
task:
agent:
machine:
type: e2-standard-2
os_image: ubuntu2404
containers:
- name: Plawyright
image: mcr.microsoft.com/playwright:v1.62.0-noble
jobs:
- name: Run Playwright
commands:
- cache restore npm-$SEMAPHORE_GIT_BRANCH-$(checksum package-lock.json)-$(checksum .semaphore/semaphore.yml)
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- npm ci
- cache store npm-$SEMAPHORE_GIT_BRANCH-$(checksum package-lock.json)-$(checksum .semaphore/semaphore.yml) ~/.npm
- npx playwright test
epilogue:
always:
commands:
# Chromatic automatically defaults to the test-results directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
- artifact push workflow test-results
- name: Chromatic
dependencies: ["Playwright"]
task:
prologue:
commands:
- sem-version node 24.19.0
- artifact pull workflow test-results
secrets:
- name: CHROMATIC_PROJECT_TOKEN
env_vars:
- name: CHROMATIC_ARCHIVE_LOCATION
value: test-results
jobs:
- name: Run Chromatic
commands:
- cache restore npm-$SEMAPHORE_GIT_BRANCH-$(checksum package-lock.json)-$(checksum .semaphore/semaphore.yml)
- npm ci
- npx chromatic --playwright
```
```yml title=".semaphore/semaphore.yml"
version: v1.0
name: UI Tests
agent:
machine:
type: e2-standard-2
os_image: ubuntu2404
global_job_config:
prologue:
commands:
- sem-version node 24.19.0
- checkout
blocks:
- name: Cypress
dependencies: []
task:
env_vars:
- name: ELECTRON_EXTRA_LAUNCH_ARGS
value: "--remote-debugging-port=9222"
jobs:
- name: Run Cypress tests
commands:
- cache restore npm-$SEMAPHORE_GIT_BRANCH-$(checksum package-lock.json)-$(checksum .semaphore/semaphore.yml)
- cache restore cypress-$SEMAPHORE_GIT_BRANCH-$(checksum package-lock.json)-$(checksum .semaphore/semaphore.yml)
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- npm ci
- cache store npm-$SEMAPHORE_GIT_BRANCH-$(checksum package-lock.json)-$(checksum .semaphore/semaphore.yml) ~/.npm
- cache store cypress-$SEMAPHORE_GIT_BRANCH-$(checksum package-lock.json)-$(checksum .semaphore/semaphore.yml) ~/.cache/Cypress
- npm run dev &
- npx cypress run
epilogue:
always:
commands:
# Chromatic automatically defaults to the cypress/downloads directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
- artifact push workflow cypress/downloads
- name: Chromatic
dependencies: ["Cypress"]
task:
prologue:
commands:
# You can omit the destination flag if you're using a root-level directory.
- artifact pull workflow downloads --destination cypress/downloads
secrets:
- name: CHROMATIC_PROJECT_TOKEN
env_vars:
- name: CHROMATIC_ARCHIVE_LOCATION
value: cypress/downloads
jobs:
- name: Run Chromatic
commands:
- cache restore npm-$SEMAPHORE_GIT_BRANCH-$(checksum package-lock.json)-$(checksum .semaphore/semaphore.yml)
- npm ci
- npx chromatic --cypress
```
{/* prettier-ignore-end */}
We recommend saving the project token as an secret named `CHROMATIC_PROJECT_TOKEN` for security reasons. When the Chromatic CLI is executed, it will read the value automatically without any additional flags. Refer to the official Semaphore [secrets documentation](https://docs.semaphore.io/using-semaphore/secrets) to learn more about it.
### Run Chromatic on specific branches
If you need to customize your workflow to run Chromatic on specific branches, adjust your workflow like so:
```yml title=".semaphore/semaphore.yml"
# Other required configuration
blocks:
# Other jobs implemented in the workflow
# 👇 Adds Chromatic as a job
- name: Chromatic
run:
when: branch = 'main' # 👈 Filters the execution to run only on the main branch
task:
jobs:
- name: Run Chromatic
commands:
- npx chromatic
```
Read the official Semaphore [conditional job execution documentation](https://docs.semaphore.io/using-semaphore/jobs#skip-run).
Now Chromatic will only run in the `main` branch.
### Run Chromatic on large projects
Chromatic is prepared to handle large file uploads (with a limit of 5000 files, including stories and assets). If your project exceeds this limit, we recommend adjusting your workflow and run the `chromatic` command with the `--zip` flag to compress your build before uploading it. For example:
```yml title=".semaphore/semaphore.yml"
# Other required configuration
blocks:
# Other jobs
# 👇 Adds Chromatic as a job
- name: Chromatic
# Other configuration
task:
jobs:
- name: Run Chromatic
commands:
# Other job steps
# 👇 Runs Chromatic with the flag to compress the build output.
- npx chromatic --zip
```
### Run Chromatic on monorepos
Chromatic can be run on monorepos that have multiple subprojects. Each subproject will need it's own project token stored as an environment variable.
#### Prerequisites
1. Ensure that you're in the correct working directory for the subproject.
2. Have `build-storybook` npm script in the subproject's `package.json` file OR explicitly name the script using the `--build-script-name` CLI flag and make sure the script is listed in the subproject's `package.json` file.
If you've already built your Storybook in a separate CI step, you can adjust your workflow to include the [`--storybook-build-dir`](/docs/configure#options) CLI flag to point to the build output directory.
```yml title=".semaphore/semaphore.yml"
# Other required configuration
# 👇 Adds Chromatic for for each monorepo subproject
blocks:
- name: Run Chromatic on Project 1
task:
prologue:
commands:
- checkout
- cd apps/frontend
# Other job steps
secrets:
- name: CHROMATIC_PROJECT_TOKEN_1
jobs:
- name: Publish Project 1 to Chromatic
commands:
- npx chromatic --project-token=$CHROMATIC_PROJECT_TOKEN_1
- name: Run Chromatic on Project 2
task:
prologue:
commands:
- checkout
- cd packages/ui
# Other job steps
secrets:
- name: CHROMATIC_PROJECT_TOKEN_2
jobs:
- name: Publish Project 2 to Chromatic
commands:
- npx chromatic --project-token=$CHROMATIC_PROJECT_TOKEN_2
```
If you want to run Chromatic in parallel for each subproject, you can adjust your workflow as follows:
```yml title=".semaphore/semaphore.yml"
# Other required configuration
blocks:
# Other jobs
# 👇 Runs Chromatic in parallel for each monorepo subproject
- name: Run Chromatic on Project 1
dependencies: []
task:
prologue:
commands:
- checkout
- cd apps/frontend
# Other job steps
secrets:
- name: CHROMATIC_PROJECT_TOKEN_1
jobs:
- name: Publish Project 1 to Chromatic
commands:
- npx chromatic --project-token=$CHROMATIC_PROJECT_TOKEN_1
- name: Run Chromatic on Project 2
dependencies: []
task:
prologue:
commands:
- checkout
- cd packages/ui
# Other job steps
secrets:
- name: CHROMATIC_PROJECT_TOKEN_2
jobs:
- name: Publish Project 2 to Chromatic
commands:
- npx chromatic --project-token=$CHROMATIC_PROJECT_TOKEN_2
```
You can also run Chromatic conditionally for each subproject when a specific change is detected. For example:
{/* prettier-ignore-start */}
```yml title=".semaphore/semaphore.yml"
# Other required configuration
blocks:
# Other jobs
# 👇 Adds Chromatic as a conditional job for each subproject
- name: Run Chromatic on Project 1
dependencies: []
run:
# 👇 Checks for changes in the apps/frontend directory, excluding any MDX files and triggers the worflow execution
when: 'change_in(''/apps/frontend'', {exclude: ''/apps/frontend/**/*.mdx'', default_branch: ''main''})'
task:
prologue:
commands:
- checkout
- cd apps/frontend
# Other job steps
secrets:
- name: CHROMATIC_PROJECT_TOKEN_1
jobs:
- name: Publish Project 1 to Chromatic
commands:
- npx chromatic --project-token=$CHROMATIC_PROJECT_TOKEN_1
- name: Run Chromatic on Project 2
dependencies: []
run:
# 👇 Checks for changes in the packages/ui directory, excluding any MDX files and triggers the worflow execution
when: 'change_in(''/packages/ui'', {exclude: ''/packages/ui/**/*.mdx'', default_branch: ''main''})'
task:
prologue:
commands:
- checkout
- cd packages/ui
# Other job steps
secrets:
- name: CHROMATIC_PROJECT_TOKEN_2
jobs:
- name: Publish Project 2 to Chromatic
commands:
- npx chromatic --project-token=$CHROMATIC_PROJECT_TOKEN_2
```
{/* prettier-ignore-end */}
Read the official Semaphore [monorepo documentation](https://docs.semaphore.io/using-semaphore/monorepo) to learn more about configuring your workflow.
### Enable TurboSnap
TurboSnap is an advanced Chromatic feature implemented to improve the build time for large projects, disabled by default once you add Chromatic to your CI environment. To enable it, you'll need to adjust your existing workflow and run the `chromatic` command with the `--only-changed` flag as follows:
```yml title=".semaphore/semaphore.yml"
# Other required configuration
blocks:
# Other jobs
# 👇 Adds Chromatic as a job
- name: Chromatic
task:
jobs:
- name: Run Chromatic
commands:
# Other job steps
# 👇 Enables Chromatic's TurboSnap feature.
- npx chromatic --only-changed
```
TurboSnap is highly customizable and can be configured to fit your requirements. For more information, read our [documentation](/docs/turbosnap).
### External Pull Requests
By default, Semaphore allows external pull requests to run on your workflow. If you want to restrict this behavior, refer to the official Semaphore [documentation](https://docs.semaphore.io/using-semaphore/workflows#pr) to learn more about it.
### UI Test and UI Review
[UI Tests](/docs#test-how-uis-look--function) and [UI Review](/docs/review) rely on [branch and baseline](/docs/branching-and-baselines) detection to keep track of [snapshots](/docs/snapshots). We recommend the following configuration.
#### Command exit code for "required" checks
If you are using pull request statuses as required checks before merging, you may not want your Semaphore job to fail if test snapshots render without errors (but with changes). To achieve this, pass the flag `--exit-zero-on-changes` to the `chromatic` command, and your job will continue in such cases. For example:
```yml title=".semaphore/semaphore.yml"
# Other required configuration
# 👇 Adds Chromatic as a job
blocks:
- name: Chromatic
task:
jobs:
- name: Runs Chromatic
commands:
# Other job steps
# 👇 Runs Chromatic with the flag to prevent workflow failure
- npx chromatic --exit-zero-on-changes
```
Read our [configuration reference documentation](/docs/configure#options).
When using `--exit-zero-on-changes` your build will still stop and fail if your Storybook contains stories that error. If you'd prefer Chromatic _never_ to block the build, you can use `npx chromatic || true`.
#### Re-run failed builds after verifying UI test results
Builds that contain visual changes need to be [verified](/docs/quickstart#4-review-changes). They will fail if you are not using `--exit-zero-on-changes`. Once you accept all the changes, re-run the workflow and the `Chromatic` job will pass.
If you deny any change, you will need to make the necessary code changes to fix the test (and thus start a new build) to get Chromatic to pass again.
#### Maintain a clean "main" branch
A clean `main` branch is a development **best practice** and **highly recommended** for Chromatic. This means testing your `main` branch to ensure builds are passing. It's important to note that baselines will not persist through branching and merging unless you test your `main` branch.
If the builds are a result of direct commits to `main`, you will need to accept changes to keep the main branch clean. If they're merged from `feature-branches`, you will need to make sure those branches are passing _before_ you merge into `main`.
#### Squash/rebase merge and the "main" branch
We use GitHub, GitLab, and Bitbucket APIs respectively to detect squashing and rebasing so your baselines match your expectations no matter your Git workflow (see [Branching and Baselines](/docs/branching-and-baselines#how-do-baselines-get-preserved-during-squash-and-rebase-merging) for more details).
If you’re using this functionality but notice the incoming changes were not accepted as baselines in Chromatic, then you'll need to adjust the `chromatic` command and include the `--auto-accept-changes` flag. For example:
```yml title=".semaphore/semaphore.yml"
# Other configuration here
blocks:
# 👇 Checks if the branch is not main and runs Chromatic
- name: Chromatic
run:
when: branch != 'main'
task:
jobs:
- name: Run Chromatic
commands:
# Other job steps
- npx chromatic
# 👇 Checks if the branch is main and runs Chromatic with the flag to accept all changes
- name: Runs Chromatic and and auto accept changes
run:
when: branch = 'main'
task:
jobs:
- name: Run Chromatic
commands:
# Other job steps
- npx chromatic --auto-accept-changes
```
Read our [configuration reference documentation](/docs/configure#options).
Including the `--auto-accept-changes` flag ensures all incoming changes will be accepted as baselines. Additionally, you'll maintain a clean `main` branch.
If you want to test the changes introduced by the rebased branch, you can adjust your workflow and include a new step with the `ignore-last-build-on-branch` flag. For example:
```yml title=".semaphore/semaphore.yml"
# Other required configuration
blocks:
# Other jobs
# 👇 Adds Chromatic as a job
- name: Chromatic
task:
jobs:
- name: Run Chromatic
commands:
# Other job steps
# 👇 Option to skip the last build on target branch
- npx chromatic --ignore-last-build-on-branch=my-branch
```
Including the `--ignore-last-build-on-branch` flag ensures the latest build for the specific branch is not used as a baseline.
#### Run Chromatic on external forks of open source projects
You can enable PR checks for external forks by sharing your project token where you configured the Chromatic command (often in `package.json` or in the pipeline step).
Sharing project tokens allows contributors and others to run Chromatic builds on your project, which can use snapshots. They cannot access your account, settings, or accept baselines. This can be an acceptable tradeoff for open source projects that value community contributions.
#### Skipping builds for certain branches
Sometimes you might want to skip running a build for a certain branch, but still have Chromatic mark the latest commit on that branch as "passed". Otherwise pull requests could be blocked due to required checks that remain pending. To avoid this issue, you can run `chromatic` with the `--skip` flag. This flag accepts a branch name or glob pattern.
One use case for this feature is skipping builds for branches created by a bot. For instance, Dependabot automatically updates a projects dependencies. Although some dependencies can result in UI changes, you might not find it worthwhile to run Chromatic for every single dependency update. Instead, you could rely on Chromatic running against the `main` or `develop` branch.
To skip builds for `dependabot` branches, use the following:
```shell
npx chromatic --skip 'dependabot/**'
```
Read our [configuration reference documentation](/docs/configure#options).
To apply this to multiple branches, use an "extended glob". See the [globs guide] for details.
```shell
npx chromatic --skip '@(renovate/**|dependabot/**)'
```
[globs guide]: /docs/globs
---
## Automate Chromatic with Travis CI
URL: https://chromatic.com/docs/travisci
> Learn how to configure Chromatic with Travis CI
# Automate Chromatic with Travis CI
Chromatic's automation can be included as part of your Travis CI job with relative ease.
## Setup
To integrate Chromatic with your existing workflow, you’ll need to add the following:
{/* prettier-ignore-start */}
```yml title=".travis.yml"
language: node_js
os: linux
dist: jammy
node_js:
- 20
before_script:
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- npm ci
cache: npm
branches:
only:
- main
jobs:
include:
- stage: "Chromatic"
name: "Run Chromatic"
script: npx chromatic
```
```yml title=".travis.yml"
language: node_js
os: linux
dist: jammy
node_js:
- 20
before_script:
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- npm ci
cache: npm
branches:
only:
- main
jobs:
include:
- stage: "Playwright"
name: "Run Playwright"
script:
- npx playwright install --with-deps
- npx playwright test
workspaces:
create:
name: playwright
paths:
# Chromatic automatically defaults to the test-results directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
- test-results
- stage: "Chromatic"
name: "Run Chromatic"
workspaces:
use: playwright
env:
- CHROMATIC_ARCHIVE_LOCATION="test-results"
script: npx chromatic --playwright
```
```yml title=".travis.yml"
language: node_js
os: linux
dist: jammy
node_js:
- 20
before_script:
# ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment.
- npm ci
cache:
directories:
- ~/.npm
- ~/.cache
branches:
only:
- main
jobs:
include:
- stage: "Cypress"
name: "Run Cypress"
env:
- ELECTRON_EXTRA_LAUNCH_ARGS="--remote-debugging-port=9222"
script:
- npm run dev &
- npx cypress run
- kill $(jobs -p) || true
workspaces:
create:
name: cypress
paths:
# Chromatic automatically defaults to the cypress/downloads directory.
# Replace with the path to your custom directory and adjust the CHROMATIC_ARCHIVE_LOCATION environment variable accordingly.
- cypress/downloads
- stage: "Chromatic"
name: "Run Chromatic"
workspaces:
use: cypress
env:
- CHROMATIC_ARCHIVE_LOCATION="cypress/downloads"
script: npx chromatic --cypress
```
{/* prettier-ignore-end */}
We recommend saving the project token as an encrypted environment variable named `CHROMATIC_PROJECT_TOKEN` for security reasons. When the Chromatic CLI is executed, it will read the environment variable automatically without any additional flags. Refer to the official Travis CI [environment variables documentation](https://docs.travis-ci.com/user/environment-variables/#defining-variables-in-repository-settings) to learn more about it.
### Run Chromatic on specific branches
If you need to customize your workflow to run on specific branches, you can do so. Change your `.travis.yml` to the following:
```yml title=".travis.yml"
# Other required configuration
branches:
only: main # 👈 Filters the execution to run only on the main branch
jobs:
include:
# Other jobs
# 👇 Adds Chromatic as a job
- name: 'Run Chromatic'
script: npx chromatic
```
Read the official Travis CI [conditional build documentation](https://docs.travis-ci.com/user/conditional-builds-stages-jobs/).
### Run Chromatic on large projects
Chromatic is prepared to handle large file uploads (with a limit of 5000 files, including stories and assets). If your project exceeds this limit, we recommend adjusting your workflow and run the `chromatic` command with the `--zip` flag to compress your build before uploading it. For example:
```yml title=".travis.yml"
# Other required configuration
jobs:
include:
# Other jobs
# 👇 Adds Chromatic as a job
- name: 'Run Chromatic'
#👇 Runs Chromatic with the flag to compress the build output.
script: npx chromatic --zip
```
### Run Chromatic on monorepos
Chromatic can be run on monorepos that have multiple subprojects. Each subproject will need it's own project token stored as an environment variable.
#### Prerequisites
1. Ensure that you're in the correct working directory for the subproject.
2. Have `build-storybook` npm script in the subproject's `package.json` file OR explicitly name the script using the `--build-script-name` CLI flag and make sure the script is listed in the subproject's `package.json` file.
If you've already built your Storybook in a separate CI step, you can adjust your workflow to include the `--storybook-build-dir` CLI flag to point to the build output directory.
```yml title=".travis.yml"
# Other required configuration
# 👇 Runs Chromatic in parallel for each monorepo subproject
jobs:
include:
# Other jobs
- name: 'Publish Project 1 to Chromatic'
before_script:
# Other steps
- cd packages/project_1
script: npx chromatic
env: CHROMATIC_PROJECT_TOKEN=$CHROMATIC_PROJECT_TOKEN_1
- name: 'Publish Project 2 to Chromatic'
before_script:
# Other steps
- cd packages/project_2
script: npx chromatic
env: CHROMATIC_PROJECT_TOKEN=$CHROMATIC_PROJECT_TOKEN_2
```
Additional parallelization can be achieved when configuring your workflow to run Chromatic on multiple subprojects. Read the official Travis CI [build matrix documentation](https://docs.travis-ci.com/user/build-matrix/).
### Enable TurboSnap
TurboSnap is an advanced Chromatic feature implemented to improve the build time for large projects, disabled by default once you add Chromatic to your CI environment. To enable it, you'll need to adjust your existing workflow and run the `chromatic` command with the `--only-changed` flag as follows:
```yml title=".travis.yml"
# Other required configuration
jobs:
include:
# Other jobs
# 👇 Adds Chromatic as a job
- name: 'Run Chromatic'
# 👇 Enables Chromatic's TurboSnap feature.
script: npx chromatic --only-changed
```
TurboSnap is highly customizable and can be configured to fit your requirements. For more information, read our [documentation](/docs/turbosnap).
### Recommended configuration for build events
Travis CI like other CI systems offer the option of running builds for various types of events. For instance for commits pushed to a branch in a pull request. Or for "merge" commits between that branch and the base branch (main).
These specific types of commits (merge) don't persist in the history of your repository. That can cause Chromatic's baselines to be lost in certain situations.
For internal pull requests (i.e., pull requests that aren't from forks) we recommend disabling Chromatic on `pr` build events. Also make sure you have `push` builds enabled in your settings.
Once these conditions are met, add the following code to your `.travis.yml`:
```yml title=".travis.yml"
# Other required configuration
jobs:
include:
# Other jobs
# 👇 Adds Chromatic as a job
- name: 'Run Chromatic'
# 👇 Verifies the build event type or a if it's a forked repository
if: (type = push OR head_repo != repo )
script: npx chromatic
```
For external pull requests (i.e., forked repositories), the above code will ensure Chromatic runs with the `pr` build event because Travis will not trigger `push` events for these cases.
### UI Test and UI Review
[UI Tests](/docs#test-how-uis-look--function) and [UI Review](/docs/review) rely on [branch and baseline](/docs/branching-and-baselines) detection to keep track of [snapshots](/docs/snapshots). We recommend the following configuration.
#### Command exit code for "required" checks
If you are using pull request statuses as required checks before merging, you may not want your Travis build to fail if test snapshots render without errors (but with changes). To achieve this, pass the flag `--exit-zero-on-changes` to the `chromatic` command, and your job will continue in such cases. For example:
```yml title=".travis.yml"
# Other required configuration
jobs:
include:
# Other jobs
# 👇 Adds Chromatic as a job
- name: 'Run Chromatic'
# 👇 Runs Chromatic with the flag to prevent workflow failure
script: npx chromatic --exit-zero-on-changes
```
Read our [configuration reference documentation](/docs/configure#options).
When using `--exit-zero-on-changes` your build will still stop and fail if your Storybook contains stories that error. If you'd prefer Chromatic _never_ to block the build, you can use `npx chromatic || true`.
#### Re-run failed builds after verifying UI test results
Builds that contain visual changes need to be [verified](/docs/quickstart#4-review-changes). They will fail if you are not using `--exit-zero-on-changes`. Once you accept all the changes, re-run the build and the `Run Chromatic` job will pass.
If you deny any change, you will need to make the necessary code changes to fix the test (and thus start a new build) to get Chromatic to pass again.
#### Maintain a clean "main" branch
A clean `main` branch is a development **best practice** and **highly recommended** for Chromatic. This means testing your `main` branch to ensure builds are passing. It's important to note that baselines will not persist through branching and merging unless you test your `main` branch.
If the builds are a result of direct commits to `main`, you will need to accept changes to keep the main branch clean. If they're merged from `feature-branches`, you will need to make sure those branches are passing _before_ you merge into `main`.
#### Squash/rebase merge and the "main" branch
We use GitHub, GitLab, and Bitbucket APIs respectively to detect squashing and rebasing so your baselines match your expectations no matter your Git workflow (see [Branching and Baselines](/docs/branching-and-baselines#how-do-baselines-get-preserved-during-squash-and-rebase-merging) for more details).
If you’re using this functionality but notice the incoming changes were not accepted as baselines in Chromatic, then you'll need to adjust the workflow and include a new Chromatic job with the `--auto-accept-changes` flag. For example:
```yml title=".travis.yml"
# Other configuration here
jobs:
include:
# 👇 Checks if the branch is not main and runs Chromatic
- name: 'Run Chromatic'
if: branch != main
script: npx chromatic
# 👇 Checks if the branch is main and runs Chromatic with the flag to accept all changes
- name: 'Run Chromatic and auto accepts changes'
if: branch = main
script: npx chromatic --auto-accept-changes
```
Read our [configuration reference documentation](/docs/configure#options).
Including the `--auto-accept-changes` flag ensures all incoming changes will be accepted as baselines. Additionally, you'll maintain a clean `main` branch.
If you want to test the changes introduced by the rebased branch, you can adjust your workflow and include a new step with the `ignore-last-build-on-branch` flag. For example:
```yml title=".travis.yml"
# Other required configuration
jobs:
include:
# Other jobs
# 👇 Adds Chromatic as a job
- name: 'Run Chromatic'
# 👇 Option to skip the last build on target branch
script: npx chromatic --ignore-last-build-on-branch=my-branch
```
Read our [configuration reference documentation](/docs/configure#options).
Including the `--ignore-last-build-on-branch` flag ensures the latest build for the specific branch is not used as a baseline.
#### Run Chromatic on external forks of open source projects
You can enable PR checks for external forks by sharing your project token where you configured the Chromatic command (often in `package.json` or in the pipeline step).
Sharing project tokens allows contributors and others to run Chromatic builds on your project, which can use snapshots. They cannot access your account, settings, or accept baselines. This can be an acceptable tradeoff for open source projects that value community contributions.
#### Skipping builds for certain branches
Sometimes you might want to skip running a build for a certain branch, but still have Chromatic mark the latest commit on that branch as "passed". Otherwise pull requests could be blocked due to required checks that remain pending. To avoid this issue, you can run `chromatic` with the `--skip` flag. This flag accepts a branch name or glob pattern.
One use case for this feature is skipping builds for branches created by a bot. For instance, Dependabot automatically updates a projects dependencies. Although some dependencies can result in UI changes, you might not find it worthwhile to run Chromatic for every single dependency update. Instead, you could rely on Chromatic running against the `main` or `develop` branch.
To skip builds for `dependabot` branches, use the following:
```shell
npx chromatic --skip 'dependabot/**'
```
Read our [configuration reference documentation](/docs/configure#options).
To apply this to multiple branches, use an "extended glob". See the [globs guide] for details.
```shell
npx chromatic --skip '@(renovate/**|dependabot/**)'
```
[globs guide]: /docs/globs
---
## Acceptable Use Policy
URL: https://chromatic.com/docs/acceptable-use
> Chromatic Acceptable Use Policy
# Acceptable Use Policy
Chroma Software, Inc.®
Last reviewed: Feb 22, 2024
Chroma Software, Inc., a business corporation (herein “Chromatic”, “we”, “us” or “our”), offers a cloud service (herein “Chromatic Service”) for Storybook that automates workflows for UI feedback, visual regression testing, and documentation. While we support the development of UIs to help create the core frontend technology for thousands of companies, Chromatic Service may only be used for lawful purposes.
This Acceptable Use Policy (“AUP”) governs the use of Chromatic Service by our customers (“Customers” or “you”) and by users that have gained access to the Chromatic Service through Customer accounts (“Users”). By using the Chromatic Service, you acknowledge that you and your Users are responsible for compliance with this AUP, and agree to be bound by this AUP. You are responsible for violations of this AUP by any User that accesses the Chromatic Service through your account. We reserve the right to remove content, suspend or otherwise terminate your access to the Chromatic Service for usage that violates or may violate the AUP or that otherwise appears unlawful.
The following activities are prohibited:
- Violate any law, statute, ordinance, or regulation (including without limitation the laws and regulations governing export control, unfair competition, anti-discrimination, or false advertising);
- Use or interact with the Chromatic Service in a manner that harasses, bullies, defames or threatens a specific person or entity or is fraudulent, deceptive, or otherwise objectionable (determined by Chromatic);
- Attempt to undermine or jeopardize the security or integrity of the Chromatic Service and other user accounts;
- Impersonate any person or entity;
- Send unsolicited messages (SPAM);
- “Crawl” or “scrape” any page of the Chromatic Service;
- Interfere or disrupt the Chromatic Service or the servers and networks which are connected to the Chromatic Service;
- Use the Chromatic Service for any purpose other than the legitimate testing or validation of websites, mobile websites and applications, team collaboration, and documentation.
You and any User shall not, nor allow any third party to upload, record, publish, post, link to, transmit or distribute any content, nor otherwise utilize the Chromatic Service in a manner that:
- infringe or violate the copyright, patent, trademark, service mark, trade name, trade secret, or other intellectual property rights of any third party or Chromatic, or any rights of publicity or privacy of any party;
- advocates, promotes, incites, instructs, informs, assists and/or otherwise encourages violence, inappropriate behavior, hateful or harassing behavior, and/or any illegal activities;
- promotes, solicits or comprises inappropriate, harassing, insensitive, abusive, profane, hateful, defamatory, libelous, threatening, obscene, indecent, vulgar, pornographic or otherwise objectionable or unlawful content or activity.
---
## Billing
URL: https://chromatic.com/docs/billing
> Chromatic billing information
# Billing
Chromatic bills customers monthly based on their subscription date. For example, if you subscribed on February 14, you'll be billed on the 14th of each month.
Each plan comes with a set amount of billed snapshots per month. If you go beyond that amount, then you are charged for additional billed snapshots. All counts reset at the end of each month.
Why am I not receiving invoices?
Ensure that the Chromatic invoice email (`invoice+statements@chromatic.com`) and `chromatic.com` domain is added to your approved list.
Can we pay annually for our self-serve subscription?
Not at this time. We currently only support monthly payments for our self-serve customers. If you're interested in annual payments, consider upgrading to an [Enterprise plan](https://www.chromatic.com/enterprise).
## Snapshots
The monthly bill is calculated based on the number of billed [snapshots](/docs/snapshots). There are two types of snapshots:
- **Captured (1 billed snapshot):** Chromatic performs the full suite of work, including taking screenshots or capturing accessibility data, and running diffs.
- **Turbosnap (0.2 billed snapshot):** Chromatic identifies tests that have no code changes associated with them or their dependencies and copies over the existing snapshots from previous baselines for them.
## How we count billed snapshots
Each test can lead to multiple snapshots depending on the number of browsers/devices, modes, and test types you run. [Visual](/docs/visual) and [accessibility tests](/docs/accessibility) incur billed snapshots; [interaction tests](/docs/interactions) don't.
Billed snapshots are calculated based on the number of tests, builds, browsers, and modes. You can use our [snapshot calculator](https://www.chromatic.com/snapshot-calculator) to estimate your monthly snapshot usage and see the underlying math.
```
visual snapshots = Tests x Builds x Browsers x Modes
accessibility snapshots = Tests x Builds x Modes
```
### Without TurboSnap enabled
Chromatic captures a new snapshot for every test in every build resulting in higher usage. The total billed snapshots are calculated as follows:
```
billed snapshots = visual snapshots + accessibility snapshots
```
### With TurboSnap enabled
Chromatic copies over snapshots from existing baselines. We refer to these as "turbosnaps", which cost 0.2 billed snapshots each. For the remaining stories, Chromatic captures new snapshots as usual. Therefore, the total billed snapshots are calculated as follows:
```
Visual snapshots = Tests with changes x Builds x Browsers x Modes
Accessibility snapshots = Tests with changes x Builds x Modes
turbosnaps = (Tests - Tests with changes) x Builds x Browsers x Modes
billed snapshots from turbosnaps = turbosnaps * 0.2
billed snapshots = visual snapshots + accessibility snapshots + billed snapshots from turbosnaps
```
### Billed snapshots are counted at the account level
If your account has multiple projects, we sum the billed snapshots each project incurs to get your total usage. You can see a breakdown of billed snapshots by project in the [usage report](/docs/billing/usage-reports) for each billing period.
A couple more things to note:
- Your [billing page](#view-current-months-usage) will include a breakdown of captured snapshots vs turbosnaps.
- If you use our free [Publish Storybook](/docs/publish) service only (i.e., UI Test and UI Review is disabled) you won't incur billed snapshots.
### View current month's usage
Find the current month's usage in the Plan section of the Billing page.

### Additional billed snapshots
Each plan comes with a specific number of included billed snapshots. If your usage reaches that amount:
1. **Free plan:** Review and testing will be paused once you use all 5,000 included billed snapshots per month. You can resume testing by upgrading to a paid plan or waiting until your included billed snapshots reset at the end of the billing cycle. 
2. **Paid plans:** Review and testing will not be interrupted. Additional billed snapshots beyond the included amount are charged at the end of the billing period.
For information on the number of billed snapshots included in each plan and the cost of additional snapshots, refer to the [pricing page](https://www.chromatic.com/pricing). You can also set [usage alerts](/docs/billing#usage-alerts) to notify a designated email address when your usage reaches a certain number of billed snapshots.
Alternatively, you may consider upgrading to an enterprise plan for more billed snapshots. Contact us via in-app chat or email to learn more.
### Usage alerts
Keep track of your account's snapshot usage by setting up a usage alert. When your usage reaches a certain snapshot threshold in a billing period, we'll notify the designated email address.
For example, if you want to get a notification when you use 90% of the 35,000 billed snapshots in the Starter plan, you'd set the snapshot alert threshold to 31,500.

### Data retention
Chromatic guarantees a minimum of 12 months of data retention for builds and snapshots on all plans.
## Change plans
Change your plan in account settings. All changes are prorated to the day. That means you can change your plan anytime in the month without getting charged unnecessarily for unused billed snapshots.
## Legacy plans
In September 2025, we announced adjustments to our paid plans. The Standard plan has been renamed the Pro plan, while the now "Legacy Pro plan" is no longer available to new customers. However, we will continue to honor the benefits of the Legacy Pro plan for all existing customers on that plan as long as they remain subscribed.
These changes will take effect with the November 2025 billing cycle.
## Invoices
Invoices are generated each month on your account's Billing page. Click to see a PDF of the amount owed and a breakdown of billed snapshot usage.

### Email invoices to your billing or finance manager
By default, Chromatic sets the account's billing email to the email address of the person who signed up for the plan. We send all billing and account related emails to this address.
Go to the Payment section on the Billing page to change the billing email associated with your account. Click "Change email".

### Refunds
If you aren’t happy with Chromatic, we’ll refund your money. We want customers to ship consistent UIs, save time, and build bulletproof component libraries.
If it’s not working out for you, contact us via our in-app chat or [email](mailto:support@chromatic.com) to get a refund for your current month's usage.
Subsequent refunds will be credited to your account for use in future invoices.
---
## Usage reports & exports
URL: https://chromatic.com/docs/billing/usage-reports
> View and export detailed billing period usage reports, including a CSV breakdown of every build
# Usage reports & exports
Access usage reports for each billing period on the billing page. These reports offer a detailed breakdown of usage and display the invoice statement.
The **usage section** provides a per-project summary of Visual, Accessibility and TurboSnap snapshots utilized.
The **invoice** includes details of the active plan for the billing period, the base number of billed snapshots included, charges for additional billed snapshots, and a link to download a PDF copy of the invoice (available for all billing periods).

To access the current billing period's usage report, click on the "View usage" button in the Plan section.

To view previous billing periods, click on the card for the desired period in the Statements section.

## Export usage data as a CSV
You can generate a CSV file with a detailed list of every build within a build period. Click on a billing period to view the Usage Report, then click the "Download CSV" button to get a CSV file for that period.
The CSV file provides a granular breakdown of usage and includes the following columns:
- Date
- Creation date and time of the build (ISO 8601)
- App ID
- Unique Chromatic project identifier
- Build ID
- Unique Chromatic build identifier
- Repository slug
-
Owner and name of the Git repository linked to the project (`:`)
- Branch name
-
Git branch name for which the build was created, prefixed with `:` if the build originates from a fork
- Build number
- The incremental number for this build
- turbosnaps
-
Number of snapshots copied by [TurboSnap](/docs/billing#with-turbosnap-enabled).
- TurboSnap Bail Reason
-
Explains why a TurboSnap triggered a full rebuild. For more details, check out the [TurboSnap docs](/docs/turbosnap/troubleshooting#what-do-the-turbosnap-bail-reasons-in-my-usage-report-mean).
- Chrome snapshots
- Number of captured visual Chrome snapshots
- Firefox snapshots
- Number of captured visual Firefox snapshots
- Safari snapshots
- Number of captured visual Safari snapshots
- Edge snapshots
- Number of captured visual Edge snapshots
{' '}
- Internet Explorer snapshots
- Phased out in 2023. Number of captured visual Internet Explorer snapshots.
- Accessibility snapshots
- Number of captured accessibility snapshots
## Export monthly and yearly usage data as CSV
Usage reports export your account's activity for the chosen billing period. You can also download a CSV of your monthly or yearly snapshot usage across all your projects' builds. Click the "Generate report" button and select a year and/or month, and then click "Generate CSV."
For a custom date range or to get the report in JSON format, contact us via in-app chat or [email](mailto:support@chromatic.com).

---
## Infrastructure upgrades
URL: https://chromatic.com/docs/infrastructure-upgrades
> Learn how Chromatic handles browser rendering changes to be minimally disruptive
# Infrastructure upgrades
Chromatic's browser infrastructure is periodically upgraded. This can lead to changes in how your stories render due to underlying rendering engine upgrades or tweaks in how stories are executed and snapshotted.
Typically, upgrades happen without you needing to do anything. But more extensive upgrades may lead to noticeable rendering differences. Here's what we do in those cases.
## How to upgrade your project
When an infrastructure upgrade is available you're notified in the app. You choose which projects are updated and when within a four week time window. Once the time window has passed, all projects will automatically upgrade.
### Opt-in to upgrade
Opt-in to the upgrade on the Manage screen for your project. This will switch you over to the new infrastructure and migrate UI test baselines using **upgrade builds**.

### Upgrade builds
Chromatic runs an "upgrade build" to ensure stories are snapshotted using a consistent infrastructure. That allows you to migrate your UI test baselines between infrastructures without test flake or false positives. Each open branch gets its own upgrade build(s).
An upgrade build isolates all the UI changes caused by swapping infrastructure in one build. Unlike typical builds, upgrade builds don't snapshot new code. They work by **rerunning** the most recent build on that branch using the new infrastructure.

Existing baselines that were snapshotted on old infrastructure are re-snapshotted using the new infrastructure. This ensures that subsequent builds are compared "apples-to-apples" to baselines snapshotted on the same infrastructure.
### Changes are auto-accepted
Visual differences between old and new infrastructure are auto-accepted. Since the upgrade build compares the same code but on different infrastructure, minor visual variation can be attributed to the infrastructure upgrade itself (not your code).
Future builds will use the upgrade build's auto-accepted baselines as the source of truth.

### Release notes for infrastructure upgrades
Read about the infrastructure changes in the [release notes](/docs/infrastructure-release-notes).
| Capture Stack version | Status |
| :-------------------------------------------------------: | -------------------------------------------------------------- |
| [Version 9](/docs/infrastructure-release-notes#version-9) | Upgrade window open ([opt in for upgrade](#opt-in-to-upgrade)) |
| [Version 8](/docs/infrastructure-release-notes#version-8) | General availability |
| [Version 7](/docs/infrastructure-release-notes#version-7) | No longer available |
| [Version 6](/docs/infrastructure-release-notes#version-6) | No longer available |
| [Version 5](/docs/infrastructure-release-notes#version-5) | No longer available |
| [Version 4](/docs/infrastructure-release-notes#version-4) | No longer available |
| [Version 3](/docs/infrastructure-release-notes#version-3) | No longer available |
| [Version 2](/docs/infrastructure-release-notes#version-2) | No longer available |
| [Version 1](/docs/infrastructure-release-notes#version-1) | No longer available |
---
### Frequently asked questions
Can I run tests on a specific browser version?
Chromatic does not support running tests on specific browser versions.
With each infrastructure upgrade, our goal is to provide you with the latest stable browser versions, enabling a consistently flake-free testing environment while simplifying our infrastructure and customer support.
Read our [documentation](/docs/browsers) to learn more about enabling additional browsers.
Can I continue using the previous capture stack version?
When a new capture stack is released in **beta**, you’ll receive an invitation to opt in. Once the general rollout begins, you’ll have a limited upgrade window to switch over. After that window closes, all projects will automatically move to the new capture stack, and the older version will no longer be available.
In short, you cannot remain on the older stack indefinitely.
---
## Notifications
URL: https://chromatic.com/docs/notifications
> Control when and how you receive activity notifications
# Notifications
Chromatic sends email notifications to keep [collaborators](/docs/access/collaborators) in the loop. You have control over when and how these notifications are delivered.
### [UI Tests](/docs#test-how-uis-look--function)
In UI Tests, Chromatic emails the build owner when there are changes to a build and when there are discussions. If you're not the build owner but participate in a discussion thread, you'll get notified of replies for that discussion.
### [UI Review](/docs/review)
In UI Review, Chromatic emails the PR owner and any participants when a discussion begins, is replied-to, or gets resolved.
### Change the default email address
To set the default email address, go to the [Profile](https://www.chromatic.com/profile) page.

### Forward emails for different projects to other addresses
To adjust which activities trigger emails and where they get sent, go to the [Notifications](https://www.chromatic.com/notifications) page.
By default, notifications get sent to your default email address. If you signed up via GitHub, Bitbucket, or GitLab, Chromatic will retrieve the email addresses associated with your account from your Git provider. You can forward notifications to any of these email addresses.
---
### Frequently asked questions
Why am I not getting email notifications of discussions?
If you signed up to Chromatic via the supported Git providers (e.g., GitHub, GitLab, BitBucket), notifications are sent automatically to the email address you have configured for any discussion you've subscribed to.
Still, if you do not see any notifications, this could be an issue with your local Git configuration. Run the following command to verify which email is configured:
```shell
git config user.email
```
In case you need to change it, you can run the following command:
```shell
git config user.email 'your@email.com'
```
---
## Open source sponsorships
URL: https://chromatic.com/docs/open-source
> Chromatic sponsors open source component libraries
# Open source sponsorships
Chromatic sponsors open source component libraries and design systems with free usage. As open source maintainers ourselves, we know how tough it can be to get professional tools that'll help your project grow.
Chromatic supports the open source workflow out of the box. We mirror repository permissions for maintainers while allowing read-only access to viewers.
See if your project qualifies – write to us via in-app chat.
## What's the eligibility criteria for OSS sponsorship?
Chromatic offers a free plan (35k snapshots per month, Chrome only) to open-source design systems or UI component libraries that meet the following criteria:
- Community-led project with any of the following:
- Over 100 contributors
- Over 40k weekly npm DLs
- Over 10k GitHub stars
- UI library or design system built specifically for a company:
- Over 5 contributors
- UI library or design system built for Government organizations:
- Over 5 contributors
- Must be a national-level or higher organization (e.g., European Union, Gov.UK, US Digital Service), not a local or municipal organization (e.g., State of Massachusetts).
## Considerations
Open Source Storybooks are [**publicly visible**](/docs/access/collaborators#visibility). Custom domains can be set up for Open Source accounts, even for [free ones](/docs/permalinks#prerequisites).
---
## Privacy Policy
URL: https://chromatic.com/docs/privacy-policy
> Chromatic Privacy Policy
# Privacy and Cookies Notice
Chroma Software, Inc.®
Updated: May 21, 2025
Chroma Software, Inc., a business corporation (herein “Chromatic”, “we”, “us” or “our”), based in the United States and headquartered at 548 Market St. \#26384 San Francisco, CA 94104, is committed to protecting and respecting your privacy and personal information (herein, “personal information” refers to any information that identifies you or is about you as an individual). This Privacy Notice describes how we collect, use and share personal information through your (herein, “you” or “your” refers to the person accessing our products and services) interaction with our website: [https://www.chromatic.com/](https://www.chromatic.com/), (herein, “Website”).
Please read this Privacy Notice carefully so you can make an informed decision about your use of our Website.
## Contents
- [Privacy and Cookies Notice](#privacy-and-cookies-notice)
- [Contents](#contents)
- [1. Scope of This Privacy Notice](#1-scope-of-this-privacy-notice)
- [2. How We Collect Personal Information](#2-how-we-collect-personal-information)
- [3. Categories of Personal Information We Collect](#3-categories-of-personal-information-we-collect)
- [4. How We Use Personal Information](#4-how-we-use-personal-information)
- [6. Links to Third-party Websites](#6-links-to-third-party-websites)
- [7. Collection of Personal Information From Minors](#7-collection-of-personal-information-from-minors)
- [8. Sharing and Sale of Your Personal Information](#8-sharing-and-sale-of-your-personal-information)
- [9. Protection of Personal Information](#9-protection-of-personal-information)
- [10. How Long We Keep Your Personal Information](#10-how-long-we-keep-your-personal-information)
- [11. Where We Transfer Your Personal Information](#11-where-we-transfer-your-personal-information)
- [12. Cookies Notice](#12-cookies-notice)
- [13. Your Privacy Rights](#13-your-privacy-rights)
- [14. Notice to European Users](#14-notice-to-european-users)
- [15. Notice to Canadian Users](#15-notice-to-canadian-users)
- [16. Notice to Australian Users](#16-notice-to-australian-users)
- [17. Do Not Track Signals and Third-Party Tracking](#17-do-not-track-signals-and-third-party-tracking)
- [18. Questions and Contacts](#18-questions-and-contacts)
- [19. Changes to Our Privacy Notice](#19-changes-to-our-privacy-notice)
## 1. Scope of This Privacy Notice
This Privacy Notice applies to anyone who interacts with us through our Website, which manages our product and service offerings. This Privacy Notice provides details about the personal information we collect about you, how we use it, and how we protect and safeguard your personal information. This Privacy Notice also provides information about your rights as an individual, in relation to the personal information that we collect from you.
## 2. How We Collect Personal Information
We may collect personal information about you from various interactions on our Website. These interactions may include creating an account, placing an order, utilizing the comments feature, or utilizing the chat bot. Other interactions may include signing up for our newsletter or other marketing materials, and through your contact and interaction with us on social media, blogs, surveys, and/or product feedback communications.
We may also collect certain online identifiers, which may be considered personal information, through your use of our Website. This information includes online activity information and technical information about your usage activities, to the extent that such information constitutes personal information. We may also set cookies on your web browser or use other tracking technologies when you interact with websites, applications, or advertisements in our network. This allows us to collect certain websites’ usage data and online identifiers which, under certain privacy regulations, may be considered personal information. However, in many cases such data may be aggregated or anonymized, and may only ever be used to attempt to identify you as an individual where we have a legal basis to do so (for example in the case of an investigation into fraudulent transactions). For more information, refer to our “Cookies Notice” in section 12 below.
## 3. Categories of Personal Information We Collect
We may collect, and may have collected in the past, any of the following categories of personal information from you:
- Contact information, such as, email address, and phone numbers;
- Personal Identifiers, such as your name, alias, and other unique personal identifiers;
- Financial details, such as details about your credit or payment card or payment account, including details of account numbers, payment details, or billing addresses;
- Account Information, such as your username, and consent and preferences (e.g., to receive newsletters);
- Credentials, such as passwords, password hints, and similar security information used for authentication and account access;
- Commercial information, such as purchase history;
- Geolocation data, such as physical location or movements;
- We may collect information about interaction with, and responses to, our marketing communications;
- Any personal information you send to us in emails, attachments, and other communications that you send us or otherwise contribute.
Data and online identifiers we collect through our Website (e.g., through cookies and other tracking technologies) may include IP addresses, preferences, web pages visited prior to coming to our Website, information about browser, network or device (such as browser type and version, operating system, internet service provider, preference settings, unique device IDs, language, and other regional settings), and information about how you interact with our Website (such as pages visited, timestamps, clicks, scrolling, browsing times, and load times). For more information refer to our “Cookies Notice” in section 12 below.
## 4. How We Use Personal Information
Your personal information may be used by us, our employees and service providers, and disclosed to third-parties for the following purposes:
- **Communicate with you**, including by responding to questions or communications you send to us (e.g., as a response to communications you have sent via online webforms or email), and other relevant service or product-related announcements;
- **Perform our services**, including personalizing Website user experience (e.g., delivering relevant content and product offerings), order fulfilment and fulfilling transactions, maintaining accounts and contracts, providing customer service, informing and updating our investors, monitoring disputes, or verifying information;
- **Notify you about changes to our products and services;**
- **Manage our affiliate, distributor, and customer relationships**, including to enforce or apply the agreements concerning you (including any applicable agreements between you and us);
- **Perform marketing, including providing relevant details and informational updates related to our products and services, or advertising our products and services online**. This could include “remarketing” or “retargeting”, whereby users of our Website may be marketed to on other third-party websites through use of Marketing Cookies – see “Cookies Policy” section 12 below for further information. In addition to third-party cookies, remarketing may also involve our use of personal information (such as name and email address) collected from you in prior interactions, which may then be used to provide you with relevant updates, marketing, or other information related to your prior interactions with our products and services;
- **Administer promotions** such as offering product discounts, giveaways, or other incentives;
- **To improve the Services,** including undertaking monitoring, market research, trend analysis, and customer satisfaction survey activities to verify, maintain, or improving the quality and types of products and services being provided, including on our Website, or to handle and respond to complaints or questions, analyzing your interactions with our products and services, or acting on feedback you provide through surveys, product feedback, emails, etc.;
- **Audit our transactions and interactions**, for purposes where we have legal grounds to do so, such as security or for regulatory compliance;
- **Detect, remediate, and, if applicable, prosecute any physical security or information security-related or criminal incidents**, including protecting against any illegal activity such as fraud to ensure the security and integrity of our services;
- **Enforce our legal rights and comply with legal or regulatory obligations** including in connection with court orders, complaints, or performance of identity verification to respond to certain requests for information, or to establish, make, or defend against legal claims;
- **Act in the public interest**, in line with any laws that apply;
- **Evaluate job applications and business proposals** (e.g., agreements or requests proposed by affiliates and distributors, or prospective affiliates and distributors);
- **Post customer product comments** on our Website that may contain personal information, such as name. By submitting express written consent, your comment regarding your experience with our products/services could be potentially posted on our Website. If you wish to delete your comment, please contact us at [privacy@chromatic.com](mailto:privacy@chromatic.com) and be sure to include your name, comment location, and contact information.
## 6. Links to Third-party Websites
Our Website may also contain links to and marketing from the websites of third-parties. We have no control over the content or operation of these websites, nor do we control the confidentiality or privacy practices of the website operators. Consequently, any personal information you submit through such website is governed by the privacy policies of the website in question. It is therefore your responsibility to find out about the third-party policies in order to protect your personal information when visiting these third-party websites.
## 7. Collection of Personal Information From Minors
Our Website is not designed or intended to attract children under 13 years of age, and we do not knowingly collect information from minors. By using our Website, you hereby represent that you are at least the age of legal majority in your place of residence. If you believe that we have inadvertently collected personal information from a child under 13 years of age, please contact us at privacy@chromatic.com.
## 8. Sharing and Sale of Your Personal Information
We may disclose your personal information to service providers and other third-parties. In the past, we may have disclosed to such third-parties any of the categories of personal information outlined in the above section 3, “Categories of Personal Information We Collect”, wherever we have legal basis for such sharing. However, we endeavor to share only the minimum relevant personal information that is required to fulfill the business purpose for sharing such personal information.
We may disclose, and may have already disclosed, personal information to the following categories of third-parties:
- **Our service providers** - Our business partners, suppliers and sub-contractors who help us provide our Website, products and services. This includes, for example, our e-commerce platform providers, analytics providers, marketing and advertising service providers, website development and troubleshooting service providers. Our service providers may include, but are not limited to:
- **Intercom.** Intercom assists us in providing a unified customer communications platform for customer interaction and experience management. For more information about Intercom’s privacy practices, visit [https://www.intercom.com/legal/privacy](https://www.intercom.com/legal/privacy).
- **Cloudflare.** Cloudflare assists us in analyzing the performance of the Site and the Services. For more information about Cloudflare’s privacy practices, visit https://www.cloudflare.com/privacypolicy/.
- **Stripe.** Stripe assists us in processing your payments. For more information about Stripe’s privacy practices, visit [https://stripe.com/privacy](https://stripe.com/privacy).
- **Google Analytics/Ads.** Google helps us better understand your use of our Website and services. Google Analytics collects information such as how often users visit our Website, what pages are visited, and what other sites may have been used prior to visiting. We also use Doubleclick by Google in order to serve ad based on a user’s prior visit to websites, and YouTube Ads in order to help us advertise the Services. Google’s ability to use and share information collected by Google Analytics about your visits to our Website is restricted by the [Google Analytics Terms of Use](https://marketingplatform.google.com/about/analytics/terms/us/) and the [Google Privacy Policy](https://policies.google.com/privacy). You can also opt-out of and manage your preferences for Google’s use of personalized advertising and related cookies by visiting Google’s [Ad Settings](https://support.google.com/accounts/answer/2662856?co=GENIE.Platform%3DDesktop&hl=en), and Google Analytics also offers an opt-out mechanism for the web available [here](https://tools.google.com/dlpage/gaoptout/).
- **HubSpot.** HubSpot is an analytics provider that utilizes cookie and usage data collected to track and examine the use of the Site and the Services, analyze demographic information, and to prepare reports on user activities and share them with other HubSpot services. HubSpot may use the data collected to contextualize and personalize the ads of its own advertising network. You can find out more information about HubSpot and the data it collects at [https://legal.hubspot.com/privacy-policy](https://legal.hubspot.com/privacy-policy).
- **Microsoft Clarity.** Microsoft Clarity assists us in capturing information regarding how you use and interact with the Site through behavioral metrics, heatmaps, and session replay. We use this information to improve and market our products and services and fraud prevention/security. You can find out more information about Microsoft Clarity and the data it collects at [https://privacy.microsoft.com/en-US/privacystatement](https://privacy.microsoft.com/en-US/privacystatement).
- **Gatsby.** Gatsby helps us provide functionality for the Site. You can view Gatsby’s privacy policy here: [https://www.gatsbyjs.com/privacy-policy](https://www.gatsbyjs.com/privacy-policy).
- **Meta/Facebook.** Meta helps us to customize our advertising and to serve you ads on your social media based on your browsing behavior. This allows your behavior to be tracked after you have been redirected to one of our Websites by clicking on the Meta/Facebook ad. The Meta Pixel stores a cookie on your device to enable us to measure the effectiveness of Facebook ads for statistical and market research purposes. We do not have access to the information collected through the Meta Pixel. However, the information collected via the Meta Pixel is also stored and processed by Facebook. You can learn more about Meta’s privacy preferences by visiting [https://www.facebook.com/privacy/policy/](https://www.facebook.com/privacy/policy/).
- **Adobe Analytics.** Adobe Analytics helps us to understand your use of our Website and services. Adobe uses cookies or other tracking technologies to help us analyze how users interact with the Sites and Services, compile reports on their activity, and provide other services related to their activity and usage. The technologies used by Adobe may collect information such as your IP address, time of visit, whether you are a returning visitor, and any referring website. You can opt out of the use of Adobe Analytics by visiting https://www.adobe.com/privacy/opt-out.html.
- **Common Room.** We utilize Common Room in order to aid us with understanding your use of our Website and services. You have view Common Room’s privacy policy by visiting https://www.commonroom.io/privacy-policy/.
- **Our professional advisers** - Including accountants, lawyers and other professional advisers that assist us in carrying out our business activities;
- **Government authorities and third-parties involved in legal or regulatory action** - External agencies and organizations (including the police and the relevant local authority) for the purpose of complying with applicable legal and regulatory obligations.
We may also disclose your personal information to other third-parties, for example:
- In the event that we sell or buy any business or assets, or restructure our business or assets, we may disclose your personal information to the prospective affiliate, seller or buyer of such business or assets;
- If we are under a duty to disclose or share your personal information in order to comply with any legal obligation.
## 9. Protection of Personal Information
We are committed to protecting the security of your personal information. We use a variety of security technologies and procedures to help protect your personal information from unauthorized access, use, or disclosure. No method of transmission over the internet, or method of electronic storage, is 100% secure, however. Therefore, while we use reasonable efforts to protect your personal information, we cannot guarantee its absolute security.
## 10. How Long We Keep Your Personal Information
We will retain your personal information for as long as is necessary for the purposes for which it was collected, or longer if required by applicable law. Those periods are also based on the requirements of applicable data protection laws, applicable legal and regulatory requirements and periods relating to the commencement of legal actions.
## 11. Where We Transfer Your Personal Information
We are headquartered in the United States and we will process your personal information in the United States. Your personal information will be transferred and stored in the United States.
If we transfer personal information outside the European Economic Area (EEA), Asia, or Australia, we will implement appropriate and suitable safeguards to ensure that such data will be protected as required by applicable data protection laws. For further information as to the safeguards we implement please contact [privacy@chromatic.com](mailto:privacy@chromatic.com).
## 12. Cookies Notice
This Cookies Notice applies when using our Website.
**Cookie Overview and How They are Used on Our Website**
Our Website uses cookies to distinguish you from other users of our Website. Cookies are pieces of information stored directly on the device you are using by your browser. Cookies allow us to recognize your device and allows our Website to remember certain information about you (such as marketing preferences or account information), and to perform analytics and other functions in relation to your, and others’, use of our Website. This helps us to provide you with a good, secure, and personalized experience when you browse our Website and allows us to improve our Website over time.
Cookies set by us on our Website, named “first-party” cookies, are used to help evaluate and enable performance and secure functionality of our Website. These may enable us to collect or remember certain usage data and data about your device. This may include data on website pages visited prior, during and after visiting our Website, clicks or interactions made with the pages on our Website, consents and preferences, time spent on our pages and date/timestamps of visits and interactions, device identifiers such as IP address or operating system type, and browser type.
We also use “third-party” cookies, which are cookies from a website domain other than our Website. These are used for our Website’s analytics, site functionality, security, and marketing efforts by sharing usage and device-related data with relevant third-parties.
We, and third-parties performing services on our behalf, may use cookies for security purposes (for example, in helping prevent fraud), to facilitate navigation, to display information more effectively, and to personalize your experience while using our services. In addition, we may use the information to gather statistical information about the usage of our services in order to understand how they are used, continually improve their design and functionality, and assist us with resolving questions about them. Cookies further allow us to present to you the advertisements or offers that are most likely to appeal to you. We may also use cookies to track your responses to our advertisements and we may use cookies or other files to track your use of other websites.
**Web Beacon Overview and How They are Used on Our Website**
The pages of our Website contain images (called a “single-pixel gif” or “web beacons”) that allow our third-party service providers and us to count page views or to collect other anonymous data. In general, any electronic image viewed as part of a web page, including an ad banner, can act as a web beacon. Web beacons are typically very small, usually 1 by 1 pixel in size, but their presence can be easily seen with your browser’s inspection tools. Web beacons are small in order to minimize both their display and their loading time. Our web beacons may collect, gather, monitor or share personal information about our online service visitors for web tracking purposes; they also may be used to compile anonymous, aggregated statistics about the usage of our online services.
For tracking purposes, we use web beacons on our Website along with other technical methods. We also employ third-party services (e.g., Twitter) that collect data remotely through the use of web beacons. This service then returns the completely anonymous data to us as site traffic reports.
**Types of Cookies on Our Website**
We use the following types of cookies for the following purposes:
- **Strictly Necessary Cookies**: These cookies are essential for you to browse our Website and use its intended functionality, including accessing secure areas of our Website. These cookies cannot be opted-in or out of.
- **Performance Cookies**: These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our Website. They help us to know which pages are the most and least popular and see how visitors move around our Website. All information these cookies collect is aggregated and therefore anonymous. If you do not allow these cookies, we will not know when you have visited our site.
- **Functional Cookies**: These cookies enable the Websites to provide enhanced functionality. They may be set by us or by third-party service providers whose services we have added to our pages (for example, embedding videos on webpages).
- **Marketing Cookies**: These cookies may be set on our Website by our advertising and marketing service providers. They may be used by those companies to build a profile of your interests and show you relevant advertisements on other sites. They are based on uniquely identifying your browser and internet device. This recognition is used to serve relevant adverts, links, or other information about our products and services to users visiting other websites after having previously visited our Website or interacted with our products and services. If you consent to these cookies, you may experience targeted advertising.
## 13. Your Privacy Rights
You have several choices regarding the use of your personal information on the Site and our Services. Depending on the jurisdiction you reside in, you may have certain additional rights in relation to the personal information we have collected about you, which are detailed in jurisdiction-specific sections of this Privacy Policy below.
**Email Communications.** We may periodically send you free newsletters and e-mails that directly promote the use of our Site or Services. When you receive newsletters or promotional communications from us, you may indicate a preference to stop receiving further communications from us and you will have the opportunity to “opt-out” by following the unsubscribe instructions provided in the e-mail you receive or by contacting us directly (please see [contact information](#18-questions-and-contacts) below). Despite your indicated e-mail preferences, we may send you Service-related communications, including notices of any updates to our Privacy Policy or terms of service/terms of use.
**Cookies.** If you decide at any time that you no longer wish to accept cookies from our Site for any of the purposes described above, then you can instruct your browser, by changing its settings, to stop accepting cookies or to prompt you before accepting a cookie from the websites you visit. Consult your browser’s technical information. If you do not accept cookies, however, you may not be able to use all portions of the Site or all functionality of the Services. If you have any questions about how to disable or modify cookies, visit [https://www.allaboutcookies.org/](https://www.allaboutcookies.org/).
## 14. Notice to European Users
The information provided in this “Notice to European Users” section applies only to individuals in Europe.
**Personal information**. References to “personal information” in this Privacy Policy are equivalent to “personal data” governed by European data protection legislation.
**Controller.** We are the controller of your personal information covered by this Privacy Policy for the purposes of European data protection legislation, except to the extent that we process your personal information on behalf of our customer, including personal information that we process on behalf of our Clients, in which case our customer is the controller of your personal information, and we are the processor.
We have appointed a Data Protection Officer, whose contact information is:
```
DP Dock DPO Services GmbH
Grüffkamp 10
24159 Kiel
Germany
chromatic@dp-officer.com
```
**Legal bases for processing**. We use your personal information only as permitted by law. Our legal bases for processing the personal information described in this Privacy Policy are described in the table below.
| Processing Purpose | Legal basis |
| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **To operate the services** | Processing is necessary to perform the contract governing our provision of the services or to take steps that you request prior to signing up for the services. If we have not entered into a contract with you, we process your personal information based on our legitimate interest in providing the services you access and request. |
| **To communicate with you Notify you of changes to our products/services To manage affiliate, distributor and customer relationships To market, or advertise our products/services For administer promotions** **To improve the services** **To provide security** **For compliance, fraud prevention and safety** **To act in the public interest** **For employment purposes To post customer product comments** | These activities constitute our legitimate interests. We do not use your personal information for these activities where our interests are overridden by the impact on you (unless we have your consent or are otherwise permitted to by law). |
| **To comply with law To audit our transactions and interactions** | Processing is necessary to comply with our legal obligations. |
| **With your consent** | Processing is based on your consent. Where we rely on your consent you have the right to withdraw it at any time in the manner indicated when you consent or in the services. |
**Use for new purposes.** We may use your personal information for reasons not described in this Privacy Policy where permitted by law and the reason is compatible with the purpose for which we collected it. If we need to use your personal information for an unrelated purpose, we will notify you and explain the applicable legal basis.
**Sensitive personal information.** We ask that you not provide us with any sensitive personal information (e.g., information related to racial or ethnic origin, political opinions, religion or other beliefs, health, biometrics or genetic characteristics, criminal background or trade union membership) on or through the services, or otherwise to us.
If you provide us with any sensitive personal information when you use the services, you must consent to our processing and use of such sensitive personal information in accordance with this Privacy Policy. If you do not consent to our processing and use of such sensitive personal information, you must not submit such sensitive personal information through the services.
**Automated Decision-Making and Profiling.** We do not use automated decision-making and/or profiling in regard to your personal information in connection with the services.
**Retention.** We retain personal information for as long as necessary to fulfill the purposes for which we collected it, including for the purposes of satisfying any legal, accounting, or reporting requirements, to establish or defend legal claims, or for fraud prevention purposes.
To determine the appropriate retention period for personal information, we consider the amount, nature, and sensitivity of the personal information, the potential risk of harm from unauthorized use or disclosure of your personal information, the purposes for which we process your personal information and whether we can achieve those purposes through other means, and the applicable legal requirements.
When we no longer require the personal information we have collected about you, we will either delete or anonymize it or, if this is not possible (for example, because your personal information has been stored in backup archives), then we will securely store your personal information and isolate it from any further processing until deletion is possible. If we anonymize your personal information (so that it can no longer be associated with you), we may use this information indefinitely without further notice to you.
**Your rights.**
European data protection laws give you certain rights regarding your personal information. If you are located within the European Economic Area, the United Kingdom or Switzerland, you may ask us to take the following actions in relation to your personal information that we hold:
- **Access.** Provide you with information about our processing of your personal information and give you access to your personal information.
- **Correct.** Update or correct inaccuracies in your personal information.
- **Delete.** Delete your personal information.
- **Transfer.** Transfer a machine-readable copy of your personal information to a third party of your choice.
- **Restrict.** Restrict processing of your personal information.
- **Object.** Object to our reliance on our legitimate interests as a legal basis of our processing of your personal information that impacts your rights.
You may submit these requests by email to [privacy@chromatic.com](mailto:privacy@chromatic.com) or our postal address provided below. We may request specific information from you to help us confirm your identity and process your request. Applicable law may require or permit us to decline your request. If we decline your request, we will tell you why, subject to legal restrictions. If you would like to submit a complaint about our use of your personal information or our response to your requests regarding your personal information, you may contact us or submit a complaint to the data protection regulator in your jurisdiction. You can find your data protection regulator [here](https://edpb.europa.eu/about-edpb/about-edpb/members_en).
**Cross-Border Data Transfer.**
If we transfer your personal information out of Europe to a country not deemed by the European Commission to provide an adequate level of personal information protection, the transfer will be performed:
- Pursuant to the recipient’s compliance with standard contractual clauses or Binding Corporate Rules;
- Pursuant to the consent of the individual to whom the personal information pertains; or
- As otherwise permitted by applicable European requirements.
You may contact us at [privacy@chromatic.com](mailto:privacy@chromatic.com) or via our contact information below if you want further information on the specific mechanism used by us when transferring your personal information out of Europe.
**EU Representative**
DP-Dock has been appointed as our representative in the European Union for data protection matters, pursuant to Article 27 of the GDPR. If you are in the [European Economic Area](https://verasafe.com/public-resources/eea-members/), DP-Dock can be contacted in addition to [privacy@chromatic.com](mailto:privacy@chromatic.com), only on matters related to the processing of personal data. To make such an inquiry, please contact DP-Dock at:
Website: [www.dp-dock.com](https://www.dp-dock.com/)
Email: [chromatic@gdpr-rep.com](mailto:chromatic@gdpr-rep.com)
```
EU:
DP-Dock GmbH, Attn: Chroma Software, Inc.,
Ballindamm 39, 20095
Hamburg, Germany
```
```
UK:
DP Data Protection Services UK Ltd., Attn: Chroma Software, Inc.,
16 Great Queen Street, Covent Garden,
London, WC2B 5AH, United Kingdom
```
## 15. Notice to Canadian Users
The information provided in this “Notice to Canadian Users” section applies only to individuals in Canada. Individuals located in Canada have certain rights pursuant to Canada’s Personal Information Protection and Electronic Documents Act (PIPEDA) and any applicable substantially similar provincial legislation (“Canadian data protection legislation”).
**Personal information.** References to “personal information” in this Privacy Policy are equivalent to “personal information” governed by Canadian data protection legislation.
**Consent.** By using the services and providing personal information to us, you are consenting to the collection, use and disclosure of your personal information as described in this Notice. If you do not consent to the processing of your personal information in accordance with this Notice, please do not access or continue to use the services or otherwise provide any personal information to us.
**Your rights.**
You have certain rights with respect to your personal information under Canadian data protection legislation. Subject to certain exceptions and limitations, and depending upon the province where you reside, such rights may include:
- **To withdraw consent.** The right to withdraw your consent to the collection, use or disclosure of your personal information.
- **To be informed.** The right to be informed of the existence, use, and disclosure of your personal information, and to be provided with an account of the use that has been made or is being made of this information as well as the third parties to which it has been disclosed (including a list of organizations to which your information may have disclosed).
- **To correct.** The right to challenge the accuracy and completeness of your personal information, and have it amended, updated or rectified as appropriate.
- **To challenge.** The right to challenge our compliance with the applicable Canadian data protection legislation.
- **To be forgotten.** The right to restrict the dissemination of your personal information in certain circumstances if such dissemination contravenes a law or court order, or otherwise causes serious injury to your reputation or privacy.
- **Data portability.** The right to receive computerized personal information in a structured, commonly-used and technological format, or to have such personal information transferred directly to any person or body authorized by law to collect such personal information.
**Automated Decision-Making**. We do not use automated decision-making in regard to your personal information in connection with the services.
**Complaints**. The Office of the Privacy Commissioner of Canada (Commissariat à la protection de la vie privée du Canada) advises individuals to file an objection or challenge with the relevant company before lodging a formal complaint with a regulatory authority. If you are dissatisfied with our response to an objection or inquiry, or you if wish to file a complaint with a regulatory authority first, you may file a complaint with the [Office of the Privacy Commissioner of Canada](https://www.priv.gc.ca/). Depending upon the province where you live, you may also (or instead) have the right to file a complaint with the applicable provincial privacy commissioner/regulator.
## 16. Notice to Australian Users
The information provided in this “Notice to Australian Users” section applies only to individuals in Australia. We take reasonable steps to make sure that third party recipients located outside Australia handle your personal information in a secure manner consistent with Australian privacy principles and in accordance with this Privacy Notice. However, we cannot always ensure that such third party recipients will comply with Australian privacy law in relation to your personal information. As such, where a foreign third party recipient does not handle your personal information in compliance with Australian privacy law, we will not be accountable to you and you will not be able to seek redress under Australian privacy law for such non-compliance. By providing us with your personal information, you consent to us disclosing your personal information to recipients outside Australia on this basis.
If you have any questions, concerns or complaints in relation to our handling of your personal information, you can contact us at: [privacy@chromatic.com](mailto:privacy@chromatic.com). If you are unhappy with, or have further questions concerning, our handling of your question, concern, or complaint, you may contact the Office of the Australian Information Commissioner (telephone [\+61 1300 363 992](tel:+611300363992) or email [enquiries@oaic.gov.au](mailto:enquiries@oaic.gov.au)).
## 17. Do Not Track Signals and Third-Party Tracking
Certain mechanisms may allow you to send web browser signals, known as “Do Not Track” (“DNT”) signals, indicating your choice to disable tracking on our Website. We do not respond to browser DNT signals at this time. We may not be aware of or be able to respond to every such mechanism.
Third-parties, other than our service providers (such as our Website’s analytics provider), do not have authorization from us to track which website you visited prior to and after visiting our Website. That said, we cannot control third-party tracking; therefore, there may be some third-party tracking that occurs without our knowledge or consent.
## 18. Questions and Contacts
We hope this Privacy Notice has been helpful in explaining the way we handle your personal information and your rights to control it. For any questions or comments in relation to this Privacy Notice and our privacy practices in general, please contact our Privacy Office who will be pleased to help you by email at [privacy@chromatic.com](mailto:privacy@chromatic.com).
## 19. Changes to Our Privacy Notice
Any changes we make to this Privacy Notice in the future will be posted on this page. The updated Privacy Notice will take effect as soon as it has been updated or otherwise communicated to you.
---
## Security
URL: https://chromatic.com/docs/security
> Security overview and responsible disclosure
# Security policy
Our priority is securing your intellectual property and information.
- [View latest security report](https://app.drata.com/security-report/36340072-4a17-4b9e-80be-1b80562aeb41/30c79316-dfa2-42a8-9b0c-2766cd6ecb89)
- [View SOC 2 Type 2 report](https://security.chromatic.com/)
For questions, contact our security team [security@chromatic.com](mailto:security@chromatic.com).
## Responsible disclosure
Before submitting a vulnerability request, download the **Responsible Disclosure Policy** from [security.chromatic.com](https://security.chromatic.com/) for submission instructions.
### Acknowledgments
Chromatic is grateful to the following individuals for responsibly disclosing security issues, allowing us to make Chromatic safer for everyone.
#### 2025
- [Matt Gill](https://www.linkedin.com/in/mattagill)
- [Mridul Rastogi](https://www.linkedin.com/in/mridul-rastogi-532726292/)
- [Harsh Maheta](https://www.linkedin.com/in/harsh-maheta-7057542a9)
- [Parth Narula](https://www.linkedin.com/in/parth-narula-86283821a)
#### 2024
- [Harish Harishwar](https://x.com/Hari_harishwar)
- [James Zeilenga](https://www.linkedin.com/in/james-zeilenga)
#### 2023
- [Rohit Sharma](https://www.linkedin.com/in/r0x5r/)
- [Professor the Hunter](https://www.linkedin.com/in/bughuntar/)
- [Kunal Mhaske](https://www.linkedin.com/in/kunal-mhaske-59928a170/)
#### 2022
- [Bharat Adhikari](https://www.linkedin.com/in/bharat-adhikari-726337225)
---
## Terms of Service
URL: https://chromatic.com/docs/terms-of-service
> Chromatic Terms of Service
# Terms of Service
Chroma Software, Inc.®
Last Updated: July 28, 2022
The Chroma Terms of Service Agreement (the “Agreement”) is made by and between the customer identified in a Subscription Order that references this Agreement (“Customer”, “You”, or “Your”) and Chroma Software, Inc. (referred to herein as “Chroma”, “We”, “Us”, or “Our”). This Agreement is effective as of the date Customer accepts the terms of this Agreement (the “Effective Date”) or, if earlier, when you use any of the Chroma Services. You understand and agree that Chroma will treat your use of the Chroma Services as acceptance of the Terms from that point onwards. You may not access the Services if You are a direct competitor, except with Chroma’s prior written consent. In addition, You may not access the Services for purposes of monitoring their availability, performance or functionality, or for any other benchmarking or competitive purposes
IN ORDER TO USE CHROMA SERVICES, CUSTOMER AGREES TO THE TERMS AND CONDITIONS OF THIS AGREEMENT WHICH WILL GOVERN CUSTOMER’S PURCHASE AND USE OF CHROMA SERVICES, INCLUDING USES BY CUSTOMER’S EMPLOYEES, CONTRACTORS, AGENTS, AND OTHER AUTHORIZED USERS. IF YOU ARE ACTING ON BEHALF OF AN ENTITY, YOU REPRESENT THAT YOU HAVE THE AUTHORITY TO ENTER INTO THIS AGREEMENT ON BEHALF OF THAT ENTITY. IF CUSTOMER DOES NOT ACCEPT THE TERMS OF THIS AGREEMENT, THEN IT MUST NOT PURCHASE OR USE THE CHROMA SERVICES. IF YOU REGISTER FOR A FREE VERSION OUR SERVICES, THIS AGREEMENT WILL ALSO GOVERN THAT FREE VERSION.
## Table of contents
- [Terms of Service](#terms-of-service)
- [Table of contents](#table-of-contents)
- [1. Definitions](#1-definitions)
- [2. Chroma Delivery of Services and Content](#2-chroma-delivery-of-services-and-content)
- [3. Use of Services and Content](#3-use-of-services-and-content)
- [4. Non-Chroma Providers](#4-non-chroma-providers)
- [5. Fees Payment and Terms Audit](#5-fees-payment-and-terms-audit)
- [6. Proprietary Rights](#6-proprietary-rights)
- [7. Confidentiality](#7-confidentiality)
- [8. Term and Termination](#8-term-and-termination)
- [9. Warranty](#9-warranty)
- [10. Indemnification](#10-indemnification)
- [11. Limitation of Liability](#11-limitation-of-liability)
- [12. General](#12-general)
## 1. Definitions
As used in this Agreement, the following terms shall have the meanings set forth in this Section 1. Certain other terms may be defined in the context of their use elsewhere in the Agreement.
"**Affiliate**" means an entity that directly or indirectly controls, is controlled by, or is under common control with a party to this Agreement. For purposes of this definition, “control” means ownership of at least fifty percent (50%) of the outstanding voting shares of the subject entity.
"**Applications**" means a software application developed by the Customer, its Affiliate(s), or a third-party service provider.
"**Beta Services**" means Chroma Services that are not generally available to customers.
"**Chromatic**” means Chroma’s application testing platform or Chroma’s user interface development platform both hosted at [https://chromatic.com](https://chromatic.com).
"**Confidential Information**" means any and all confidential or proprietary information or materials which have been or are hereafter disclosed or made available by one party (the “Disclosing Party”) to the other (the “Receiving Party”) in connection with this Agreement, whether provided orally or in writing and in any form or media, including without limitation:
- (i) All trade secrets;
- (ii) Existing or contemplated products, services, designs, technology, processes, technical data, engineering techniques, methodologies and concepts and any related information;
- (iii) Information relating to business plans, sales or marketing methods and customer lists or requirements;
- (iv) Customer-specific terms or pricing set forth in business proposals, this Agreement or any Subscription Order and
- (v) where Chroma is the Disclosing Party,
- (a) Chroma’s Pre-Existing Intellectual Property,
- (b) General Enhancements,
- (c) Services Materials,
- (d) Training Materials,
- (e) Documentation, including data security related certification such as SOC 2 reports, and
- (f) Implementation architectures that encompass Chromatic and any of the foregoing items (a) – (e) (“Implementation Architectures”).
"**Content**" means information obtained by Chroma from Our content licensors or publicly available sources and provided to Customer pursuant to an Order Form, as more fully described in the Documentation.
"**Documentation**" means all Chroma published user manuals and guides, regardless of media, that explain or facilitate the use of Chromatic, and other related services.
"**General Enhancements**" means any improvements, modifications, enhancements, or extensions to or derivative works of Chroma Pre-existing Intellectual Property that have or could have general applicability to Chroma customers, including, but not limited to, any modifications to, or derivative works of, Chromatic.
"**Intellectual Property**" means any and all patents, inventions, copyrights, works of authorship, trademarks, trade secrets, know-how, and all other intellectual property (whether registered or unregistered and including the right to register such intellectual property) that are, in each case, protected under the laws of any governmental authority having jurisdiction.
"**Malicious Code**" means code, files, scripts, agents or programs intended to do harm, including, for example, viruses, worms, time bombs and Trojan horses.
"**Pre-Existing Intellectual Property**" means:
- (a) Intellectual Property in existence as of the Effective Date of this Agreement, and
- (b) Intellectual Property that a party creates or develops outside the scope of Services or Support provided under this Agreement and without the use of the other party’s Confidential Information.
“**Subscription Order”** means an online order form or order document executed by the parties that sets forth specific Services and/or Support being purchased by Customer under this Agreement.
“**Service**” or “**Services**” means Chroma technologies, products, support, and/or professional services as set forth in an applicable Subscription Order or free version.
"**Services Materials**" means:
- (a) The processes, know-how, proprietary information and methodologies, document templates, and project tools including, but not limited to, best practice guides and reference architecture materials; and
- (b) Utilities, connectors, scripts, tools, Chromatic implementation code, and other software (and any updates thereto) that, in each case, are used by Chroma to deliver the Services or Support to Customer.
“**Support**” means email and in-app support for Chromatic.
"**Training Materials**" means Chroma training courses, documentation, and other associated training materials, including any and all updates thereto.
"**Training Services**” means Chroma’s training services offerings as set forth in an applicable Subscription Order.
"**User**" means an individual who is authorized by Customer to use Chroma Services, for whom Customer has ordered Chroma Services, and to whom Customer (or Chroma, at Your request) has supplied a user identification and password. Users may include, for example, Customer’s employees, consultants, contractors, agents, or, subject to Chroma’s approval, a third party with which Customer transacts business.
"**We**" "**Us**" or "**Our**" means the Chroma Software company described in Section 12 (Governing Law and Venue).
"**You**" or "**Your**" means the company or other legal entity for which you are accepting this Agreement, and Affiliates of that company or entity.
"**Your Data**" or “**Customer Data**” means electronic data and information submitted by or for You to Chroma Services or collected and processed by or for You using Chroma Services.
## 2. Chroma Delivery of Services and Content
Subject to the terms and conditions of this Agreement, Chroma will provide to Customer the Services and Content agreed by the parties in applicable Subscription Orders. Subscription Orders shall be deemed incorporated herein. Services and Support are only for Customer’s internal use. Customer may not use the Services or Support to supply any training or support services to any third party. All Services and Content delivered under this Agreement are deemed accepted by Customer upon delivery.
**2.1. Provision of Purchased Services**
Chroma will:
- (a) Make the Services and Content available to Customer pursuant to this Agreement and the applicable Subscription Orders, and
- (b) Use commercially reasonable efforts to make Chroma Services available, except for:
- (i) Planned downtime (of which We shall give at least 1 business day notice and which We shall schedule to the extent practicable during the off-peak hours of our choosing), and
- (ii) Any unavailability caused by circumstances beyond Our reasonable control, including, for example, an act of God, act of government, flood, fire, earthquake, civil unrest, war, act of terror, quarantine, strike or other labor problem (other than one involving Our employees), Internet service provider failure or delay, or denial of service attack.
**2.2. Protection of Customer Data**
Chroma will maintain administrative, physical, and technical safeguards for protection of the security, confidentiality (to the extent applicable) and integrity of Customer Data. Those safeguards will include, but will not be limited to, measures for preventing access, use, modification or disclosure of Customer Data by Chroma personnel except:
- (a) To provide Chroma Services and prevent or address service or technical problems,
- (b) As compelled by law in accordance with Section 7 below, or
- (c) As Customer expressly permits in writing.
**2.3 Chroma Personnel**
Chroma will be responsible for the performance of Chroma personnel (including Chroma employees and contractors) and their compliance with Chroma obligations under this Agreement, except as otherwise specified herein.
**2.4. Free Services**
Some Chroma Services may be provided to you without charge up to certain limits as published on the Chroma website or Subscription Order. Usage over this limit may require your purchase of Chroma Services.
**2.5 Beta Services**
From time to time Chroma may invite Customer to try, at no charge, Chroma products or services that are not generally available to Chroma customers ("Beta Services"). You may accept or decline any such trial in its sole discretion. Any Beta Services will be clearly designated as beta, pilot, limited release, early access, developer preview, non-production or by a description of similar import. Beta Services are provided for evaluation purposes and not for production use, are not supported, may contain bugs or errors, and may be subject to additional terms. Beta Services are not considered " Chroma Services" hereunder and are provided "AS IS" with no express or implied warranty. Chroma may discontinue Beta Services at any time in its sole discretion and may never make them generally available. Chroma will have no liability for any harm or damage arising out of or in connection with a Beta Service.
**2.6 Recommendations**
Chroma may, and Customer grants us permission to, make recommendations via Chroma Services or other marketing channels for products or services we think may be of interest to you based on your Application(s), the Content, and/or your use of Chroma Services.
**2.7 Modification of Chroma Services**
Chroma is constantly innovating in order to provide the best possible experience for its customers and users. Customer acknowledges and agree that the form and nature of the Chroma Services provided may change from time to time without prior notice to you. Changes to the form and nature of the Chroma Services will be effective with respect to all versions of Chromatic; examples of changes to the form and nature of the Chroma Services includes without limitation security patches, added functionality, and other enhancements.
## 3. Use of Services and Content
**3.1 Subscriptions**
Unless otherwise provided in the Subscription Order Form,
- (a) Services and Content are purchased as subscriptions,
- (b) New subscriptions may be added during a subscription term, and
- (c) Any added subscriptions shall terminate on the same termination date as the underlying subscriptions.
Customer must provide accurate and complete registration information any time you register to use the Chroma Services. Customer is responsible for the security of your passwords and for any use of your account. If you become aware of any unauthorized use of your password or of your account, you shall notify Chroma immediately.
**3.2 Usage Limits**
Chroma Services and Content are provided subject to usage limits, including, for example, the quantities specified in a Subscription Order Form or Chromatic website. If Customer’s use of Chroma Services exceeds the aforementioned usage limits, Customer shall be billed for such usage on the applicable invoices, and Customer agrees to pay such additional fees in accordance with Section 5. Unpaid amounts may cause termination of this Agreement or suspension of Services, at Chroma’s discretion, as set forth in [Section 5](#5-fees-payment-and-terms-audit).
**3.3 Customer Responsibilities**
Customer will
- (a) Be responsible for Users’ compliance with this Agreement,
- (b) Be responsible for the accuracy, quality and legality of Customer Data and the means by which Customer acquired Customer Data,
- (c) Use commercially reasonable efforts to prevent unauthorized access to or use of Services and Content, and notify Chroma promptly of any such unauthorized access or use,
- (d) Use Services and Content only in accordance with the Documentation and applicable laws and government regulations of the United States or other countries, including the country in which you are resident or from which you use Chroma Services.
Customer agrees that Chroma has no responsibility or liability for Customer’s deletion or failure to store any Customer Data, content, applications, and other communications maintained or transmitted through Chroma Services. Customer further acknowledges that you are solely responsible for securing and backing up your Applications and any associated data and content. Customer agrees that your purchases of Chroma Services are not contingent on the delivery of any future functionality or features or dependent on any oral or written public comments made by Chroma or any of its affiliates regarding future functionality or features. Customer is responsible for technical support of its Applications. Customer affirms that you are over the age of 13, as you must be over 13 years of age to use the Services, and children under the age of 13 cannot use or register for the Services.
**3.4 Usage Restrictions**
Chroma may suspend or terminate access to Chroma Services if Customer has violated usage restrictions impacting the stability, availability or integrity of the Chroma Services. Customer will not
- (a) Make any Service or Content available to, or use any Service or Content for the benefit of, anyone other than Customer or Your Users,
- (b) Sell, resell, license, sublicense, distribute, rent or lease any Service or Content, or include any Service or Content in a service bureau or outsourcing offering, unless you have been specifically allowed to do so in a separate agreement with Chroma,
- (c) Use a Service or Content to store or transmit infringing, libelous, or otherwise unlawful or tortious material, or to store or transmit material in violation of third-party privacy rights,
- (d) Use a Service to store or transmit Malicious Code,
- (e) Interfere with or disrupt the integrity or performance of any Service or third-party data contained therein,
- (f) Attempt to gain unauthorized access to any Service or Content or its related systems or networks,
- (g) Permit direct or indirect access to or use of any Service or Content in a way that circumvents a contractual usage limit,
- (h) Copy a Service or any part, feature, function or user interface thereof, (i) copy Content except as permitted herein or in an Order Form or the Documentation,
- (i) Copy Content except as permitted herein or in an Order Form or the Documentation,
- (j) Frame or mirror any part of any Service or Content, other than framing on Customer’s own intranets or otherwise for Customer’s own internal business purposes or as permitted in the Documentation,
- (k) Access any Service or Content for the purposes of building a competitive product or service, creating derivative works based on Chroma Services, or bringing an intellectual property infringement claim against Chroma, or
- (l) Reverse engineer, modify, decompile, disassemble or otherwise attempt to discover the source code, object code or underlying structure, ideas, know-how or algorithms relevant to any Chroma Service.
Customer may not develop multiple Applications to simulate or act as a single Application or otherwise access the Chroma Services in a manner intended to avoid incurring fees.
**3.5 Open Source Software Licenses**
Chroma Services may include certain open source components that are subject to open source licenses (“Open Source Software”). Such Open Source Software is licensed under the terms of the license that accompanies the Open Source Software. Nothing in this Agreement limits your rights under, or grants you rights that supersede, the terms and conditions of any applicable license terms for such Open Source Software.
**3.6 Removal or Suspension of Customer Application and Data**
Customer understands that all information (such as data files, written text, computer software, music, audio files or other sounds, photographs, videos or other images) to which you may have access as part of, or through your use of, the Chroma Services are the sole responsibility of the person from which such content originated. Chroma reserves the right (but shall have no obligation) to remove any or all Customer applications and data from Chroma Services. Customer agrees to immediately take down any content that violates the [Acceptable Use Policy](/docs/acceptable-use), including pursuant to a take-down request from Chroma. In the event that you elect not to comply with a request from Chroma to take down certain content, Chroma reserves the right to directly take down such content. If Chroma is required by a licensor to remove Content, or receive information that Content provided to Customer may violate applicable law or third-party rights, Chroma may so notify Customer and in such event You will promptly remove such Content from Your systems. If Customer does not take required action in accordance with the above, Chroma may disable the applicable Content and/or Service until the potential violation is resolved.
**3.7 Administrative Access to Chromatic**
Customer agrees not to
- (a) Access (or attempt to access) the administrative interface of Chromatic by any means other than through the interface that is provided by Chroma in connection with the Chroma Services, unless you have been specifically allowed to do so in a separate agreement with Chroma, or
- (b) Engage in any activity that interferes with or disrupts the Chroma Services (or the servers and networks which are connected to Chromatic).
## 4. Non-Chroma Providers
**4.1. Non-Chroma Applications and Customer Data**
If Customer installs or enables a Non-Chroma Application for use with the Chroma Services, Customer grants Chroma permission to allow the provider of that Non-Chroma Application to access Your Data as required for the interoperation of that Non-Chroma Application with the Chroma Services. Chroma is not responsible for any disclosure, modification or deletion of Your Data resulting from access by a Non-Chroma Application.
**4.2. Integration with Non-Chroma Applications**
Chroma Services may contain features designed to interoperate or integrate with certain Non-Chroma Applications. To use such features, Customer may be required to obtain access to such Non-Chroma Applications subject to their terms and conditions, or to grant Chroma access to Customer’s account(s) on such Non-Chroma Applications. If the provider of a Non-Chroma Application ceases to make the Non-Chroma Application available for interoperation or integration with the corresponding Service features on reasonable terms, Chroma may, at its sole discretion, cease providing those Service features without providing Customer any prior notice, refund, credit, or other compensation.
**4.3 Non-Chroma Content**
Chroma Services may include hyperlinks to other websites, resources, or content which are provided by companies or persons other than Chroma (“Non-Chroma Content”). Chroma has no control over any Non-Chroma Content. Chroma is not responsible for the quality or availability of any such Non-Chroma Content, and does not endorse any advertising, products or other materials on or available from such Non-Chroma Content. Chroma is not liable for any loss or damage which may be incurred by you or your Users in connection with Non-Chroma Content or as a result of any reliance placed by you on the completeness, accuracy or existence of any advertising, products or other materials on, or available from, such Non-Chroma Content.
## 5. Fees Payment and Terms Audit
**5.1 Fees and Expenses**
For purchased Chroma Services and Support, Customer will pay Chroma the fees set forth in the applicable Subscription Order.
**5.2 Payment Terms**
Unless otherwise agreed by the parties in an applicable Subscription Order, Chroma will charge Customer credit card at the interval specified in an applicable order invoice as follows:
- (a) For Services, upon execution of the applicable Subscription Order; and
- (b) for Training Services, monthly in-arrears as such Services are delivered by Chroma.
Customer will pay all such invoices issued by Chroma in full within thirty (30) days of receiving each invoice, without setoff, counterclaim, or deduction of any kind. All unpaid amounts will accrue interest at the rate of 1.5% per month on any outstanding balance, or the maximum amount permitted by law, whichever is lower, plus all expenses of collection. Chroma may, in its sole discretion, suspend the provision of Services or Support, as applicable, (i) upon ten (10) days prior written notice to Customer, if any invoice is more than thirty (30) days past due, or (ii) immediately if Customer is a non-enterprise, self-service customer paying by credit card, and said credit card payment has been declined after reasonable attempts. This right of suspension will not limit any other of Chroma’s rights or remedies related to Customer’s failure to pay. To the fullest extent permitted by law, Customer waives all claims relating to charges unless claimed within 60 days after the charge (this does not affect your credit card issuer rights). Charges are solely based on Chroma's measurements of your use of the Chroma Services, unless otherwise agreed to in writing. Nothing in these Terms obligates Chroma to extend credit to any party. Chroma may change its fees and payment policies for the Chroma Services by notifying you at least fifteen (15) days before the beginning of the billing cycle in which such change will take effect. Changes to the fees or payment policies will be posted on the Chromatic website (or such other URL Chroma may provide from time to time). Customer acknowledges and agrees that any credit card and related billing and payment information that you provide to Chroma may be shared by Chroma with companies who work on Chroma’s behalf, such as accounting firms, payment processors and/or credit agencies, solely for the purposes of checking credit, effecting payment to Chroma and servicing your account.
**5.3 Refunds & Cancellation**
Customer may cancel and receive a full refund of fees paid within the first thirty (30) days of the initial service provisioning date for orders related to Chromatic. Chroma reserves the right, in its sole discretion, to issue any refunds in the form of credit towards future Chroma Services. After the aforementioned 30 days, any subsequent Chromatic orders associated to a Customer’s user account or previously associated web domains are not eligible for refund. Customer may only request a cancellation or refund via written notice to Chroma. In the event Customer terminates a Subscription Order without cause, Customer is responsible for all fees incurred unless a refund is expressly provided herein.
**5.4 Taxes**
All fees and expenses charged by Chroma under this Agreement are exclusive of any taxes, duties, or similar charges imposed by any government, and Customer agrees to pay for any and all federal, state, or local sales, use, excise, privilege, or other taxes, duties or assessments, however designated or levied, relating to this Agreement, exclusive of taxes based on Chroma’s net income. If Customer is required to pay any withholding tax, charge, or levy in respect of any payments due to Chroma hereunder, Customer agrees to gross up payments actually made to Chroma such that Chroma receives sums due hereunder in full and free of any deduction for any such withholding tax, charge, or levy.
## 6. Proprietary Rights
**6.1 Customer Retained Property**
Customer owns and retains all worldwide right, title, and interest in and to all of Customer’s Pre-existing Intellectual Property and Customer’s Confidential Information (together, the “Customer Retained Property”). Except as expressly set forth herein, nothing in this Agreement conveys any right, title, or interest in or to the Customer Retained Property to Chroma or any other third party. Chroma acknowledges and agrees that it obtains no right, title or interest from you (or your licensors) under these Terms in or to any Applications or data that you create, submit, post, transmit or display on, or through, the Chroma Services, including any intellectual property rights which subsist in that Application (whether those rights happen to be registered or not, and wherever in the world those rights may exist). Unless you have agreed otherwise in writing with Chroma, you agree that you are responsible for protecting and enforcing those rights and that Chroma has no obligation to do so on your behalf. By creating an Application and associated Data through use of the Chroma Services, you give Chroma a worldwide, royalty-free, and non-exclusive license to reproduce, adapt, modify, translate, publish, publicly perform, publicly display and distribute such Application and Data for the sole purpose of enabling Chroma to provide you with the Chroma Services.
**6.2 Chroma Retained Property**
Chroma owns and retains all worldwide right, title and interest in and to all:
- (a) Chroma’s Pre-Existing Intellectual Property,
- (b) General Enhancements,
- (c) Services Materials,
- (d) Training Materials,
- (e) Documentation, and
- (f) Implementation Architectures (together, the “Chroma Retained Property”), including any and all Intellectual Property therein and thereto.
Except as expressly set forth herein, nothing in this Agreement conveys any right, title, or interest in or to the Chroma Retained Property or Chromatic (including General Enhancements thereto) to Customer or any other third party.
**6.3 Feedback**
Customer may, in its sole discretion or at the invitation by Chroma, provide Chroma with suggestions, enhancement requests, comments, recommendations, or other feedback related to Services provided by Chroma (“Feedback”). By submitting any Feedback, Customer agrees that Customer’s disclosure is gratuitous and without restriction, and will not place Chroma under any fiduciary or other obligation, and Chroma is free to use such Feedback without any additional compensation to Customer, and/or to disclose such Feedback on a non-confidential basis or otherwise to anyone.
**6.4 Residual Rights**
The parties acknowledge and agree that Chroma is in the business of providing training, and support services to third parties that are or may be substantially similar to the Services and Support being provided to Customer. Customer agrees that Chroma, its employees, and agents will be free to use and employ their general skills, know-how, and expertise, and to use, disclose, and employ any generalized ideas, concepts, know-how, methods, techniques, or skills gained or learned during the course of any Services or Support performed under this Agreement and retained in the unaided memory of Chroma’s employees or agents, subject to its obligations respecting Customer’s Confidential Information pursuant to [Section 7](#7-confidentiality).
**6.6 Reservation of Rights**
Chroma reserves all rights not expressly granted to Customer in this Agreement. Except as expressly stated, nothing herein shall be construed to
1. Directly or indirectly grant to a receiving party any title to or ownership of a providing party’s intellectual property rights in services or materials furnished by such providing party hereunder, or
2. Preclude such providing party from developing, marketing, using, licensing, modifying or otherwise freely exploiting services or materials that are similar to or related to the Support, services, or materials provided hereunder.
**6.6 Copyright Policy**
Customer agree to set up a process to respond to notices of alleged infringement that comply with the United States' Digital Millennium Copyright Act ("DMCA notices"). It is Chroma's policy to respond to DMCA notices or other applicable copyright laws and to terminate the accounts of repeat infringers. Chroma reserves the right to take down content in Customer’s Application or, if necessary, the Application itself upon receipt of a valid DMCA notice.
## 7. Confidentiality
**7.1 Obligations**
For a period of five (5) years from the date of disclosure of the applicable Confidential Information, the Receiving Party will (i) hold the Confidential Information of the Disclosing Party in trust and confidence and avoid the unauthorized disclosure or release thereof to any other person or entity by using the same degree of care as the Receiving Party uses to avoid unauthorized use, disclosure, or dissemination of its own confidential information of a similar nature, but, in no event, less than a reasonable degree of care, and (ii) not use Confidential Information for any purpose except as expressly contemplated under this Agreement or any Subscription Order; provided that, to the extent, Confidential Information constitutes a trade secret under applicable law, the Receiving Party agrees to protect such information for so long as it qualifies as a trade secret. Notwithstanding any other provision of this Agreement, the Receiving Party may disclose Confidential Information to those of the Receiving Party’s employees and contractors having a need to know such Confidential Information, provided that the Receiving Party takes reasonable measures to ensure that such employees and contractors are bound by non-use and non-disclosure obligations at least as restrictive as those contained in this Agreement. Each party shall be liable for all violations of this Section 7 by its employees and contractors.
**7.2 Exclusions**
The obligations of the Receiving Party under this Section 7 will not apply to information of the Disclosing Party that the Receiving Party can demonstrate
- (i) was in the possession of the Receiving Party at the time of disclosure without any restrictions as to confidentiality of such information,
- (ii) was generally available to the public at the time of disclosure or became generally available to the public after disclosure through no breach of this Agreement or other wrongful act by the Receiving Party,
- (iii) was rightfully received by the Receiving Party from a third party without restriction on disclosure, or
- (iv) is independently developed by the Receiving Party without use of or reference to the Confidential Information. The Receiving Party may disclose Confidential Information to the extent required to comply with binding orders of governmental entities that have jurisdiction over it; provided that, to the extent legally permitted, the Receiving Party gives the Disclosing Party reasonable written notice to allow the Disclosing Party to seek a protective order or other appropriate remedies, discloses only such Confidential Information as is required by the governmental entity, and uses commercially reasonable efforts to obtain confidential treatment for any Confidential Information disclosed.
**7.3 Return and Destruction**
Upon the written request of the Disclosing Party, the Receiving Party shall promptly return or destroy the Confidential Information, including all copies thereof (certifying the fact of such destruction to the Disclosing Party), with the exception that the Receiving Party
- (a) may retain an archival copy of the Confidential Information and
- (b) is not required to destroy or alter computer-based back-up files generated in the normal course of its business.
Any Confidential Information contained in such archival copies or backup files shall, however, remain subject to the confidentiality obligations of this Section 7.
**7.4 Equitable Relief**
The parties acknowledge and agree that any breach of the obligations of this Section 7 may cause the non-breaching party irreparable harm for which an adequate remedy at law may not be available and that, therefore, the non-breaching party shall be entitled to seek injunctive relief, in addition to all other remedies available at law.
## 8. Term and Termination
**8.1 Term**
The term of this Agreement will commence on the Effective Date of the applicable order and will continue until terminated as set forth herein. The term for the provision of Support or Services provided under individual Subscription Orders will be as set forth in such Subscription Order; provided, however, that if a Subscription Order for Support does not specify the term for such Support, Support will be deemed to have commenced upon execution of the Subscription Order.
**8.2 Termination**
If there are no active Subscription Orders in place, either party may terminate this Agreement for convenience by providing written notice to the other party. Each party will have the right to terminate this Agreement or any individual Subscription Order for cause upon written notice to the other party:
- (a) If the other party breaches any material term of this Agreement or the applicable Subscription Order, and, if such breach is capable of cure, the breaching party fails to cure such breach within thirty (30) days of its receipt of notice of the breach from the non-breaching party, or
- (b) If
- (i) the other party becomes insolvent or makes an assignment for the benefit of creditors,
- (ii) a trustee or receiver is appointed for such other party or for a substantial portion of its assets or
- (iii) bankruptcy, reorganization or insolvency proceedings are instituted by or against such other party.
Termination of a specific Subscription Order will not result in the termination of any other Subscription Orders. Termination of this Agreement for cause will result in the immediate termination of all active Subscription Orders.
**8.3 Effects of Termination**
Upon any termination, Chroma will be entitled to payment for all Services and Support rendered, and expenses incurred, through the effective date of termination, including for work in progress. Sections [1](#1-definitions), [5](#5-fees-payment-and-terms-audit), [6](#6-proprietary-rights), [7](#7-confidentiality), [8.3](#8-term-and-termination), [9.2](#9-warranty), [10](#10-indemnification), [11](#11-limitation-of-liability) and [12](#12-general)) will survive any termination of this Agreement.
## 9. Warranty
**9.1 Limited Warranties**
- Each party represents and warrants that it has the right, power, and authority to enter into, and perform its obligations under, this Agreement and each Subscription Order.
- Chroma warrants that the Services and Support will be performed by qualified personnel in a professional and workmanlike manner consistent with applicable industry standards. Customer must notify Chroma in writing of any alleged failure by Chroma to perform Support or Services in accordance with the foregoing warranty within thirty (30) days of the delivery of the affected Services or Support. Chroma’s entire liability and Customer’s sole remedy for Chroma’s failure to perform in accordance with the above warranty shall be for Chroma to:
- (i) use commercially reasonable efforts to cure or correct such failure, or
- (ii) if Chroma is unable to cure or correct such failure, terminate the affected Services or Support and refund that portion of fees paid by Customer to Chroma that corresponds to such failure to perform.
**9.2 Disclaimer**
EXCEPT AS EXPRESSLY PROVIDED IN SECTION [9.1](#9-warranty), CHROMA DOES NOT MAKE OR GIVE ANY REPRESENTATION, WARRANTY, OR COVENANT OF ANY KIND, WHETHER EXPRESS OR IMPLIED, IN CONNECTION WITH THE SUPPORT OR SERVICES PROVIDED HEREUNDER. WITHOUT LIMITING THE FOREGOING, AND TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, CHROMA EXPRESSLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY, QUALITY, NON-INFRINGEMENT, TITLE, OR FITNESS FOR A PARTICULAR PURPOSE AND ANY REPRESENTATION, WARRANTY, OR COVENANT BASED ON COURSE OF DEALING OR USAGE IN TRADE. NO ADVICE OR INFORMATION, WHETHER ORAL OR WRITTEN, OBTAINED BY CUSTOMER FROM CHROMA OR THROUGH THE CHROMATIC WILL CREATE ANY WARRANTY NOT EXPRESSLY STATED HEREIN. WITHOUT LIMITING THE FOREGOING, CHROMATIC, ITS SUBSIDIARIES, ITS AFFILIATES, AND ITS LICENSORS DO NOT WARRANT THAT THE CONTENT IS ACCURATE, RELIABLE OR CORRECT; THAT CHROMATIC WILL MEET CUSTOMER’S REQUIREMENTS; THAT CHROMATIC WILL BE AVAILABLE AT ANY PARTICULAR TIME OR LOCATION, UNINTERRUPTED OR SECURE; OR THAT ANY DEFECTS OR ERRORS WILL BE CORRECTED, INCLUDING WITHOUT LIMITATION BY ANY CHROMA SUPPORT. CHROMA SHALL HAVE NO OBLIGATION TO IDENTIFY OR CORRECT ANY DEFECTS OR ERRORS, OR TO MODIFY CHROMATIC OR PERFORM ANY SOFTWARE DEVELOPMENT SERVICES AS PART OF THE CHROMA SUPPORT.
## 10. Indemnification
**10.1 General**
Each party (the “Indemnitor”) agrees, at its own expense, to
- (a) Defend the other party, its Affiliates, and their respective directors, officers, employees, and agents (the 'Indemnitees') from and against any third party claim, suit, or action brought against any of the Indemnitees for death, bodily injury, or damage to or loss of any real or tangible personal property to the extent arising out of the Indemnitor's (including its employees and agents) gross negligence or willful misconduct in the performance of this Agreement (each a “General Claim”), and
- (b) Indemnify the Indemnitees against any and all liabilities, losses, damages, costs, and expenses finally awarded to an unaffiliated third party by a court of competent jurisdiction or agreed by the Indemnitor in settlement with regard to any such General Claim.
Further, Chroma will defend, indemnify, and hold harmless at its expense, any third-party claim, action or proceeding (including resulting liabilities, losses, damages, costs, and expenses finally awarded to an unaffiliated third party) against Customer, and its Indemnitees, that the Services infringe, misappropriate, or violate a third-party’s proprietary rights (a “Customer Infringement Claim”). Customer will defend, indemnify, and hold harmless at its expense, any third-party claim, action or proceeding (including resulting liabilities, losses, damages, costs, and expenses finally awarded to an unaffiliated third party) against Chroma, and its Indemnitees, that any Customer technology related to this Agreement infringes, misappropriates, or violates a third-party’s proprietary rights (a “Chroma Infringement Claim”).
**10.2 Conditions to Indemnification**
As conditions to indemnification under this Section 10, the indemnified party must (a) notify the indemnifying party promptly in writing of the General Claim, Customer Infringement Claim, or Chroma Infringement Claim, as applicable, for which the indemnified party is seeking indemnification, (ii) grant the indemnifying party sole control over the defense and settlement of each General Claim Customer Infringement Claim, or Chroma Infringement Claim, as applicable, and (iii) provide the indemnifying party with reasonable cooperation in response to such party’s requests for assistance. The indemnifying party may not settle or compromise a General Claim Customer Infringement Claim, or Chroma Infringement Claim, as applicable, without the prior written consent of indemnified party if such settlement includes an admission of liability on the part of the indemnified party.
## 11. Limitation of Liability
EXCEPT (A) WITH REGARD TO EITHER PARTY’S BREACH OF CONFIDENTIALITY OBLIGATIONS UNDER [SECTION 7](#7-confidentiality) (“CONFIDENTIALITY”), OR (B) TO THE EXTENT THAT AN AMOUNT IS INCLUDED IN A COURT AWARD OR SETTLEMENT RELATED TO EITHER PARTY’S INDEMNIFICATION OBLIGATIONS UNDER [SECTION 10](#10-indemnification) (“INDEMNIFICATION”), IN NO EVENT WILL EITHER PARTY BE LIABLE UNDER THIS AGREEMENT FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES (INCLUDING WITHOUT LIMITATION, LOST REVENUE, LOST PROFITS, LOSS OF INCOME, OR LOSS OF BUSINESS ADVANTAGE), WHETHER OR NOT FORESEEABLE, EVEN IF IT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. EXCEPT WITH REGARD TO (A) EITHER PARTY’S BREACH OF CONFIDENTIALITY OBLIGATIONS UNDER [SECTION 7](#7-confidentiality) (“CONFIDENTIALITY”), OR (B) EITHER PARTY’S INDEMNIFICATION OBLIGATIONS UNDER [SECTION 10](#10-indemnification) (“INDEMNIFICATION”), IN NO EVENT WILL EITHER PARTY’S CUMULATIVE AND AGGREGATE LIABILITY UNDER THIS AGREEMENT EXCEED THE AMOUNTS PAID BY CUSTOMER UNDER THIS AGREEMENT DURING THE TWELVE (12) MONTH PERIOD IMMEDIATELY PRECEDING THE FIRST DATE ON WHICH LIABILITY AROSE. THESE LIMITATIONS OF LIABILITY WILL REMAIN IN FULL FORCE AND EFFECT, REGARDLESS OF WHETHER EITHER PARTY’S REMEDIES HEREUNDER ARE DETERMINED TO HAVE FAILED OF THEIR ESSENTIAL PURPOSE. THE ABOVE LIMITATIONS WILL NOT, HOWEVER, LIMIT CUSTOMER’S PAYMENT OBLIGATIONS UNDER THIS AGREEMENT.
## 12. General
**12.1 Subcontractors**
Chroma may engage third parties to furnish services in connection with Services or Support, provided that such third parties have executed appropriate confidentiality agreements with Chroma. In addition, Services and Support may be performed by Affiliates of Chroma. No engagement by Chroma of a subcontractor or an Affiliate will relieve Chroma of any of its obligations under this Agreement and Chroma shall be fully responsible for the actions or omissions of such subcontractor as they relate to the subject matter of this Agreement.
**12.2 Assignment**
Neither party may assign this Agreement or any of its rights or obligations hereunder without the prior written consent of the other party, which shall not be unreasonably withheld, except that
- (i) either party may assign this Agreement or rights granted hereunder to its Affiliate without the consent of the other party, and
- (ii) the transfer of this Agreement, or rights granted hereunder, by Chroma to a successor entity in the event of a merger, corporate reorganization, or acquisition of all or substantially all the assets of a party shall not constitute an assignment for purposes of this Section 12.2.
Any attempted assignment or transfer in violation of this Section 12.2 shall be null and void.
**12.3 Governing Law and Venue**
This Agreement is governed by and will be construed in accordance with the laws of the State of California, without regard to conflict of law principles and the terms of this Section 12.3 apply. The parties acknowledge and agree that this Agreement relates solely to the performance of services (not the sale of goods) and, accordingly, will not be governed by the Uniform Commercial Code. In addition, the provisions of the Uniform Computerized Information Transaction Act and United Nations Convention on Contracts for the International Sale of Goods will not apply to this Agreement. All Services and Support provided hereunder are “Commercial Items” as that term is defined in the Federal Acquisition Regulation (FAR) at 48 C.F.R. 2.101. Any legal action or proceeding arising under this Agreement will be brought exclusively in the state or federal courts located in San Francisco County, California, and the parties expressly consent to personal jurisdiction and venue therein.
**12.4 Independent Contractors**
The relationship between the parties established under this Agreement is that of independent contractors, and nothing in this Agreement or Subscription Orders shall be construed to create an employment, partnership, joint venture, or agency relationship between the parties.
**12.5 Notices**
All notices required or permitted under this Agreement must be in writing. Notices will be effective
- (a) upon delivery, if delivered in person or through use of a reputable courier or overnight delivery service, or
- (b) two (2) days after mailing, if sent by a form of certified mail.
Notices must be sent to the addresses set forth in applicable Subscription Orders. Notices to Chroma must additionally be sent to the attention of the Chroma Legal Department, 548 Market St #26384, San Francisco, CA 94104.
**12.6 Publicity**
Customer agrees that Chroma may reference and use Customer’s name and trademarks in Chroma marketing and promotional materials, including, but not limited to, a list of Chroma customers, the Chroma and/or Chromatic websites, or verbal reference, solely for purposes of identifying Customer as a customer of Chroma Services.
**12.7 Severability**
If any provision of this Agreement is held to be invalid or unenforceable, the remaining portions will remain in full force and effect and such provision will be enforced to the maximum extent possible so as to achieve the intent of the parties and will be reformed to the extent necessary to make such provision valid and enforceable.
**12.8 No Waiver**
The failure of a party to enforce any provision or exercise any right under this Agreement shall not constitute a waiver of such provision or right and shall not preclude such party from enforcing such provision or exercising such right at any later time.
**12.9 Force Majeure**
Except for the obligation to pay sums due hereunder, neither party will be liable to the other for any delay or failure to perform due to causes beyond its reasonable control.
**12.10 No Third Party Beneficiaries**
The terms of this Agreement are intended to be, and are solely for the benefit of, Chroma and Customer and do not create any right in favor of any third party.
**12.11 Compliance with Export and Other Laws**
Customer acknowledges that items provided hereunder are of United States origin, are provided subject to the U.S. Export Administration Regulations, and may be subject to other applicable national and international laws. Diversion or distribution contrary to applicable export control laws is prohibited. Customer represents that
- (1) it is not, and is not acting on behalf of,
- (a) any person who is a citizen, national, or resident of, or who is controlled by the government of any country to which the United States has prohibited export transactions, or
- (b) any person or entity listed on the U.S. Treasury Department list of Specially Designated Nationals and Blocked Persons or the U.S. Commerce Department’s Denied Persons List or Denied Entity List; and
- (2) it will not permit items delivered under this Agreement to be used for any purposes prohibited by law, including, but not limited to, any prohibited development, design, manufacture, or production of missiles or nuclear, chemical, or biological weapons.
Additionally, each of the parties agrees that it will not engage in any illegal, unfair, deceptive, or unethical business practices whatsoever, including, but not limited to, any act that would constitute a violation of the U.S. Foreign Corrupt Practices Act.
**12.12 Counterparts and Signatures**
Subscription Orders may be executed in counterparts, each of which shall be deemed an original and all of which, when taken together, shall constitute one and the same instrument. Facsimile and electronic copies of signatures shall have the same effect as originals. If a party elects to sign Subscription Orders electronically, it expressly acknowledges and agrees that such electronic signature is the legal equivalent of, and has the same force and effect as, a manual signature.
**12.13 Entire Agreement**
This Agreement, together with any Subscription Orders, constitutes the entire agreement between the parties concerning the subject matter hereof. Any additional or conflicting terms contained in subscription orders issued by Customer with respect to Services or Support provided hereunder are hereby expressly rejected and shall have no force or effect on the terms of this Agreement or any Subscription Order. This Agreement supersedes all prior or contemporaneous discussions, proposals, and agreements between the parties, whether written or oral, relating to the subject matter hereof. No amendment, modification, or waiver of any provision of this Agreement will be effective unless in writing and signed by both parties.
**12.14 Precedence**
In the event of a conflict between the terms of any Subscription Order with the terms of this Agreement, the terms of the Subscription Order shall control but
- (a) only with respect to the specific Services or Support purchased under such Subscription Order, and
- (b) only if the Subscription Order specifically references the conflicting provision(s) of this Agreement with the intention to supersede such provision(s).
---
## Understand and optimize snapshot usage with Trends
URL: https://chromatic.com/docs/usage-trends
> Track billed snapshot usage over time and diagnose unexpected increases
# Understand and optimize snapshot usage with Trends
Three factors drive billed snapshot usage: how many builds you run, how many snapshots each build generates, and the average billed cost of those snapshots. Trends visualizes all three over time so you can see where usage comes from and investigate unexpected increases.
Go to the Billing page and click Trends.

## How to investigate an increase in billed snapshots
Start with all projects selected and choose a Date Range that includes periods before and after the increase. More than one thing can cause an increase during the same period, so check each usage driver even after you find one cause.
### 1. Find when and where usage increased
Start with the Billed Snapshots chart, which breaks usage down by browser, accessibility testing, and TurboSnap and plots build volume as the Builds line. Identify when usage first spiked above its previous pattern.

Next, use Billed Snapshots per Project to see each project's share of usage during that period. The project with the most total usage may have remained stable while a smaller project caused the increase.
Select each likely project in Billed Snapshots per Project or from the App ID filter, then compare its Billed Snapshots history with the account-wide increase. If several projects increased, repeat the remaining steps for each.

### 2. Did build volume increase?
On the Billed Snapshots chart, compare the bars with the Builds line. Look for changes at the same time and peaks that follow a similar pattern.
**Billed Snapshots + Builds line up.** When both rise at roughly the same time and follow a similar pattern, build volume likely contributed to the usage increase. Continue to [Did build volume outpace PR activity?](#did-build-volume-outpace-pr-activity).

**Billed Snapshots + Builds don't line up.** When the bars grow while the Builds line stays stable or rises more slowly, build volume is less likely to be the primary cause. Continue to [Billed Snapshots per Build](#3-did-billed-snapshots-per-build-increase).

If there is no clear pattern in the charts, check both build volume and snapshots per build.
#### Did build volume outpace PR activity?
PR volume naturally grows as teams add developers and fluctuates with seasonality. Use the Build Count chart to see whether increased build volume reflects more PRs or a CI workflow that triggers more builds.

Feature Builds run on feature branches, so they help show how much development is happening across active branches. Default Builds run on common long-lived branches and often come from routine merge, deployment, or scheduled workflows. Trends uses recognized branch names to classify builds into these groups.
| Pattern | What it suggests | What to check |
| ----------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------ |
| PRs and Feature Builds increased together | Build volume is growing with your team's output | Confirm the additional PRs and builds were expected |
| Feature Builds increased faster than PRs | Each PR may now produce more builds | Check for additional commits, reruns, bot branches, or duplicate CI jobs |
| Default Builds increased | Default-branch workflows are running more often | Check for changes to merge, push, scheduled, or deployment-triggered workflows |
Use the [usage report CSV](/docs/billing/usage-reports#export-usage-data-as-a-csv) to pinpoint the branches and builds behind the increase, then review your CI workflow and [Chromatic configuration](/docs/configure) for unintended triggers.
#### Are PRs with UI changes being reviewed?
After determining why build volume grew, use the Velocity chart to see how many PRs changed the UI and how many of those were reviewed.

Unchanged PRs contain no UI changes and are typically backend-only. These are common and healthy because not every PR affects the frontend.
Unreviewed Changed PRs contain UI changes that your team is not reviewing. This may be intentional, such as a side-project spike that is not headed to production. If unreviewed changed PRs make up a large share, consider using Draft PRs and [skipping Chromatic runs for them](/docs/faq/chromatic-draft-pr) to optimize usage.
Reviewed PRs contain UI changes and have user activity on at least one of the PR's builds. This activity indicates that your team is reviewing UI changes in Chromatic, where they can catch regressions before merging.
### 3. Did billed snapshots per build increase?
Use the Billed Snapshots per Build chart to compare the periods before and after a usage increase.

| Pattern | What it suggests | What to check |
| --------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Stories per Build and Total Snapshots per Build increased together | The project added stories or tests | Review the stories or tests added when usage increased and confirm the growth was intentional |
| Total Snapshots per Build increased faster than Stories per Build | Each story began producing more snapshots | Check for added [browsers](/docs/browsers), [Modes](/docs/modes), or newly enabled [Visual Testing](/docs/visual) and [Accessibility Testing](/docs/accessibility) |
| Billed Snapshots per Build increased while Total Snapshots per Build stayed relatively stable | The average billed cost of each snapshot increased | Continue to [Did Snapshot Billing Rate increase?](#4-did-snapshot-billing-rate-increase) |
| No discernible pattern | The view may be too broad, or more than one factor changed | Narrow the filters, then compare each factor |
### 4. Did Snapshot Billing Rate increase?
Snapshot Billing Rate is billed snapshots divided by total snapshots. It shows whether your usage is becoming more or less efficient over time. When you first set up Chromatic, the rate starts at `1.0` because a full cost snapshot is captured for every test.
[TurboSnap](/docs/turbosnap) lowers your Snapshot Billing Rate by using changed files to determine which stories need new snapshots. It _copies_ or _bypasses_ snapshots for stories it determines could not have changed and these are billed at a lower rate.
- Captured costs `1.0` billed snapshot.
- Copied (via TurboSnap) costs `0.2` billed snapshots.
- Bypassed (via TurboSnap) costs `0.0` billed snapshots.
There is no such thing as "best practice" rate. Most teams with TurboSnap have a lower rate than `1.0`, but the exact rate will depend on what part of your project is in development at any given time. You shouldn't expect a rate of `0.0` because that would mean every snapshot was bypassed because none of the frontend under test changed.
| Pattern | What it suggests | What to check |
| ------------------------------------------------ | -------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| Snapshot Billing Rate increased | A larger share of snapshots was billed at full cost | Use TurboSnap Effectiveness Breakdown to see why more snapshots were captured at full cost |
| Snapshot Billing Rate stayed stable or decreased | TurboSnap effectiveness did not drive the usage increase | Use the causes identified in steps 2 and 3 |
#### Why did the rate increase?
TurboSnap [bails](/docs/turbosnap/troubleshooting#what-do-the-turbosnap-bail-reasons-in-my-usage-report-mean) when it cannot safely determine which tests were affected. When it bails, the affected snapshots are captured at the full rate of `1.0`, which raises the average Snapshot Billing Rate.
The TurboSnap Effectiveness Breakdown chart visualizes the ratio of snapshots billed at a lower rate versus full cost.

| Pattern | What it suggests | What to check |
| --------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------- |
| Captured: No TurboSnap increased | More snapshots came from builds that were not using TurboSnap | Confirm TurboSnap is enabled for the affected projects and builds |
| Labels beginning with Captured: Bail increased | TurboSnap could not determine a safe set of affected tests | Find the dominant bail reason and the builds behind it |
| Labels beginning with Captured: TurboSnap increased | File changes may have legitimately affected more tests | Check which files changed and whether they should affect many tests |
| Copied: TurboSnap or Bypassed: TurboSnap increased | A larger share of snapshots was billed at a lower cost | Use these segments as a reference point when comparing captured snapshots |
| No discernible pattern | The view may be too broad, or more than one factor changed | Narrow the filters, then compare each factor |
When you've identified the dominant bail reason, export bail data from the [usage report CSV](/docs/billing/usage-reports#export-usage-data-as-a-csv) then follow the corresponding [TurboSnap troubleshooting](/docs/turbosnap/troubleshooting) guidance.
## How to verify an optimization
1. Make your optimization in code or configuration
2. Wait until the project has run enough builds to see a usage pattern emerge.
3. Return to Trends with the same App ID. Choose a Date Range that includes comparable periods before and after your optimization.
4. Compare Billed Snapshots, build volume, Total Snapshots per Build, and Snapshot Billing Rate.
If usage did not change as expected, export the [usage report CSV](/docs/billing/usage-reports#export-usage-data-as-a-csv) for the affected period and compare the individual builds.
---
## Combine stories & E2E
URL: https://chromatic.com/docs/combine-stories-e2e
> Learn how to use Storybook, E2E testing frameworks (Playwright or Cypress) and Chromatic together for functional and visual testing UIs.
# Integrating Playwright or Cypress with Storybook and Chromatic
Developing a robust UI testing strategy often involves combining component-level and end-to-end (E2E) tests. While Storybook excels in isolated component testing, Playwright and Cypress handle E2E user flow verification. Chromatic integrates seamlessly with both Storybook and these E2E frameworks, enabling visual testing at both component and page levels.
This complexity can lead to confusion about how these tools work together. This guide addresses this by explaining how to combine Storybook, E2E testing frameworks (Playwright & Cypress), and Chromatic for a comprehensive UI testing strategy.
## Storybook is for testing components
Storybook provides an ideal environment for isolating and testing UI components. By representing different component states and variations as stories, you create a foundation for both visual and functional testing:
- **Visual testing:** Chromatic integrates with Storybook, capturing snapshots of your stories to pinpoint any unintended visual changes.
- **Functional testing:** Storybook's [play](https://storybook.js.org/docs/writing-stories/play-function) function enables you to simulate user interactions (clicks, typing, etc.) directly within a story. This allows you to write assertions and verify that your components behave as expected.
## Playwright & Cypress are for verifying user flows
Playwright and Cypress are ideal for verifying user flows within your web application, e.g.: "sign up" and "add to cart." They simulate real-world user interactions across multiple pages, ensuring that these end-to-end journeys function as intended.
While your Playwright or Cypress tests run, Chromatic captures an archive of the page (including DOM, styling, and assets) and uploads it to the cloud. There, Chromatic generates snapshots and performs pixel diffing to identify any unintended visual changes.
Does Chromatic support Playwright or Cypress component testing?
Playwright and Cypress Component Testing provides a component workbench for you to test components, similar to Storybook. However, that mode of testing is not yet supported by Chromatic. We recommend using Storybook for writing component tests.
## Should I use stories or E2E tests?
The ideal testing strategy often involves a strategic mix of component-level Storybook tests and E2E tests. Let's break down the strengths of each:
### Stories
- **Precision:** Stories ensure components render consistently given specific inputs (data, state, interactions).
- **Reliability:** Mocking data and services eliminates external dependencies, reducing flakiness and false positives.
- **Isolate failures:** Errors are quickly traced back to individual components.
- **Integrated development:** Writing stories is a natural part of the UI development process. You don’t have to maintain a separate test script because your story is reused for testing.
### E2E tests
- **System validation:** E2E tests confirm the entire system functions as designed, from user interactions to backend services.
- **Critical flows:** Validate essential user journeys (login, checkout, etc.) that span multiple components and pages.
- **Unforeseen interactions:** Can reveal issues arising from unexpected component combinations or side effects.
Most teams use Storybook to test a wide array of UI scenarios and employ E2E tests to safeguard key user journeys. Component-level tests offer greater stability due to their reliance on mocked data and APIs. This isolation also simplifies creating test cases for edge cases like failures and loading states. In contrast, E2E tests uncover integration issues and ensure the system functions cohesively.
## How to run visual tests with Storybook, Playwright, and Cypress in a single project?
You can achieve this using Chromatic by using a sub-project setup. Here's how:
1. Create two separate projects linked to the same Git repository.
2. Configure one project specifically for Storybook visual tests and the other for Playwright or Cypress visual tests.
3. Configure your CI to run Chromatic twice, once with each of the two project-specific tokens created in Step 1.
4. Upon initiating a pull request, you'll receive status checks from all Chromatic projects linked to that repository.

### Understanding sub-projects
Chromatic's sub-project functionality enables you to manage multiple testing environments within a single Git repository. By linking multiple Chromatic projects to the same repository, you'll maintain synchronized permissions and receive build status updates across all testing environments.
For details on creating sub-projects, please refer to the documentation: [Run Chromatic for each subproject](/docs/monorepos#run-chromatic-for-each-subproject).
### Can I use Playwright or Cypress to interact with stories before running visual tests?
While it's technically possible to use Playwright or Cypress to interact with stories, this workflow isn't ideal for visual testing purposes and isn't officially supported by Storybook or Chromatic. Here's why:
- **Purpose mismatch:** Playwright and Cypress are designed primarily for E2E tests across a full application. Storybook excels at isolating components for focused testing.
- **Storybook's play function is optimized:** The play function is specifically tailored for simulating interactions within the Storybook environment. Chromatic is able to wait for the play function to complete before capturing a snapshot.
For the most effective visual testing of your components, use Storybook's [play](https://storybook.js.org/docs/writing-stories/play-function) function to simulate interactions.
---
## Configure Chromatic features via Storybook params
URL: https://chromatic.com/docs/config-with-story-params
> Learn how to use Storybook parameters to configure Chromatic features at the project, component, and story level
# Using Storybook parameters to configure Chromatic features
When using Chromatic with Storybook, you can control the snapshot capturing behavior through Storybook parameters. [Parameters](https://storybook.js.org/docs/api/parameters#story-parameters) are static metadata that can be attached at the story, component (meta), and project (global) levels.
This guide will show you how to configure Chromatic features like [`diffThreshold`](/docs/threshold), [`forcedColors`](/docs/media-features), [`disableSnapshot`](/docs/disable-snapshots), and more using Storybook parameters.
## Story level parameters
Parameters specified at the story level apply to that story only. They are defined in the parameters property of the story (named export):
```ts title="Button.stories.ts|tsx"
// Replace your-framework with the framework you are using (e.g., nextjs, vue3-vite)
import type { Meta, StoryObj } from '@storybook/your-framework';
import { Button } from './Button';
const meta = {
component: Button,
} satisfies Meta;
export default meta;
type Story = StoryObj;
export const Primary: Story = {
args: {
with: 'props',
},
parameters: {
// Sets the diffThreshold for 0.2 for this specific story
chromatic: { diffThreshold: 0.2 },
},
};
```
## Component level parameters (also known as Meta)
Parameters specified in a CSF file's meta configuration apply to all stories in that file. They are defined in the parameters property of the meta (default export):
```ts title="Button.stories.ts|tsx"
// Replace your-framework with the framework you are using (e.g., nextjs, vue3-vite)
import type { Meta, StoryObj } from '@storybook/your-framework';
import { Button } from './Button';
const meta = {
component: Button,
parameters: {
// Sets the diffThreshold for 0.2 for all stories in this file
chromatic: { diffThreshold: 0.2 },
},
} satisfies Meta;
export default meta;
type Story = StoryObj;
export const Primary: Story = {
args: {
with: 'props',
},
};
export const Secondary: Story = {
args: {
with: 'secondary props',
},
};
```
## Project level parameters
Parameters specified at the project (global) level apply to all stories in your Storybook. They are defined in the parameters property of the default export in your `.storybook/preview.js|ts` file:
```ts title=".storybook/preview.ts"
// Replace your-framework with the framework you are using (e.g., react-vite, vue3-vite) if you're using Storybook 9, or with the appropriate renderer otherwise.
import type { Preview } from '@storybook/your-framework';
const preview: Preview = {
parameters: {
// Sets the diffThreshold for 0.2 for all stories in your project
chromatic: { diffThreshold: 0.2 },
},
};
export default preview;
```
## Parameter inheritance
When specifying parameters, they are merged together in order of increasing specificity:
- Project parameters
- Component parameters
- Story parameters
In other words, parameters set at the component (meta) level will override those set at the project level. Parameters set at the story level will, in turn, override those set at both the project and component (meta) levels.
---
## UI Review in Dev-Centric Workflows
URL: https://chromatic.com/docs/dev-ui-review
> Learn how to use UI Review in concert with UI Tests for a robust, developer-centric workflow
# UI Review in Dev-Centric Workflows
Chromatic’s [UI Review](/docs/review) complements automated UI Tests by providing a collaboration surface for teams to inspect and discuss visual changes before merging. In dev-centric workflows, UI Review can be used in concert with UI Tests to support robust developer review patterns, whether developers use UI Review as their primary pre-merge inspection surface or as a shared sign-off tool alongside code review.
## Dev Pre-Merge Inspection
For many teams, UI Review is part of the everyday developer workflow and not a separate step for designers or product. Rather than relying on local checkouts or manual browser builds, developers use UI Review to understand the visual impact of changes before merging.
A typical pattern for dev pre-merge UI Review is:
- A developer opens a pull request and pushes commits, triggering a Chromatic build in CI.
- Automated UI Tests run and report visual and interaction results. If there are intentional changes, tests can be accepted to update baselines and signify that expected changes have been validated.
- Developers inspect the UI Review changeset to see exactly what will change on the base branch after merge.
- Comments are left on specific snapshots to highlight unexpected diffs, missing states, or unintended side-effects.
- The reviewer iterates or approves once the UI impact matches expectations.
This workflow helps developers validate visual changes in the same way they inspect code diffs during code review, making visual impact transparent and easier to reason about in context.
## Shared Dev Sign-off on UI
For teams that want a more formal shared sign-off between developers, UI Review can act as the visual complement to code review. In this pattern, developers review UI changes together, helping guard shared components and enforce team standards.
A shared dev sign-off workflow typically looks like:
- A developer opens a pull request and pushes commits, triggering a Chromatic build in CI.
- Automated UI Tests run and report visual and interaction results. If there are intentional changes, tests can be accepted to update baselines and signify that expected changes have been validated.
- Another developer or code owner reviews the PR implementation and checks the UI Review to confirm the visual outcome.
- Both code and UI outcomes are approved before merging.
Because UI Review highlights exactly what changes will land on the base branch, it provides a single visual source of truth for the team to collaborate on. Comments are attached to specific snapshots and help teams discuss scope, intended impact, and any additional work that might be needed before merging.
## How UI Review Fits With UI Tests
Chromatic distinguishes between two workflows that often run side-by-side: UI Tests and UI Review. UI Tests run automatically to catch visual regressions against existing baselines, while UI Review shows a full changeset comparing the latest feature branch state with the base branch.
In dev-centric workflows, UI Tests are used by developers to catch and prevent unintended visual regressions early. UI Review is used to inspect intended visual changes in the context of the full UI. Developers can choose, based on team policy, whether UI Review status checks block merge or are informational.
Since they're independently surfaced on your pull request, you have the flexibility to make either UI Tests or UI Review [required checks](/docs/mandatory-pr-checks) in your Git provider settings.
---
## Globs
URL: https://chromatic.com/docs/globs
> Learn how to use glob patterns with the Chromatic`, including examples of how to exclude specific files or directories from testing.
# Globs
Chromatic options like `onlyStoryFiles` and `externals` allow you to include or exclude specific files or directories. You can specify a single file, a list using an array or by passing the CLI flag multiple times. Additionally, you can use wildcard characters known as [glob patterns](https://code.visualstudio.com/docs/editor/glob-patterns) to define sets of files or directories.
Chromatic handles globs using [picomatch](https://www.npmjs.com/package/picomatch). For a complete overview of the syntax, refer to the [picomatch documentation](https://github.com/micromatch/picomatch?tab=readme-ov-file#globbing-features).
## How to verify your glob pattern
[Picomatch playground](https://tools.chromatic.support/globs/) is a handy tool for testing your glob patterns. Let's look at some examples to understand how to use globs with Chromatic.
Imagine we have a project with the following list of files. Copy and paste it into the `File structure` text box of the [Picomatch playground](https://tools.chromatic.support/globs/).
```
.stories/preview.jsx
.stories/config/backgrounds.ts
.stories/config/msw-default-handlers.ts
.stories/decorators/auth-wrapper.tsx
.stories/decorators/redux-wrapper.tsx
src/core/show-metrics/toggle-show-metrics-banner.tsx
.stories/decorators/language-wrapper.tsx
src/core/pdf-preview/pdf-preview-test-story.tsx
src/i18n.js
src/core/api/program-api/program-api-fixtures.ts
.stories/config/msw-handlers/msw-sales-workflow-preferences-api.ts
.stories/config/msw-handlers/msw-organization-handlers.ts
.stories/config/msw-handlers/msw-validate-credit-token-api-handlers.ts
.stories/config/msw-handlers/msw-credit-application-api-handlers.ts
.stories/config/msw-handlers/msw-document-api-handlers.ts
.stories/config/msw-handlers/msw-features-handlers.ts
.stories/config/msw-handlers/msw-live-proposal-api-handlers.ts
.stories/config/msw-handlers/msw-utility-api-handlers.ts
.stories/config/msw-handlers/msw-site-api.handlers.ts
.stories/config/msw-handlers/msw-metrics-handlers.ts
.stories/config/msw-handlers/msw-quote-api-handlers.ts
src/core/api/assignment-api/assignment-fixtures.ts
.stories/config/msw-handlers/msw-contact-api.ts
.stories/config/msw-handlers/msw-address-api-handlers.ts
.stories/config/msw-handlers/msw-product-handlers.ts
.stories/config/msw-handlers/msw-quote-template-api-handlers.ts
.stories/config/msw-handlers/msw-design-desk-template-api-handlers.ts
.stories/config/msw-handlers/msw-deal-tracker-dashboard-api-handlers.ts
.stories/config/msw-handlers/msw-report-definition-api-handlers.ts
src/core/show-metrics/toggle-show-metrics-banner.styl
src/translations/proposal/en.ts
src/translations/credit-application/en.ts
src/translations/proposal/es.ts
src/translations/credit-application/es.ts
src/translations/project/en.ts
src/translations/project/es.ts
src/core/api/organization-testimonial-api/organization-testimonial-api-fixtures.ts
public/test-files/test-pdf.pdf
public/test-files/test-pdf-spanish.pdf
src/core/api/features/features-api-fixtures.ts
src/core/api/utility-api/utility-api-fixtures.ts
src/core/edit-usage/edit-usage-table-fixtures.ts
src/components/settings/settings-quote/quote-templates/quote-templates-react/quote-templates-fixtures.ts
src/core/api/design-desk-template-api/design-desk-template-api-fixtures/design-desk-template-detail-fixture.ts
src/core/api/report-definition-api/report-definition-api-fixtures.ts
```
Below are different scenarios that demonstrate how to use globs to include or exclude files or directories. Try copying and pasting the examples into the `Glob string` text box of the playground to see the results.
### Scenario 1: Exclude all files in the `.stories` directory
```
.stories/**
```
### Scenario 2: Exclude all TypeScript files and TypeScript files with React components
```
**/*.ts|**/*.tsx|**/*.js. # Use | to divide
```
### Scenario 3: Exclude specific MSW handlers
```
.stories/config/msw-handlers/**
```
### Scenario 4: Exclude translation files
```
src/translations/**
```
### Scenario 5: Exclude everything but a specific file
```
!(.stories/config/msw-handlers/msw-quote-api-handlers.ts)
```
---
## Chromatic for designers
URL: https://chromatic.com/docs/guide-for-designers
> How to use Chromatic for designers
# Guide for designers
Chromatic helps designers collaborate with developers on UI implementation.
## In the design process
Chromatic serves as a library that maps every part of your UI. Use it as a shared reference point to ensure that everyone is referencing the latest UI as they design and spec products.
#### Keep everyone in sync with what's in production
During the design and product process, you often need to reference what's in production. But it's time consuming to navigate to the right page in the right state. Chromatic builds and publishes your Storybook online whenever you push code. This keeps everyone in sync with the latest UI implementation. No fussing with dependencies, git, or local dev environments. [Learn more »](/docs/quickstart)
#### Integrate with Figma to reference the real UI as you design
Design and development naturally diverge. During the design process, you need to double-check what's in production to ensure designs are accurate. Chromatic links stories to Figma components to enable quick access to both. Install our [Figma Plugin](/docs/figma-plugin) to view live stories inside of Figma. Use [Figma in Chromatic](/docs/figma-in-chromatic) to view design components inside of Chromatic alongside your production UI.
#### Documentation that's always up to date
Documentation goes out of date quickly. Storybook and Chromatic work together to automatically [generate UI documentation](https://storybook.js.org/docs/writing-docs) and publish it to a shareable URL. This documentation contains stories rendered as live examples, as well as an interactive component API explorer. You can also customize the generated docs with additional prose. [Learn more »](https://storybook.js.org/docs/writing-docs)
#### Embed stories in Notion and other oEmbed services
During the specification process, you often need to describe complex UI behaviors that words can't do justice. Embed UI from Storybook directly into Notion, Medium, and countless other platforms that support oEmbed. This way your readers can interact with live, rendered components that easily show behavior. [Learn more »](/docs/embed#embed-stories)
---
## Track changes and sign-off on implementation
[UI Review](/docs/review) is made for designers and product managers. It's a purpose-built tool for discussing implementation details and tracking sign-offs. Chromatic works behind the scenes to make the review process easy for teams by organizing change requests, notifying participants, and syncing with Git providers for pull requests checks. The key features for reviewers are:
- Generate changesets to focus reviewer attention on only what changed
- Assign reviewers manually or automatically
- Specify fine-grained roles for teammates
- Create discussions and mention others
- Resolve discussions to show that feedback was addressed
- UI checklist to see visualize what needs to be done

---
## In development workflow
URL: https://chromatic.com/docs/in-development
> How Chromatic helps teams develop applications
# In development workflow
Chromatic automates UI development so you can build features faster, with less manual work. Follow along with our recommended workflow to see how it fits into your development process.
Not using Storybook? Chromatic integrates seamlessly with [Playwright](/docs/playwright) and [Cypress](/docs/cypress) to offer thorough visual testing. In this scenario, proceed with writing E2E tests as usual and incorporate Chromatic into your [Pull Request workflow »](/docs/in-pull-request)
### Develop UIs with Storybook
Chromatic automatically turns stories into tests. So the more coverage of your UI with stories, the more time you'll save your team with our automation.
If you're just getting started with Storybook, we recommend you incrementally adopt Storybook to help develop discrete parts of your UI and then expand usage from there. For example, start by using Storybook to develop a new feature. This gives you the chance to write your first stories and see how it fits into your workflow.

If you're a seasoned Storybook user, most teams choose a [Component-Driven](https://componentdriven.org/) approach to UI development. UIs are built from the “bottom up” starting with basic components that are progressively combined to assemble pages.

1. Build each component in isolation and write stories for its variations.
2. Compose small components together to enable more complex functionality.
3. Assemble pages by combining composite components.
4. Integrate pages into your project by hooking up data and business logic.
Chromatic also integrates with Playwright and Cypress
Developers test user flows end-to-end by navigating between pages with Playwright or Cypress. This methodology allows you to simulate how users behave. Chromatic uses these E2E tests as visual test cases by automatically snapshotting key moments in the test.
- [Learn how to setup Playwright »](/docs/playwright)
- [Learn how to setup Cypress »](/docs/cypress)
### Verify each story in multiple dimensions
Once key UI states are captured as stories, verify how each story renders in different environments and with different user preferences to see how real users experience the UI.
| Dimension | What to test |
| -------------------------------------- | ----------------------------------------- |
| [Browsers](/docs/browsers) | Chrome, Safari, Edge, Firefox |
| [Viewports](/docs/viewports) | Mobile, tablet, desktop |
| [Themes](/docs/themes) | Dark mode, light mode, and custom themes |
| [Locales](/docs/custom-decorators) | Languages, text direction |
| [Media features](/docs/media-features) | `forced-colors`, `prefers-reduced-motion` |
### Create a library of test cases
In the steps above, you developed UI and manually verified each story's appearance and functionality. Chromatic is designed to automate this manual verification process by creating a library of test cases from your stories. Once you create a story, you don't need to go back to check each story by hand to confirm that it looks correct. Instead, your library is automatically tested for changes every time you push code.

---
## Next: In pull request workflow
Now that you've developed UI in Storybook, see how Chromatic speeds up your pull request workflow. Learn how to collect feedback, manage change requests, and get stakeholder sign-off.
Read next chapter
---
## In pull request workflow
URL: https://chromatic.com/docs/in-pull-request
> How Chromatic helps you test and review pull requests
# In pull request workflow
Chromatic serves as a single hub that allows you to test, approve PRs, and share feedback. During the pull request, Chromatic automatically runs in CI when you push code. There are two key workflows: UI Tests and UI Review.

### UI Tests catch bugs automatically
[UI Tests](/docs#test-how-uis-look--function) prevent visual and functional bugs. They're similar to other types of testing (unit, E2E, etc.), in that they enable developers to catch and fix regressions. UI Tests run in CI automatically when you push code so you can see the impact of code changes on the user interface while you develop.
| UI Tests | What dimensions are tested |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Visual | [Browsers](/docs/browsers), [Viewports](/docs/viewports), [Themes](/docs/themes), [Locales](/docs/custom-decorators), [CSS Media Features](/docs/media-features) |
| Interactions | [Click, type, hover](/docs/interactions) |

UI Tests compare the snapshot of a story with the previously accepted [baseline](/docs/branching-and-baselines#whats-a-baseline) in your git history (typically on the same branch). If there are changes, you'll get a diff of the changes. If the changes are intentional, press the accept button to update the baselines. Once all changes are approved, UI Tests will pass, signaling that it's “ready” for review from stakeholders.

### UI Review to get team sign off
After UI Tests pass, the workflow progresses to UI Review. In tools like GitHub, GitLab, and Bitbucket, you assign other developers to review the code for a pull request. Chromatic complements this workflow by allowing you to assign designers, product managers, and other stakeholders to review UI changes in that pull request.
UI Review is different than UI Tests because it shows you what will change on the base branch when you merge a pull request. This is identical to the difference between code review and testing in CI.

How to invite reviewers to a project?
Invite reviewers by going to the project's Manage page » Collaborate tab. You can invite collaborators by email or by sharing an invite link. SSO is also an option for Enterprise plans, which enables all teams to access Chromatic easily.
[More on inviting collaborators »](/docs/access/collaborators#external-collaborators)
How to assign designers and product managers to review?
Click on Assign Reviewers on the review's Activity tab to choose reviewers from the project’s collaborators. Reviewers will be emailed a link to the review page to begin their review.

UI Review is the opportunity to discuss changes and get final team sign off. In the past, teams had to manually click through the UI to review all possible variations. Chromatic's superpower is that it knows exactly which stories have changed. It generates a changeset for reviewers that shows precisely what they need to sign off on.

Why UI Review when all the edge cases should be addressed in the spec?
UI Review acknowledges that even the best laid plans lack fidelity. Developers often run into edge cases or technical hurdles that are impossible for teams to predict ahead of time.
Reviewers leave feedback and request changes by starting discussions. Chromatic helps developers gather discussions in one place that every participant can follow. Resolve a discussion to signal that the work is done. Once all discussions are resolved and stakeholders approve, the UI Review will pass.

### Merge with confidence when pull request checks pass
The status of UI Tests and UI Review appears on your pull request as a check. This keeps your team abreast of any changes to the user interface that need attention. When all checks pass, you’re ready to merge!

How to make UI Tests and UI Review a required pull request check?
You have flexibility to control whether UI Tests and UI Review are required checks in your Git provider settings.
Make UI Tests a required check if you want to ensure that you're 100% protected from visual and functional regressions. Make UI Review a required check to ensure that all feedback gets resolved and every change is signed-off.
You can change whether each check is required separately.
---
## Conclusion
You finished touring all the ways Chromatic contributes to your UI development workflow. We look forward to the incredible UIs you’ll build. Continue exploring with our most popular guides and articles:
- [Intro to Storybook](https://storybook.js.org/tutorials/intro-to-storybook/) is the essential guide to learning Storybook.
- [Visual Testing Handbook](https://storybook.js.org/tutorials/visual-testing-handbook/) details how professional frontend teams visual test with Storybook.
- [Component-Driven Development](https://www.componentdriven.org/) is a "bottoms up" process for building modular UIs starting from components and ending with screens.
- [UI Testing Handbook](https://storybook.js.org/tutorials/ui-testing-handbook/) highlights testing strategies used by scaled front-end teams
#### How to get support
[Sign in](https://www.chromatic.com/start) to use the in-app chat or email support.
---
## Mandatory PR checks
URL: https://chromatic.com/docs/mandatory-pr-checks
> Learn how to block pull requests that contain unapproved visual changes
# Mandatory PR checks
When you link your Chromatic project to a GitHub, Bitbucket, or GitLab repository, Chromatic provides status checks directly on your pull requests. Depending on what features you have enabled, you'll see checks for: UI Tests, UI Review & Publish.
If Chromatic detects visual changes or if UI Review is required, the status checks will show as "pending." This indicates that a human needs to review the changes before proceeding.
You can add an additional layer of protection by requiring these checks to be mandatory. In other words, you will not be able to merge the pull request until all changes have been approved. This guarantees that no visual changes are merged without approval.
## Enable mandatory PR checks
Mandatory checks are a per-repository setting within your Git provider. The following steps show you how to require Chromatic checks to be mandatory on your pull requests:
### GitHub
For GitHub repositories, mandatory status checks are configured as branch protection rules. Here's how:
1. On GitHub.com, navigate to the main page of the repository.
2. Under your repository name, click **Settings**.
3. In the **Code and automation** section of the sidebar, click **Branches**.
4. Next to **Branch protection rules**, click **Add rule**.
5. Under **Branch name pattern**, type the branch name or pattern you want to protect. e.g., `main` or `*` to protect all branches.
6. Select **Require status checks to pass before merging**.
7. In the search field, search for status checks (e.g.: Chromatic, UI Test, UI Review, etc.), select the checks you want to require.

8. Click **Save changes**
9. Now all pull requests to the protected branch will require the Chromatic checks to pass before merging.

### Bitbucket
With BitBucket, some merge checks are already in place by default for pull requests. You can adjust that behavior with a custom configuration. Check out the following links for more information:
- [Default merge checks](https://confluence.atlassian.com/bitbucketserver/checks-for-merging-pull-requests-776640039.html)
- [Merge checklist](https://support.atlassian.com/bitbucket-cloud/docs/merge-a-pull-request/#Merge-checklist)
- [Branch permissions](https://support.atlassian.com/bitbucket-cloud/docs/use-branch-permissions/)
- [Merging strategies](https://support.atlassian.com/bitbucket-cloud/docs/suggest-or-require-checks-before-a-merge/)
To customize default settings, adjust the default configuration by following these steps:
1. Go to the repository settings
2. Click on the **Branch restrictions** item
3. Click on the **Add a branch restriction** button
4. Adjust the settings as needed for the **branch permissions**

5. Click the **Merge settings** tab to adjust the merge checks

Note: The items marked with a star are only available for paid accounts.
### GitLab
You can set up the basic merge checks for your repository by following these steps:
1. Go to the repository settings
2. Select the **Merge requests** item
3. Scroll down to the **Merge checks** section
4. Enable the checks you want to have in place for your repository. At least the "Pipelines must succeed" check is recommended.

5. Now all merge request in GitLab will require the Chromatic checks to pass before merging.

This can extended by enabling [branch protection](https://docs.gitlab.com/ee/user/project/protected_branches.html) for the repository. For GitLab paid plans, you can set up [additional rules](https://docs.gitlab.com/ee/user/project/merge_requests/authorization_for_merge_requests.html) for the repository.
## Check status by scenario
Once a check is marked as mandatory in your Git provider, its outcome depends on how Chromatic runs (or doesn't run) for that commit. Check status is driven entirely by Chromatic's build result — there's no API or setting to programmatically mark a check as passed. Use this table to understand what to expect:
| Scenario | Check result |
| ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Build has no visual changes | 🟢 Passes automatically. |
| Build run with the [`--skip`](/docs/configure#options) flag | 🟢 Marked as skipped and passes immediately, unblocking the PR regardless of whether the commit has visual changes. |
| Build has visual changes to review | 🟡 Pending: blocks merging until someone reviews and approves the changes. |
| Mandatory in your Git provider, but the corresponding check (UI Tests/UI Review) is turned off in Chromatic's project settings | 🟡 Pending indefinitely: Chromatic never sends a status for a check that isn't enabled, so the required check has nothing to satisfy it. Either disable the requirement in your Git provider or re-enable the check in Chromatic. |
| The Chromatic step itself is bypassed, for example with a conditional step (`if:` in GitHub Actions or `rules:` in GitLab CI) | 🟡 Pending indefinitely: if Chromatic never runs, it never reports a status, so a mandatory check has nothing to resolve it. Skip the build with `--skip` instead of skipping the CI step, or don't mark the check as required for that scenario. |
| Your account has used all its included billed snapshots for the billing period | 🟡 Pending: the build can't complete, so no status is sent. See [additional billed snapshots](/docs/billing#additional-billed-snapshots). |
If a check is stuck pending and none of these scenarios apply, see [Why aren't pull request checks syncing with my Git provider?](/docs/ci/#why-arent-pull-request-checks-syncing-with-my-git-provider)
---
## Manual UI Review
URL: https://chromatic.com/docs/manual-ui-review
> Learn how to manually trigger a UI review
# Manual UI Review
Manual UI Review helps you see the visual differences between any pair of branches - even if your project isn't connected to a Git provider.
## Enable UI Review
Go to your project's Manage page to enable UI Review.

## Create a Review

Go to your project's Reviews page from the sidebar. Click the “Create review” button to pick the pair of branches you want to compare.

If you’re familiar with creating pull or merge requests with Git, this process will be very familiar:
- Select the base branch, which is the branch that’s used as the source of truth for comparison. Typically, this will be your `main` branch.
- Select the head branch, which is the branch that has changes that you want to compare with the source of truth. This is often a feature or bug fix branch you’re working on.
- Enter a title for the Review.
- Click the “Compare branches” button to generate your new Review.
Your Review is now ready for you and your team to discuss. Check out the [Understanding the Review](/docs/review#understanding-the-review) section for more information on how to benefit the most from UI Review.
Glossary
- Base branch: the branch you want to use as a baseline for the comparison
- Head branch: the branch with the new changes that need to be compared against the base branch
## PR check for "UI Review"
Manually created Reviews will not create a “UI Review” status check in GitHub, GitLab, or Bitbucket. To create a status check in your Git provider for manually created Reviews, you can use a [custom webhook](/docs/custom-webhooks).
## Closing a Review
Prune your completed manual UI Reviews by clicking the "Close review" menu item in the "Review now" button tooltip. Your review will be moved to the "Closed" Reviews list on the Reviews page.

ℹ️ Reminder: closing a Review **does not** merge the branches in Git.
### Notes:
- In order to create a Review, you will need to have at least two git branches with a build on each.
- If you are trying to review the changes completed in a pull (merge) request, you will want to match the head and base branches of the Review with the respective branches of the pull (merge) request.
- You can only have one open Review at a time with the same branch combination. For example, if your head branch is `new-changes` and your base branch is `main`, you cannot open another Review with `new-changes` as the head branch and `main` as the base branch.
- You can manually create a review for a linked project as well. This feature is available to all projects.
---
---
## Mocking APIs and Network Requests
URL: https://chromatic.com/docs/mock-network-requests
> Learn how to mock APIs and network requests in your tests (Storybook, Playwright and Cypress)
# Mocking APIs and Network Requests
When testing components or pages that make network requests, it's important to mock those requests to keep your tests isolated and predictable. Chromatic integrates with functional testing frameworks to enable visual testing of your UI. Therefore, APIs are mocked by your functional testing framework, not by Chromatic itself.
## Storybook
Storybook offers [several addons](https://storybook.js.org/addons/tag/api) for mocking APIs (e.g. fetching data from a REST or GraphQL API). We recommend using the [MSW addon](https://storybook.js.org/addons/msw-storybook-addon).
Mock Service Worker (MSW) is an API mocking library that uses service workers to capture network requests and provide mocked data in response. The MSW addon integrates this functionality into Storybook. Here’s a basic example:
```tsx title="DocumentScreen.stories.tsx"
// Replace your-framework with the name of your framework (e.g. nextjs, vue3-vite)
import type { Meta, StoryObj } from '@storybook/your-framework';
import { http, HttpResponse, delay } from 'msw';
import { DocumentScreen } from './DocumentScreen';
const meta = {
component: DocumentScreen,
} satisfies Meta;
export default meta;
type Story = StoryObj;
// 👇 The mocked data that will be used in the story
const mockDocuments = [
{
id: 1,
userID: 1,
title: 'Something',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
status: 'approved',
},
{
id: 2,
userID: 1,
title: 'Something else',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
status: 'pending',
},
{
id: 3,
userID: 2,
title: 'Another thing',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
status: 'rejected',
},
];
export const MockedSuccess: Story = {
parameters: {
msw: {
handlers: [
http.get('/api/documents', () => {
return HttpResponse.json(mockDocuments);
}),
],
},
},
};
export const MockedError: Story = {
parameters: {
msw: {
handlers: [
http.get('/api/documents', async () => {
await delay(800);
return new HttpResponse(null, {
status: 403,
});
}),
],
},
},
};
```
For more details, check out the [Mocking network requests](https://storybook.js.org/docs/writing-stories/mocking-data-and-modules/mocking-network-requests) page in the Storybook documentation.
Can I use MSW to mock browser APIs like `navigator.share`?
Yes, but MSW is built to intercept and mock network requests (like fetch or XHR), not to directly mock browser APIs like the `navigator` object.
You can use `Object.defineProperty` for direct browser APIs mocking. It modifies objects like `window` or `navigator`, and lets you define them in your code.
Here's an example of how to mock the `navigator.share`:
```tsx
Object.defineProperty(navigator, 'share', {
configurable: true, // Allows the property to be redefined later
value: async (data) => {
console.log('Mocked share:', data);
return Promise.resolve(); // Simulate a successful share
},
});
```
Learn more about the `Object.defineProperty` in [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty).
### Module mocking
If you rely on third-party libraries that make network requests, you can mock those modules in your stories. This is useful when you want to avoid inconsistencies in your tests due to external dependencies. Refer to the video below and the [module mocking documentation](https://storybook.js.org/docs/writing-stories/mocking-data-and-modules/mocking-modules) for more information on how to do this.
## Playwright
Playwright allows you to mock network requests, including XHRs and fetch requests. You can also use HAR files to mock multiple network requests made by the page. Check out the [Playwright documentation](https://playwright.dev/docs/mock#mock-api-requests) for more details.
```js title="tests/DocumentScreen.spec.js|ts"
test('mocks documents api', async ({ page }) => {
// Mock the api call before navigating
await page.route('*/**/api/documents', async (route) => {
const json = [
{
id: 1,
userID: 1,
title: 'Something',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
status: 'approved',
},
{
id: 2,
userID: 1,
title: 'Something else',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
status: 'pending',
},
{
id: 3,
userID: 2,
title: 'Another thing',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
status: 'rejected',
},
];
await route.fulfill({ json });
});
// Go to the page
await page.goto('https://myapp.com/documents');
// Assert that the "Something else" is visible
await expect(page.getByText('Something else')).toBeVisible();
});
```
## Cypress
Cypress allows you to stub API responses with the `cy.intercept()` method, letting you define the body, HTTP status code, headers, and other response characteristics. You can also use `cy.fixture()` to load mock data from a file. For more details, check out the [Cypress documentation](https://docs.cypress.io/guides/guides/network-requests#Stubbing).
```js title="cypress/e2e/DocumentScreen.cy.js|ts"
cy.intercept(
{
method: 'GET', // Route all GET requests
url: '/api/documents',
},
[
{
id: 1,
userID: 1,
title: 'Something',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
status: 'approved',
},
{
id: 2,
userID: 1,
title: 'Something else',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
status: 'pending',
},
{
id: 3,
userID: 2,
title: 'Another thing',
content:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
status: 'rejected',
},
] // and force the response to be mock data
).as('getDocuments'); // and assign an alias
```
---
## Using Chromatic with Nx
URL: https://chromatic.com/docs/nx
> Use Nx natively in CI with Chromatic and Storybook
# Using Chromatic with Nx
[Nx](https://nx.dev/) is a powerful monorepo tool that helps developers optimize builds and CI/CD execution. When combined with Storybook and Chromatic, it lets you run visual tests per-project and publish a single composed Storybook all in one workspace.
This guide shows you how to set up Chromatic per-project for scoped testing in an Nx monorepo and aggregate all projects into a composed Storybook that can be published with Chromatic. By adding a workspace-wide Chromatic target, you'll have very minimal per-project configuration.
## Prerequisites
Before getting started, you'll want to make sure:
- Your Nx workspace has Storybook installed and working in at least one project.
- You are familiar with setting [environment variables](https://nx.dev/docs/guides/tips-n-tricks/define-environment-variables) and [CI secrets](https://nx.dev/docs/guides/nx-cloud/access-tokens#setting-ci-access-tokens).
- You have Chromatic project tokens for each of the Storybook projects you want to test or publish.
## Configure Nx to run Chromatic
To make sure Chromatic tests are repeatable and consistent across all projects in your monorepo, we'll:
1. Add a workspace-wide `chromatic` target in `nx.json`.
2. Let Nx automatically infer Storybook targets with `@nx/storybook/plugin`.
3. Add minimal overrides per project to provide the Chromatic token and project ID.
### Add Chromatic to `nx.json`
Open your `nx.json` and add the following under `targetDefaults`:
```json title="nx.json"
{
"targetDefaults": {
"chromatic": {
"executor": "nx:run-commands",
"options": {
"commands": [
{
"command": "npx chromatic --exit-zero-on-changes --storybook-build-dir={projectRoot}/storybook-static --storybook-base-dir={projectRoot} --storybook-config-dir={projectRoot}/.storybook --no-interactive --auto-accept-changes=main",
"description": "Chromatic will automatically build Storybook before running."
}
]
},
"dependsOn": ["build-storybook"],
"inputs": [
{
"externalDependencies": ["chromatic"]
}
]
}
}
}
```
This creates a shared Chromatic target for all projects. Each project can add one line for its token and metadata, which keeps the configuration lean. The project's token can be stored as a repository secret for security and referenced through an env var in the `project.json`.
This Chromatic command:
- Sets the correct build, config, and base directory for each project.
- Exits CLI on changes to avoid blocking anything else in your pipeline.
- Keeps your default branch clean (assumes `main` but can be updated).
### Auto-wire Storybook with Nx
If you're not yet using [Nx's Storybook plugin](https://nx.dev/docs/technologies/test-tools/storybook/introduction), you can install it in your workspace with the following command:
```sh
nx add @nx/storybook
```
Then configure Storybook in your `nx.json` under the `plugins` section:
```json title="nx.json"
{
"plugins": [
{
"plugin": "@nx/storybook/plugin",
"options": {
"servesStorybookTargetName": "storybook",
"buildStorybookTargetName": "build-storybook",
"testStorybookTargetName": "test-storybook",
"staticStorybookTargetName": "static-storybook"
}
}
]
}
```
This makes Nx detect Storybook config in any project and wire up all common Storybook targets automatically.
### Add project-specific Chromatic args
For each project that you want to test in Chromatic, open its `project.json` and add:
```json title="project.json"
{
"targets": {
"chromatic": {
"metadata": {
"projectId": "112233445566778899"
},
"options": {
"args": ["--project-token=$CHROMATIC_PROJECT_TOKEN_UI_LIBRARY"]
}
}
}
}
```
Note:
- `projectId` is the Chromatic project's ID and is used later in the composed Storybook (you can locate this in the URL of your Chromatic project).
- `--project-token` should reference a CI secret (`$CHROMATIC_PROJECT_TOKEN_UI_LIBRARY` in this example) where the project's unique token is stored.
## Run Chromatic tests in CI
Once Chromatic is configured per project, you can use Nx to run Chromatic, or limit builds to only affected projects with `nx affected`:
```sh
pnpm nx affected -t build-storybook chromatic
```
Depending on how your CI is configured with Chromatic, you may need to set the following for your Chromatic step:
- `CHROMATIC_BRANCH`
- `CHROMATIC_SHA`
- `CHROMATIC_SLUG`
These ensure Chromatic can link builds to the correct commit and branch in your repo.
### Nx-native example for GitHub Actions using `--skip`
If you have branch protection rules in place and want to [get a Chromatic PR badge when a project is not affected](/docs/monorepos#only-run-chromatic-when-changes-occur-in-a-subproject), you'll want to apply the `--skip` flag. You can keep your YAML clean by including a step to build Storybook and publish to Chromatic when projects are affected, and run a bash script when not affected to apply `--skip`. Alternatively, you can include the bash script directly in your YAML if it's preferred.
Let's say we have both `ui-library` and `design-system` projects. Add these steps to your YAML config:
```yaml title=".github/workflows/chromatic.yml"
- name: Affected
run: pnpm nx affected -t build-storybook chromatic
- name: Skip unaffected projects and mark as passed for Chromatic status checks
run: ./tools/skip-unaffected.sh
shell: bash
env:
CHROMATIC_PROJECT_TOKEN_UI_LIBRARY: ${{ secrets.CHROMATIC_PROJECT_TOKEN_UI_LIBRARY }}
CHROMATIC_PROJECT_TOKEN_DESIGN_SYSTEM: ${{ secrets.CHROMATIC_PROJECT_TOKEN_DESIGN_SYSTEM }}
```
Create the `skip-unaffected.sh` bash script that contains the following:
```sh title="./tools/skip-unaffected.sh"
#! /bin/bash
set -e
chromatic_projects=$(npx nx show projects --with-target=chromatic)
affected_chromatic_projects=$(npx nx show projects --with-target=chromatic --affected)
echo ""
echo "All Chromatic projects:"
echo "$chromatic_projects" | tr ' ' '\n' | sed '$/^/- /'
echo ""
echo "Affected Chromatic projects:"
if [ -z "$affected_chromatic_projects" ]; then
echo "- No affected Chromatic projects"
else
echo "$affected_chromatic_projects" | tr ' ' '\n'
fi
echo ""
chromatic_projects=($chromatic_projects)
affected_chromatic_projects=($affected_chromatic_projects)
for project in "${chromatic_projects[@]}"; do
if [[ ! " ${affected_chromatic_projects[@]} " =~ " ${project} " ]]; then
echo: "Project \"$project\" was not affected as part of the current CI run, skipping Chromatic build..."
NX_TUI=false npx nx run --excludeTaskDependencies $project:chromatic --skip --no-dte
fi
done
```
## Publish a composed Storybook
In addition to running tests, you may want [a single Storybook that displays all the Storybooks in your workspace side by side](/docs/composition). To create this "shared" Storybook (ex. `shared-storybook`), make a new project with a Storybook config.
Update the `main` config for that project:
```ts title="shared-storybook/.storybook/main.ts"
import { createProjectGraphAsync } from '@nx/devkit';
import type { StorybookConfig } from '@storybook/your-framework';
const projectGraph = await createProjectGraphAsync();
const projectsWithChromaticTarget = Object.values(projectGraph.nodes).filter(
(node) => node.data.name !== 'shared-storybook' && node.data.targets?.chromatic
);
const config: StorybookConfig = {
refs: projectsWithChromaticTarget.reduce((acc, project) => {
const chromaticProjectId = project.data.targets?.chromatic?.metadata?.projectId;
if (!chromaticProjectId) {
throw new Error(`Project "${project.name}" has a Chromatic target but no projectId.`);
}
acc[project.name] = {
title: project.data.name,
url: `https://main--${chromaticProjectId}.chromatic.com/`,
expanded: true,
};
return acc;
}, {}),
};
export default config;
```
This config:
- Reads the project graph at build time.
- Includes a ref for every project with a Chromatic target (except for your shared Storybook).
- Shows each project's Storybook within a single, composed Storybook.
- Assumes `main` for your default branch (can update the URL if you use a different default).
Once you've set up the project in Chromatic for your shared Storybook and published your first build, you can disable UI tests to make the project publish-only. Include a step in your CI workflow to publish your shared Storybook as needed.
Note: Chromatic requires at least one "real" story in the composed Storybook to publish it. Add a
simple placeholder story if needed.
## Configure TurboSnap across your workspace
To use TurboSnap in an Nx project, you'll need to make sure you're passing `webpackStatsJson` as an option for `build-storybook`. You can set this as a default by updating `nx.json` to include the following target default for `build-storybook`:
```json title="nx.json"
{
"targetDefaults": {
"build-storybook": {
"options": {
"webpackStatsJson": true
}
}
}
}
```
You'll also want to update `targetDefaults.chromatic.options.commands.command` to include `--only-changed`:
```json title="nx.json"
{
"targetDefaults": {
"chromatic": {
"executor": "nx:run-commands",
"options": {
"commands": [
{
"command": "npx chromatic --exit-zero-on-changes --storybook-build-dir={projectRoot}/storybook-static --storybook-base-dir={projectRoot} --storybook-config-dir={projectRoot}/.storybook --no-interactive --auto-accept-changes=main --only-changed",
"description": "Chromatic will automatically build Storybook before running."
}
]
},
"dependsOn": ["build-storybook"],
"inputs": [
{
"externalDependencies": ["chromatic"]
}
]
}
}
}
```
The `--only-changed` flag enables TurboSnap, speeding up your UI testing. [Learn more about TurboSnap](/docs/turbosnap).
## Workaround: Updating globals in composed Storybooks
If your composed Storybook isn't updating globals correctly (ex. theme or controls), you can add the following to `manager.ts`:
```ts title="shared-storybook/.storybook/manager.ts"
import { addons } from 'storybook/manager-api';
addons.register('globals-reload', () => {
const getGlobals = () => new URLSearchParams(window.location.search).get('globals');
let lastGlobals = getGlobals();
setInterval(() => {
const currentGlobals = getGlobals();
if (currentGlobals !== lastGlobals) {
lastGlobals = currentGlobals;
window.location.reload();
}
}, 250);
});
```
This causes the manager UI to reload whenever globals change, resolving the refresh issues in composed refs.
---
## Support
URL: https://chromatic.com/docs/support
> Chromatic's support guidelines
# Support
The fastest way to get help is to search the docs and browse our [FAQ](/docs/faq).
Our team is spread across timezones for a quick turnaround time. Use our **in-app chat** to get in touch. Please provide details like version numbers, logs, and screenshots, to speed up troubleshooting.
Go to our [Status page](https://status.chromatic.com/) to check uptime and get updates on outages.
If your question requires more context, contact us via [email](mailto:support@chromatic.com). We recommend using email as a last resort because it can take more time to respond.
---