GanttKit / JavaScript Gantt chart
JavaScript Gantt chart

A JavaScript Gantt chart you can drop into any app

GanttKit is a JavaScript Gantt chart library built as a headless engine plus a renderer. Install two packages, point createGantt at an element, and you have a scrollable, draggable timeline. No framework, no global registration, no config file.

Plain JavaScript 0 core dependencies ESM + CJS Tree-shakeable SSR-safe core MIT
$ npm i @ganttkit/core @ganttkit/svg Launch live demo Read the docs

Install the npm packages

Every package lives under the @ganttkit scope on npm. You always need the core plus one renderer. Feature plugins are separate packages, so an unused feature costs nothing in your bundle.

# core + the SVG renderer
npm i @ganttkit/core @ganttkit/svg

# or the HTML renderer, or canvas for very large datasets
npm i @ganttkit/core @ganttkit/html
npm i @ganttkit/core @ganttkit/canvas

# add only the features you use
npm i @ganttkit/plugin-columns @ganttkit/plugin-tree @ganttkit/plugin-progress

The core has zero runtime dependencies, so the npm install adds no transitive tree of its own. Packages ship both ESM and CommonJS builds with TypeScript definitions included.

Render your first chart

createGantt builds the engine and installs the renderer in one call. The target element only needs a height; the chart fills it and scrolls internally.

import { createGantt } from '@ganttkit/svg'
import '@ganttkit/svg/styles.css'

const gantt = createGantt({
  target: '#chart',      // selector or HTMLElement
  theme: 'dark',         // 'dark' | 'light'
  viewMode: 'Week',      // 'Day' | 'Week' | 'Month'
  rows: [
    {
      id: 'design',
      name: 'Design',
      tasks: [
        { id: 't1', name: 'Wireframes', start: '2026-07-01', end: '2026-07-08', progress: 1 },
        { id: 't2', name: 'Mockups', start: '2026-07-09', end: '2026-07-20', progress: 0.4 },
      ],
    },
    {
      id: 'build',
      name: 'Development',
      tasks: [
        { id: 't3', name: 'API', start: '2026-07-15', end: '2026-08-05', progress: 0.2 },
        { id: 'ms', name: 'Launch', start: '2026-08-31', end: '2026-08-31', kind: 'milestone' },
      ],
    },
  ],
})
<div id="chart" style="height: 480px"></div>

The data model

A chart is an array of rows; each row owns an array of tasks. Dates are ISO strings or Date objects, parsed by a replaceable date adapter.

FieldTypeNotes
idstringRequired, unique. Dependencies reference task ids.
namestringRendered as the bar label and the default sidebar column.
start, endstring | DateRequired on tasks. end is inclusive, so a same-day task is one day wide.
kind'task' | 'milestone'Optional. A milestone renders as a diamond at end.
progressnumberOptional, 0 to 1. Drawn by the progress plugin.
dependenciesstring[]Optional predecessor task ids, finish-to-start.

Compose plugins instead of toggling options

When you need more than bars, build the engine yourself and install plugins with use(). The engine is chainable and recomputes after every install. The same plugin array works with any renderer, so switching from SVG to Canvas is an import change.

import { GanttEngine } from '@ganttkit/core'
import { svgRenderer } from '@ganttkit/svg'
import { createColumns } from '@ganttkit/plugin-columns'
import { createTree } from '@ganttkit/plugin-tree'
import { progressPlugin } from '@ganttkit/plugin-progress'
import '@ganttkit/svg/styles.css'

const engine = new GanttEngine({ rows, viewMode: 'Week' })

engine.use(svgRenderer({ target: '#chart', theme: 'dark' }))
engine.use(createColumns({ columns: [{ key: 'name', label: 'Task' }] }).plugin)
engine.use(createTree().plugin)
engine.use(progressPlugin())

Update the chart at runtime

The engine is the source of truth. Mutating methods recompute the pipeline and the renderer repaints from the new scene.

gantt.setRows(nextRows)                                  // replace the dataset
gantt.updateTask('t2', { progress: 0.8 })                // patch one task
gantt.updateTaskDates('t3', '2026-07-20', '2026-08-12')  // move or resize
gantt.setViewMode('Month')                               // zoom out
gantt.destroy()                                          // remove listeners, dispose plugins

Drag to move and drag to resize are enabled by default. Turn them off globally with the draggable option, or per task with draggable: false on the task itself.

Bundle behavior

Keep reading

TypeScript Gantt chart

The shipped type definitions, key interfaces, and typed plugin authoring.

Read more

Gantt chart component

Wrap the engine as a React, Vue, Svelte or Angular component.

Read more

Gantt chart library

The architecture, the package map, and how to compare Gantt libraries.

Read more

Open source Gantt chart

MIT licensed, no keys, no telemetry, no gated features.

Read more

Frequently asked questions

Which npm package do I install for a JavaScript Gantt chart?

Install @ganttkit/core together with a renderer: @ganttkit/svg, @ganttkit/html or @ganttkit/canvas. Feature plugins such as @ganttkit/plugin-columns are separate packages, so you only add the ones you use.

Does the JavaScript Gantt chart work without a framework?

createGantt takes a CSS selector or an HTMLElement and mounts into it. There is no framework dependency in the core or the renderers, so plain JavaScript with a bundler is enough.

How do I update tasks after the chart is rendered?

Call setRows to replace the dataset, updateTask to patch a single task, or updateTaskDates to move one. The engine recomputes and the renderer repaints the affected part of the scene.

Does it support drag to reschedule?

Dragging is on by default and can be disabled globally with the draggable option or per task. With the dependencies plugin installed, moving a predecessor shifts its dependents.