Getting Started

From zero to a working Gantt chart in 5 minutes. Choose your stack below.

Installation

Install from npm or load directly from a CDN.

npm

npm install nimbus-gantt

yarn

yarn add nimbus-gantt

CDN (UMD)

<script src="https://unpkg.com/nimbus-gantt@latest/dist/nimbus-gantt.umd.js"></script>
<link rel="stylesheet" href="https://unpkg.com/nimbus-gantt@latest/dist/nimbus-gantt.css">

Data Format

Nimbus Gantt uses two core data types: GanttTask and GanttDependency.

GanttTask

interface GanttTask {
  id: string;
  name: string;
  start: string;          // ISO date: "2026-04-01"
  end: string;            // ISO date: "2026-04-15"
  progress?: number;      // 0-100
  resource?: string;      // assigned resource name
  color?: string;         // bar color override
  milestone?: boolean;    // renders as diamond
  parent?: string;        // task ID for hierarchy
  collapsed?: boolean;    // collapse children
}

GanttDependency

interface GanttDependency {
  from: string;           // source task ID
  to: string;             // target task ID
  type?: 'FS' | 'FF' | 'SS' | 'SF';  // default: 'FS'
  lag?: number;           // lag in working days
}

Sample Data

const tasks = [
  { id: '1', name: 'Project Kickoff',   start: '2026-04-01', end: '2026-04-01', milestone: true },
  { id: '2', name: 'Requirements',      start: '2026-04-02', end: '2026-04-08', progress: 100, resource: 'Alice' },
  { id: '3', name: 'Design',            start: '2026-04-09', end: '2026-04-15', progress: 60,  resource: 'Bob' },
  { id: '4', name: 'Development',       start: '2026-04-16', end: '2026-05-06', progress: 0,   resource: 'Charlie' },
  { id: '5', name: 'Testing',           start: '2026-05-07', end: '2026-05-14', progress: 0,   resource: 'Alice' },
  { id: '6', name: 'Go Live',           start: '2026-05-15', end: '2026-05-15', milestone: true },
];

const dependencies = [
  { from: '1', to: '2', type: 'FS' },
  { from: '2', to: '3', type: 'FS' },
  { from: '3', to: '4', type: 'FS' },
  { from: '4', to: '5', type: 'FS' },
  { from: '5', to: '6', type: 'FS' },
];
Vanilla JS

Vanilla JavaScript

The simplest way to get started. Create a container element and initialize the Gantt chart.

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://unpkg.com/nimbus-gantt@latest/dist/nimbus-gantt.css">
</head>
<body>
  <div id="gantt" style="width: 100%; height: 600px;"></div>

  <script src="https://unpkg.com/nimbus-gantt@latest/dist/nimbus-gantt.umd.js"></script>
  <script>
    const gantt = new NimbusGantt('#gantt', {
      tasks: [
        { id: '1', name: 'Design',      start: '2026-04-01', end: '2026-04-10', progress: 80 },
        { id: '2', name: 'Development',  start: '2026-04-11', end: '2026-04-25', progress: 20 },
        { id: '3', name: 'Testing',      start: '2026-04-26', end: '2026-05-05', progress: 0 },
      ],
      dependencies: [
        { from: '1', to: '2', type: 'FS' },
        { from: '2', to: '3', type: 'FS' },
      ],
    });

    // Listen for task changes
    gantt.on('taskUpdate', (task) => {
      console.log('Task updated:', task.name);
    });
  </script>
</body>
</html>
React

React

Use the NimbusGanttChart React component for declarative rendering with hooks integration.

import { useState } from 'react';
import { NimbusGanttChart } from 'nimbus-gantt/react';
import { CriticalPath } from 'nimbus-gantt/plugins/critical-path';
import { UndoRedo } from 'nimbus-gantt/plugins/undo-redo';
import 'nimbus-gantt/dist/nimbus-gantt.css';

function ProjectTimeline() {
  const [tasks, setTasks] = useState([
    { id: '1', name: 'Design',      start: '2026-04-01', end: '2026-04-10', progress: 80 },
    { id: '2', name: 'Development',  start: '2026-04-11', end: '2026-04-25', progress: 20 },
    { id: '3', name: 'Testing',      start: '2026-04-26', end: '2026-05-05', progress: 0 },
  ]);

  const dependencies = [
    { from: '1', to: '2', type: 'FS' },
    { from: '2', to: '3', type: 'FS' },
  ];

  return (
    <NimbusGanttChart
      tasks={tasks}
      dependencies={dependencies}
      plugins={[CriticalPath, UndoRedo]}
      height={600}
      onTaskUpdate={(updated) => {
        setTasks((prev) =>
          prev.map((t) => (t.id === updated.id ? updated : t))
        );
      }}
      onTaskClick={(task) => console.log('Clicked:', task.name)}
    />
  );
}

export default ProjectTimeline;
Tip: The React component automatically handles cleanup on unmount and re-renders efficiently when tasks or dependencies change via referential equality checks.
Salesforce

Salesforce LWC

Load Nimbus Gantt as a static resource and initialize it inside a Lightning Web Component using the loadScript pattern.

1. Upload the static resource

Download nimbus-gantt.umd.js and nimbus-gantt.css from the npm package or GitHub release. Upload both as static resources named NimbusGantt and NimbusGanttCSS.

2. Create the LWC component

// ganttTimeline.js
import { LightningElement, api } from 'lwc';
import { loadScript, loadStyle } from 'lightning/platformResourceLoader';
import GANTT_JS from '@salesforce/resourceUrl/NimbusGantt';
import GANTT_CSS from '@salesforce/resourceUrl/NimbusGanttCSS';

export default class GanttTimeline extends LightningElement {
  @api tasks = [];
  @api dependencies = [];

  ganttInitialized = false;
  ganttInstance;

  async renderedCallback() {
    if (this.ganttInitialized) return;
    this.ganttInitialized = true;

    try {
      await Promise.all([
        loadScript(this, GANTT_JS),
        loadStyle(this, GANTT_CSS),
      ]);

      const container = this.template.querySelector('.gantt-container');

      // NimbusGantt is available on window after loadScript
      this.ganttInstance = new window.NimbusGantt(container, {
        tasks: this.tasks,
        dependencies: this.dependencies,
      });

      this.ganttInstance.on('taskUpdate', (task) => {
        this.dispatchEvent(
          new CustomEvent('taskupdate', { detail: task })
        );
      });
    } catch (error) {
      console.error('Gantt init error:', error);
    }
  }

  disconnectedCallback() {
    if (this.ganttInstance) {
      this.ganttInstance.destroy();
    }
  }
}

3. Add the template

<!-- ganttTimeline.html -->
<template>
  <div class="gantt-container" style="width: 100%; height: 600px;"></div>
</template>
Salesforce note: The loadScript pattern is the standard way to load third-party libraries in LWC. The UMD build attaches NimbusGantt to the window object automatically.

Registering Plugins

Plugins are passed as an array to the constructor (or React component props). They initialize automatically and attach to lifecycle hooks.

import { NimbusGantt } from 'nimbus-gantt';
import { CriticalPath } from 'nimbus-gantt/plugins/critical-path';
import { MonteCarlo } from 'nimbus-gantt/plugins/monte-carlo';
import { DarkTheme } from 'nimbus-gantt/plugins/dark-theme';
import { UndoRedo } from 'nimbus-gantt/plugins/undo-redo';
import { MiniMap } from 'nimbus-gantt/plugins/mini-map';
import { Export } from 'nimbus-gantt/plugins/export';

const gantt = new NimbusGantt('#gantt', {
  tasks,
  dependencies,
  plugins: [
    CriticalPath,
    MonteCarlo,
    DarkTheme,
    UndoRedo,
    MiniMap,
    Export,
  ],
});

// Access plugin APIs after initialization
const criticalTasks = gantt.getPlugin('CriticalPath').getCriticalTasks();
const simulation = gantt.getPlugin('MonteCarlo').run({ iterations: 10000 });

console.log('P50 completion:', simulation.p50);
console.log('P90 completion:', simulation.p90);

Plugin order does not matter

Plugins declare their own dependencies internally. Nimbus Gantt resolves initialization order automatically.

Plugins are tree-shakeable

Each plugin is a separate entry point. Unused plugins are excluded from your bundle by your build tool.

Next Steps