Gantt chart library
A Gantt chart library that stays out of your stack
GanttKit is a Gantt chart library for web applications. A headless core owns the data model, time scale, layout geometry and interaction logic. It never touches the DOM, so the same library works in plain JavaScript, in any UI framework, and in Node during tests.
Framework-agnostic 0 core dependencies Plugin-driven Virtualized TypeScript types MIT
What a Gantt chart library actually has to do
Drawing bars is the easy part. The work that makes a Gantt chart library worth installing sits underneath:
- Time scale. Map dates to pixels across day, week and month view modes, and keep the header grid aligned with the bars while zooming.
- Layout geometry. Turn every task into a rectangle with the right row, offset, width and padding, including milestones that collapse to a single point.
- Virtualization. Emit only what the scroll viewport can show, otherwise a few thousand tasks freeze the main thread.
- Interaction. Hit testing, drag to move, drag to resize, rubber-band selection, and preview state that can be cancelled without corrupting the data.
- Scheduling rules. Finish-to-start dependencies that shift dependents when a predecessor moves.
- Presentation. Theming, localized dates, tooltips, a sidebar of columns, and a toolbar.
Most libraries bundle all of that into one widget. GanttKit splits it: the core computes, plugins extend, and a renderer paints.
Headless core versus monolithic widget
| Concern | Monolithic widget | GanttKit |
|---|
| Framework | Bound to one, or wrapped per framework by the vendor | Core is framework-free; the renderer is the only DOM-aware piece |
| Unused features | Ship in the bundle whether you use them or not | Separate packages, tree-shakeable, install what you use |
| Customization | Configuration flags the vendor anticipated | Plugins that hook the row pipeline and the scene |
| Testing | Needs a browser or a DOM shim | Engine runs in Node; assert on geometry and scene output |
| Rendering target | Fixed | SVG, HTML or Canvas from the same engine and plugins |
What you install
Everything is published under the @ganttkit scope. Pick a renderer, then add feature plugins one by one. Every package ships ESM and CJS builds with TypeScript types.
| Package | Role |
|---|
@ganttkit/core | Headless engine and plugin host. Zero runtime dependencies. |
@ganttkit/svg, @ganttkit/html, @ganttkit/canvas | Renderers. Same engine, same plugins, different painting target. |
@ganttkit/plugin-columns, plugin-tree, plugin-filter | Sidebar columns, hierarchical rows, filtering and sorting. |
@ganttkit/plugin-dependencies, plugin-baseline | Finish-to-start auto-scheduling, planned-versus-actual ghost bars. |
@ganttkit/plugin-progress, plugin-markers, plugin-tooltip | Completion fill, date markers and bands, hover detail cards. |
@ganttkit/plugin-toolbar, plugin-selection, plugin-i18n | View-mode and zoom controls, selection and context menu, localization. |
A chart in fifteen lines
import { createGantt } from '@ganttkit/svg'
import '@ganttkit/svg/styles.css'
const gantt = createGantt({
target: '#chart',
theme: 'dark',
viewMode: 'Week',
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 },
],
},
],
})
Need the sidebar, a tree, or dependencies? Build the engine explicitly and call use() for each plugin. Nothing is registered globally and nothing is hidden behind a config file.
Performance at twenty thousand tasks
The engine runs two passes. The expensive pass recomputes rows, time scale and layout when data changes. The cheap pass rebuilds only the windowed scene on scroll, coalesced to the animation frame.
| Measurement | Result |
|---|
| Scene nodes, naive render at 20,000 tasks | about 90,000 |
| Scene nodes, virtualized | about 80 |
| Scroll rebuild | under 1 ms |
| Full recompute at 20,000 tasks | about 8 ms |
How to choose a Gantt chart library
Whatever you pick, these are the questions worth asking before the integration is hard to reverse:
- License. Is it usable commercially without a key, a seat count, or a per-developer fee?
- Framework coupling. If you migrate frameworks in two years, does the chart survive?
- Bundle cost. Do unused features ship anyway, or can the bundler drop them?
- Types. Are TypeScript definitions shipped and accurate, or community-maintained?
- Virtualization. Does it survive your worst realistic dataset, not the marketing demo?
- Extensibility. When you need a behavior the vendor did not anticipate, is there a documented extension point?
- Testability. Can you assert on layout without booting a browser?
Keep reading
Frequently asked questions
What is a Gantt chart library?
A Gantt chart library turns rows of tasks with start and end dates into a scrollable timeline. It owns the time scale, the layout geometry of every bar, the scroll virtualization, and the drag interactions, so an application only has to supply data and react to changes.
Does a Gantt chart library need a UI framework?
No. GanttKit computes all geometry in a headless core that never touches the DOM, then emits a scene of vector primitives. A renderer paints that scene, so the same engine works with plain JavaScript, React, Vue, Svelte, Angular, or a server-side render.
How many tasks can a Gantt chart library display?
GanttKit virtualizes the scene to the scroll viewport. A 20,000 task chart emits roughly 80 vector nodes instead of about 90,000, a scroll rebuild takes under a millisecond, and a full recompute takes about 8 ms.
Is GanttKit free to use commercially?
Yes. GanttKit is MIT licensed, with no license keys, no seat counts, and no paid tier gating features.