The component library & design system for Codecademy. ✨
This repository is a monorepo that we manage using NX. That means that we publish several packages to npm from the same codebase, including:
We provide a single package to manage the versions of a few core dependencies: gamut, gamut-icons, gamut-illustrations, gamut-patterns, gamut-styles. Since these packages are highly intertwined we suggest only installing @codecademy/gamut-kit when your app needs all of these.
- Run
yarn add @codecademy/gamut-kit - Add each of the managed packages to your peer dependencies (this is required for enabling intellisense for these packages and does not have any effect on version resolution)
{
"peerDependencies": {
"@codecademy/gamut": "*",
"@codecademy/gamut-icons": "*",
"@codecademy/gamut-patterns": "*",
"@codecademy/gamut-illustrations": "*",
"@codecademy/gamut-styles": "*",
"@codecademy/gamut-tests": "*",
"@codecademy/variance": "*"
}
}gamut: Our React UI component library
gamut-styles: Utility styles for Gamut components and codecademy apps
gamut-icons: SVG Icons for Gamut components and codecademy apps
variance: TypeScript CSS in JS utility library
styleguide: Styleguide Documentation & storybook development sandbox
- Run
yarnin the root directory - Run
yarn buildto build all of the packages (certain packages likegamut-iconsneed to be built to function in storybook).
- Run
yarn nx storybook styleguideto start the storybook server - Add new stories to
packages/styleguide/src - Stories are written using storybook's Component Story Format and MDX. Check out our comprehensive guide on writing stories here.
This repository uses NX Release with Version Plans for package versioning and publishing.
- Create a version plan for your changes using
yarn nx release plan. This interactive command will prompt you to:- Select which packages are affected by your changes
- Choose the type of version bump (major, minor, or patch)
- Provide a description of the changes for the changelog
- The version plan will be saved as a markdown file in
.nx/version-plans/ - Commit this version plan file along with your code changes
- The version plan will be applied when your PR is merged to main
Version plan files are markdown files with YAML front matter. Here's an example:
---
gamut: minor
gamut-styles: patch
---
Add new Button variant and fix spacing issues
- Added a new "ghost" variant to the Button component
- Fixed margin spacing in the Card component- Make your changes in a feature branch, and get another engineer to review your code
- Create and commit a version plan for the changes (
yarn nx release plan) - CI checks that a version plan is present for the PR
- After reviews and checks pass, you can merge your branch into main
- Once your branch is merged into main, it will be published automatically by GitHub Actions using NX Release.
- NX Release will apply all version plans found in
.nx/version-plans/ - It will bump package versions according to the plans
- It will generate changelog entries from the version plan descriptions
- It will publish the packages to npm
- It will create git tags and GitHub releases
- NX Release will apply all version plans found in
- You can find the new version number on npmjs.com/package/, or find it in that package's
package.jsonon themainbranch
Every PR that changes files in a package publishes alpha releases that you can use to test your changes across applications.
NOTE: in case an alpha build is not published upon opening of the PR or Draft PR, re-run the
build-testcheck and that will re-run the alpha build publishing flows
- Create a PR or Draft PR.
- This will kickoff a Github Action workflow which will publish an alpha build. (This will appear in Github as the "Deploy")
- After the alpha build is published, the
codecademydevbot should comment on your PR with the names of the published alpha packages.

- Install this version of the package in your application you wish to test your changes on.
NOTE: Due to the inconsistencies of symlinks in a monorepo, instead of using
yarn link, we recommend using thenpm-link-betterpackage with the--copyflag to copy packages into your local repo'snode_modulesdirectory.
Initial Setup:
- Ensure you have npm-link-better installed:
npm install -g npm-link-better - Ensure you've built the entire
gamutrepo since you last synced:yarn build
Instructions:
For each of your local gamut packages (e.g. gamut), you'll need to do 2 things to get it working in your project:
-
Make sure your package changes have been built into the
gamut/packages/[package]/distfolder.yarn build
or
yarn build:watch(not all packages support this yet)
-
Copy that built
/distfolder to your project'snode_modules/@codecademy/[package]folder.cd myProjectRepo npm-link-better --copy --watch path/to/gamut/packages/[package]NOTE: The
--watchflag will automatically copy your package intonode_moduleseverytime it is built.
Example Workflow
Let's say we are making changes to the gamut package, and our app that uses the gamut package uses yarn start to build, serve, and watch our app for changes.
Let's also assume these two repos are sibling directories inside of a folder called repos
repos
|- gamut
|- my-app
We would run the following commands in 3 separate shells
# Shell 1: Auto-build Gamut changes
cd repos/gamut/packages/gamut
yarn build:watch
# Shell 2: Auto-copy built Gamut changes to my-app.
cd repos/my-app
npm-link-better --copy --watch ../gamut/packages/gamut
# Shell 3: Auto-update app when anything changes.
cd repos/my-app
yarn startThis would allow us to make a change in our gamut package, and see that change automatically reflected in our local app in the browser.
Troubleshooting
-
If you see compilation issues in your project's dev server after running
npm-link-better, you may have to restart your app's dev server. -
If you are seeing compilation issues in a
gamutpackage, you may need to rebuild the whole repository viayarn build
Instructions for using `yarn link` instead (not recommended)
For quicker development cycles, it's possible to run a pre-published version of Gamut in another project. We do that using symlinks (the following instructions assume you have set up and built Gamut):
cd /path/to/gamut/packages/gamutyarn linkcd path/to/other/repoyarn link @codecademy/gamutyarn install
If your other project uses React, you must link that copy of React in Gamut:
cd path/to/other/repocd node_modules/reactyarn linkcd /path/to/gamut/packages/gamutyarn link reactyarn build
See the docs for more information for why you have to do this.
- Use NX generators to create the new package. For example:
yarn nx g @nx/react:library <package-name> --buildable --publishable
- Make sure to set the
publishConfigfield to{ "access": "public" }in the generated package.json to let your published package be public by default
- Make sure to set the
- Customize the generated source code as needed for your package
- Run
yarn installfrom the repository root - Send a
featPR adding that package with a version plan (usingyarn nx release plan) - Once merged, message out in our #frontend Slack channel to other Gamut developers to re-run
yarn installafter they merge frommain
Notes:
If your package will be used in other packages in the monorepo, you may need to set up aliases in jest and storybook so that they can be run without building your package first. You can find these aliases in jest.config.js and the styleguide storybook config.
NX
This monorepo uses NX to cache previous builds locally and in CI.
The config for NX is located at /nx.json, along with project.json files for each package.
For new packages, please use an NX generator plugin to create your initial package, this will ensure that all of the configuration for linting & testing is set up correctly.
Breaking changes are indicated in version plans by specifying a major version bump. When creating a version plan with yarn nx release plan, select "major" as the bump type for packages that introduce breaking changes.
Examples of version plans with breaking changes:
---
gamut: major
---
Breaking: Removed deprecated Button variants
This removes the previously deprecated "primary-blue" and "secondary-red" variants.You should create a major version bump if your changes introduce any incompatibilities with previous versions of the module. This will indicate to package consumers that they need to refactor their usage of the module to upgrade.
Because Gamut is a separate repository from its consumers, it can be tricky to coordinate technically breaking changes. If your changes will require changes in any downstream repositories:
- Create a PR in Gamut to create alpha package versions
- Create PRs in the repositories using those alpha package versions
- Update each downstream PR description to link to the Gamut PR, and vice versa
- Once all PRs have been approved, merge your Gamut PR first
- Update your repository PRs to use the new (non-alpha) package versions once published
- Merge your repository PRs
This process minimizes the likelihood of accidental breaking changes in Gamut negatively affecting development on our other repositories.
Changelog content is driven by the description in version plan files (in .nx/version-plans/), not the PR title or PR description.
Storybook is built and published automatically when there are merges into the main branch.