Skip to content

commercetools/nimbus

Repository files navigation

Nimbus Design System

Nimbus Logo

A modern, extensible design system for building consistent, accessible user interfaces.

πŸ“š Table of Contents

πŸ” Overview

Nimbus is a comprehensive design system that provides a collection of reusable components, icons, and design tokens for building consistent user interfaces. This monorepo contains multiple packages and applications that work together to provide a cohesive design system experience.

πŸ—οΈ Repository Structure

Packages

Package Description Purpose
@commercetools/nimbus Core UI component library Provides React components for building user interfaces
@commercetools/nimbus-icons Icon library SVG files wrapped as React components
tokens Design tokens Color, spacing, typography, and other design variables
color-tokens Brand colors Brand-specific color definitions

Applications

Application Description Purpose
docs Documentation site Interactive documentation for all Nimbus packages, auto-generated from MDX files in the packages

πŸš€ Getting Started

Prerequisites

Before you begin, ensure you have the following installed:

  • Node.js: v22.14.0+
  • PNPM: v9.12.3+

Installation

All commands should be run from the repository root.

  1. Clone the repository:

    git clone https://github.com/your-org/nimbus.git
    cd nimbus
  2. Initialize the repository:

    pnpm nimbus:init

Tip

It is advisable to run the repo:init command after every branch-switch. The command gets rid of all node_modules- & dist-folders, reinstalls dependencies and rebuilds all packages.

πŸ’» Development Workflow

Development Mode

Start the development environment with the following command:

pnpm start

This will start both the documentation app and Storybook in parallel:

If you prefer to run just one of the applications:

# Start only the documentation app
pnpm start:docs

# Start only Storybook
pnpm start:storybook

Building the Project

Complete Build

Build all packages and applications:

pnpm build

Targeted Builds

Build only specific parts of the system:

# Build only the packages (not the docs application)
pnpm build:packages

# Build only the documentation application
pnpm build:docs

# Build only the design tokens
pnpm build:tokens

Creating New Components

For detailed guidance on creating new components, see the Component Guidelines.

πŸ§ͺ Testing

Nimbus uses Vitest for testing with two distinct test types that serve different purposes.

Test Types

1. Storybook Tests (Component Tests)

  • Purpose: Test component behavior, interactions, and visual states
  • Environment: Real browser (headless Chromium with Playwright)
  • Use for: ALL component testing - buttons, forms, dialogs, menus, etc.
  • Location: *.stories.tsx files with play functions
  • Speed: Slower (~seconds per story)

2. Unit Tests

  • Purpose: Test utility functions and React hooks in isolation
  • Environment: JSDOM (fast, simulated browser environment)
  • Use for: Pure functions, custom hooks, validators, formatters
  • Location: *.spec.ts or *.spec.tsx files
  • Speed: Very fast (~milliseconds per test)

Running Tests

# Run all tests (unit + Storybook)
pnpm test

# Run only unit tests (fast)
pnpm test:unit

# Run only Storybook tests (slower, browser-based)
pnpm test:storybook

# Run specific test file
pnpm test packages/nimbus/src/components/button/button.stories.tsx

# Run tests with minimal console output
pnpm test --silent

# Run tests in watch mode (unit tests only)
pnpm test:unit --watch

# Run with coverage
pnpm test --coverage

Testing Workflow (IMPORTANT)

[!IMPORTANT] Storybook tests run against the BUILT bundle, not source files.

Why Building is Required

The Storybook configuration operates in two distinct modes:

Mode Command Imports From Purpose
Development pnpm start:storybook Source files (src/) Live editing with HMR
Testing pnpm test:storybook Built bundle (dist/) Test production-like code

During testing, imports resolve to the built bundle in packages/nimbus/dist/. This ensures:

  • Tests validate actual published behavior
  • Tests match how consumers use the package
  • Tests catch build-related issues

Correct Testing Workflow

# ❌ WRONG - Tests will use stale code
# Make changes to component
pnpm test:storybook  # Tests old code!

# βœ… CORRECT - Build first, then test
# 1. Make changes to component
# 2. Build the package
pnpm build:packages

# 3. Run tests
pnpm test:storybook

# Or combine in one command
pnpm build:packages && pnpm test:storybook

Detection Logic

The system automatically detects test mode via:

  • configType === 'DEVELOPMENT' - Set by Vite based on command
  • VITEST_WORKER_ID - Set automatically by Vitest when running tests
  • VITEST=true - Manual override for forcing test mode

Manual Override Example:

# Force test mode (use built bundle) even in development
VITEST=true pnpm start:storybook

# Normal development mode (use source files with HMR)
pnpm start:storybook

When test mode is detected, Storybook uses the built bundle instead of source files.

Developer Visibility:

Storybook logs which mode is active on startup:

  • [Storybook] Running in DEVELOPMENT (HMR enabled, using source files) - Development mode with live reload
  • [Storybook] Running in PRODUCTION/TEST (using built bundle) - Testing or production mode

This helps confirm whether your changes require a build before testing.

Common Testing Patterns

# Quick iteration cycle for component changes
pnpm --filter @commercetools/nimbus build && pnpm test:storybook

# Test specific component
pnpm --filter @commercetools/nimbus build && pnpm test packages/nimbus/src/components/menu/menu.stories.tsx

# Unit tests don't need building (they import source directly)
pnpm test:unit --watch

# Full test suite
pnpm test

Common Pitfalls

Issue Solution
❌ Tests pass but changes don't show Build the package before testing
❌ Tests fail after working locally Ensure pnpm build was run
❌ Expecting HMR during tests Use pnpm start:storybook for live preview
βœ… Build β†’ Test β†’ Iterate This is the correct workflow

πŸ› οΈ Project Management

Initialize or Reset

To initialize or reset the entire project:

# Full initialization (reset, install dependencies, build)
pnpm nimbus:init

# Reset only (remove node_modules and dist folders)
pnpm nimbus:reset

Working with Tokens

Generate design tokens for the system:

pnpm generate:tokens

This command processes the token source files and outputs them in multiple formats:

  • CSS custom properties
  • TypeScript definitions
  • Component-specific token files

πŸ”„ Integration Guide

Testing Local Nimbus Changes in Other Repositories

Want to test your local Nimbus code changes in another repo (like Merchant Center) before publishing? pnpm link --global lets you do this by creating a direct connection (a symlink) between your local Nimbus and the other repo.

Follow these steps:

  1. Build Nimbus: Make sure Nimbus and its internal packages have been built recently with your latest changes. (Via pnpm build command in the Nimbus repo).

  2. Register Nimbus Locally: In your Nimbus design system repository (at the root folder), run:

    pnpm link --global
    • What this does: This tells your computer where your local Nimbus code lives and registers it globally under its package name (nimbus). Think of it like a temporary, local "publishing" step just for your machine.
  3. Connect Your Project to Local Nimbus: In the target repository where you want to use your local Nimbus (such as Merchant Center), run:

    pnpm link --global nimbus
    • Important: You'll need to run this command within the application you want to use it in rather than at the root level - for example, in the application-project-settings directory in the Merchant Center repo.
    • What this does: This connects this specific project to the local Nimbus you just registered. It creates a special link (symlink) inside this project's node_modules folder that points directly to your local Nimbus code.
    • Verification: You can peek inside the target repo's node_modules folder; you should see nimbus listed (often visually indicated as a link).
  4. Import and Use: Now, in your target repo's code, you can import and use Nimbus components.

    // Correct way to import after linking:
    import {
      Box,
      Avatar,
      NimbusProvider,
      Button,
      LoadingSpinner,
    } from '../../../node_modules/nimbus/packages/nimbus'; // <-- This is a relative path to the symlink - you'll have to adjust the depth as needed.
    // Use the components...
    function MyComponent() {
      return (
        <NimbusProvider>
          <Box>
            <Button>Hello Nimbus!</Button>
          </Box>
        </NimbusProvider>
      );
    }
    ```
5.  **Testing changes**: Make changes to your local Nimbus code, then run
    `pnpm build` in Nimbus to rebuild. You should now see changes reflected in
    the target repo.

6. **Unlink when finished**:

   ```bash
   # In the target project:
   pnpm unlink -g nimbus

   # In the Nimbus repository:
   pnpm unlink --global

πŸ‘₯ Contributing

We welcome contributions from all team members. To contribute:

  1. Create a new branch for your feature or fix
  2. Make your changes
  3. Write or update tests
  4. Update documentation
  5. Submit a pull request

Please follow our coding standards and commit message conventions.

❓ Troubleshooting

Problem Solution
Component styles not updating Make sure you've rebuilt the tokens with pnpm build:tokens
Documentation site not showing latest changes Restart the development server with pnpm start
Build errors after pulling latest changes Try running pnpm nimbus:init to reset, reinstall, and rebuild

For additional help, please contact the Nimbus team or submit an issue in our repository.