Skip to main contentCarbon Design System

1. Installing Carbon

Starting with our Vue CLI generated app, let’s install Carbon and begin using Carbon components. By the end you will have a Vue app that uses the UI Shell to navigate between pages.


A preview of what you will build:

Fork, clone and branch

This tutorial has an accompanying GitHub repository called carbon-tutorial-vue that we’ll use as a starting point for each step.


To begin, fork carbon-tutorial-vue using your GitHub account.


Go to your forked repository, copy the SSH or HTTPS URL and in your terminal run the two commands to get the repository in your local file system and enter that directory.

git clone [your fork SSH/HTTPS]
cd carbon-tutorial-vue

Add upstream remote

Add a remote called upstream so we can eventually submit a pull request once you have completed this tutorial step.

git remote add upstream [email protected]:carbon-design-system/carbon-tutorial-vue.git

Or, if you prefer to use HTTPS instead of SSH with your remotes:

git remote add upstream

Verify that your forked repository remotes are correct:

git remote -v

Your terminal should output something like this:

origin [your forked repo] (fetch)
origin [your forked repo] (push)
upstream [email protected]:carbon-design-system/carbon-tutorial-vue.git (fetch)
upstream [email protected]:carbon-design-system/carbon-tutorial-vue.git (push)


Now that we have our repository set up, let’s check out the branch for this tutorial step’s starting point. Run the two commands:

git fetch upstream
git checkout -b vue-step-1 upstream/vue-step-1

Build and start

We have the repository forked to your GitHub account, cloned down to your machine, and the starting branch checked out. Next, install the Vue app’s dependencies with:


After the dependencies are installed, you can start the app with:

yarn serve

Your default browser should open up with an empty page that says: Hello Carbon! Well, not quite yet. This is the starting point for the Carbon tutorial.

OK. So we made a small change to the Vue CLI generated app replacing the HelloWorld component and replaced it with our own message and swapped out the favicon.

Install Carbon

Even though we installed existing dependencies, we’ve yet to install the Carbon packages.

  • carbon-components - component styles
  • @carbon/vue - Vue components
  • @carbon/icons-vue - Vue icons

Stop your development server with CTRL-C and install Carbon dependencies with:

yarn add carbon-components @carbon/vue @carbon/icons-vue

Other dependencies

If you check out the file package.json, you’ll notice a few dependencies beyond those listed above. These were installed as part of the project creation using the Vue CLI. These include:

  • vue-router: Used to make routing in Vue apps simpler
  • @vue/cli-plugin-babel: To ensure we produce well supported code.
  • @vue/cli-plugin-eslint: To allow us to catch potential errors.
  • @vue/cli-plugin-unit-jest: To allow us to unit test our code.
  • node-sass: To allow us to use the sass css precompiler.

NOTE: We could have installed these separately but using the CLI to set this up for us ensures a good base config for these dependencies.

To avoid having to add the ~ prefix when importing SCSS files from node_modules, create a .env file at the project root that contains:


For the Windows operating system, use:


Then, start the app again. If your app’s currently running, you’ll need to restart it for the new environment variable to be used.

yarn serve

The app looks as it did before. Next, let’s add Carbon styling.

Import carbon-component styles

In the src directory, create a sub-directory styles and add a new file _carbon.scss to it. Then in App.vue edit the style tag to import it.

<style lang="scss">
@import "./styles/carbon";

In styles/_carbon.scss, import the Carbon styles by adding the following at the top of the file:

@import 'carbon-components/scss/globals/scss/styles';

This will take a moment for the Sass to compile. Once compiled, you’ll notice that the Carbon base styling is applied (IBM Plex Sans font family, font size, weight, colors, etc.)

Because any change to _carbon.scss will re-compile all of the Carbon Sass, avoid making changes here unless instructed to do so. it is better to make them in the component files or a separate file if needed.

Next we’ll create a Carbon Button to test that our dependencies are working properly.

After the other imports in main.js and before the Vue instance is created add the following.

import CarbonComponentsVue from "@carbon/vue";

This is a quick way to pull in all @carbon/vue components and register them for use in your project. Individual components can be imported to a project or component.

e.g. Instead of modifying src/main.js we could have added the following to src/App.vue:

import { CvButton } from '@carbon/vue';
export default {
components: {

See the Carbon Vue Components documentation for other ways to load components from @carbon/vue components.

In this tutorial we will stick to importing all of the components at once so we can focus on our use of @carbon/vue.

Now open the App.vue component and replace:

Hello Carbon! Well, not quite yet. This is the starting point for the Carbon tutorial.





Congratulations, you’ve imported your first component! You should see a Carbon styled button on the page.

NOTE: In this tutorial you can use either tag format. The Vue style guide recommend sticking to either Pascal or kebab case. The examples from here will use Pascal case for file and component names with kebab case in the HTML.

Add UI Shell

Next we’re going to create a Vue component called TutorialHeader to use with the UI Shell Carbon component. Create a new directory src/components. In the src/components directory, create TutorialHeader directory. Create the following files inside src/components/TutorialHeader:


Import and export the header

In src/components/TutorialHeader/index.js, import and export our TutorialHeader component like so:

import TutorialHeader from './TutorialHeader';
export default TutorialHeader;

Lazyness - VSCode users only

If you are using VSCode then you might want to add the following snippet which will when you type ‘index’ generate an index file for you based on the folder name.

"index-file": {
"prefix": "index",
"body": [
"import ${TM_DIRECTORY/.*[\\/]//gm} from './${TM_DIRECTORY/.*[\\/]//gm}';",
"export { ",
"export default ${TM_DIRECTORY/.*[\\/]//gm}",

You can also use the following to create a skeleton component. To use this one, start typing the word template in your template file and it will generate a file, making assumptions based on the component file name.

"Vue_Component": {
"prefix": "template",
"body": [
"export default {",

OK, back to using Carbon components. Let’s make use of our Carbon UI Shell components in TutorialHeader.vue. Set up the file like so:

<cv-header aria-label="Carbon tutorial">
<cv-skip-to-content href="#main-content"
>Skip to content</cv-skip-to-content
<cv-header-name href="/" prefix="IBM">Carbon Tutorial</cv-header-name>

Import icons

Now let’s import the icons from our @carbon/icons-vue elements package. After the closing template tag in the TutorialHeader.vue file, we need to import each individual icon we will use.

import Notification20 from "@carbon/icons-vue/es/notification/20";
import UserAvatar20 from "@carbon/icons-vue/es/user--avatar/20";
import AppSwitcher20 from "@carbon/icons-vue/es/app-switcher/20";
export default {
name: "TutorialHeader",
components: { Notification20, UserAvatar20, AppSwitcher20 }

Then we need to add content to the header-global slot where we will use our icons. These represent actions in the header a user can make. Replace:

<template slot="header-global" />


<template slot="header-global">
<cv-header-global-action aria-label="Notifications">
<notification-20 />
<cv-header-global-action aria-label="User avatar">
<user-avatar-20 />
<cv-header-global-action aria-label="App switcher">
<app-switcher-20 />

Render the header

Next we’ll render our UI Shell by importing our TutorialHeader component and CvContent into App.vue. Add a script tag if you don’t have one, then update it as follows:

import TutorialHeader from "./components/TutorialHeader";
export default {
name: "App",
components: {

In addition to importing the TutorialHeader component, we have also declared it for use in our template by adding it to the components property of our component.

As our template currently just contains a Button it is still not rendering anything more interesting so let’s update that to include our imported components. This should look like the following:

<div id="app">
<tutorial-header />
<cv-content id="#main-content">

You should now see a styled UI Shell header and a button below it.

Create pages

Next thing we need to do is create the files for our views.

Since our app will have two pages, we’ll create two folders in src/views. Clear out the files currently in the views folder and add the following folders.

├── LandingPage
└── RepoPage

Create the following files in the LandingPage folder:

├── index.js
└── LandingPage.vue

Create the following files in the RepoPage folder:

├── index.js
└── RepoPage.vue

Import and export content pages

Starting with LandingPage, just like with our header, we need to export the component in src/view/LandingPage/index.js by adding:

import LandingPage from './LandingPage';
export default LandingPage;

Next in LandingPage.vue we’ll create our component.

<div>LANDING PAGE</div>

We’ll repeat this process with RepoPage.

In src/view/RepoPage/index.js, import and export the RepoPage component like so:

import RepoPage from './RepoPage';
export default RepoPage;

Then in RepoPage.vue create the component.

<div>REPO PAGE</div>

Awesome! We’ve just created our content pages. Next thing we need to do is render them with our router.

Add routing

Lucky for you, as part of the Vue CLI project set up we added vue-router. This created the views folder and also added, src/router.js and imported that into src/main.js for us.

We need to adjust it by replacing the contents of src/router.js with:

import Vue from 'vue';
import Router from 'vue-router';
import LandingPage from './views/LandingPage';
export default new Router({
routes: [

If you click on Repositories and then on IBM Carbon Tutorial you’ll notice a flicker as we hop from one page to another. We can fix this by using vue-router to manage our views.

Next we need to update src/App.vue to render these views.

In the template section remove the <cv-button /> and replace it with <router-view /> as follows

<cv-content id="#main-content">
<router-view />

After that we need to do a couple quick fixes to the UI Shell to have it work with the vue-router.

In src/components/TuturialHeader/TutorialHeader.vue simply replace the href attributes used in the cv-header-name and cv-header-menu-item components with to. @carbon/vue will under the covers switch from use of an a tag to router-link.

<cv-header-name to="/" prefix="IBM">Carbon Tutorial</cv-header-name>


<cv-header-menu-item to="/repos">Repositories</cv-header-menu-item>

You should now have a working header that routes to different pages without full page reload!

Submit pull request

We’re going to submit a pull request to verify completion of this tutorial step and demonstrate a couple of related concepts.

Continuous integration (CI) check

We have a ci-check script defined in package.json that verifies file formatting for files that have been touched since the last Git commit with a tool called Prettier. You’d typically also have that script run your test suite as part of your CI build. Go ahead and make sure everything looks good with:

yarn ci-check

Git commit and push

Before we can create a pull request, stage and commit all of your changes:

git add --all && git commit -m "feat(tutorial): complete step 1"

Then, push to your repository:

git push origin vue-step-1

Pull request (PR)

Finally, visit carbon-tutorial-vue to “Compare & create pull request”. In doing so, make sure that you are comparing your repository’s vue-step-1 branch into base: vue-step-1. Take notice of the Netlify bot that deploys a preview of your PR every time that you push new commits. These previews can be shared and viewed by anybody to assist the PR review process.