Skip to content
FluxGantt

FluxGantt

The Modern MIT-Licensed Gantt Chart Library

TypeScript-first · headless · framework-agnostic. A Gantt engine you embed in your own app — render to SVG, drag to reschedule, compute the critical path, export to JSON/CSV/SVG/PNG. No DOM required for the engine; it runs in Node, Workers, and tests.

Why FluxGantt

  • 7.35 KiB gzip for the engine. Rendering, interaction, IO, theming and responsive behaviour are opt-in imports on separate subpaths, so you download what you compose — an editable chart is 19.16 KiB, everything composed is 23.85 KiB. Budgets are enforced on every pull request. These sizes exclude the Temporal polyfill (~45.8 KiB gzip), which runtimes without native Temporal (Node 22/24, older browsers) need. See Comparison for how that lands against dhtmlx, Bryntum, SVAR and Frappe.
  • Headless engine. State + compute (critical path, working calendar, cascade) run without a DOM. The render layer is a separate concern you can swap or server-side-render around.
  • Zero required host CSS. The SVG renderer bakes every visual property inline with a --fg-* custom-property fallback — the chart renders correctly even if you ship no stylesheet. Override the tokens when you want to theme it.
  • Framework-agnostic core, idiomatic wrappers. @fluxgantt/core imports no framework. @fluxgantt/react and @fluxgantt/vue give you a real <FluxGantt> component + hook / composable.
  • Correct dates. All date/time math goes through the Temporal API — timezone- and DST-correct, not native Date guesswork.
  • Accessible by construction. The critical path is distinguished by a dashed outline, not color alone — so it survives color-blindness and grayscale printing.
  • TypeScript end-to-end. Branded IDs (TaskId, DependencyId…) stop you mixing entity ids at compile time.

Install

# Coming soon to npm (see the pre-release note above).
pnpm add @fluxgantt/core
# Optional framework wrappers:
pnpm add @fluxgantt/react   # React 18/19
pnpm add @fluxgantt/vue     # Vue 3

Quick start

Create tasks, link a couple of them, and mount — about 15 lines. This is the same code as examples/plain-html-demo.

import { createGantt, toTaskId } from '@fluxgantt/core';
import { withRender } from '@fluxgantt/core/render';
import { withInteraction } from '@fluxgantt/core/interaction';
 
// Rendering and interaction are opt-in mixins — a headless consumer (server-side
// scheduling, tests) never downloads them. Compose both for a live, editable chart.
const gantt = withInteraction(
  withRender(
    createGantt({
      tasks: [
        { id: toTaskId('design'), name: 'Design', start: '2026-08-03', end: '2026-08-05', progress: 1, type: 'task' },
        { id: toTaskId('build'), name: 'Build', start: '2026-08-05', end: '2026-08-10', progress: 0.6, type: 'task' },
        { id: toTaskId('review'), name: 'Review', start: '2026-08-10', end: '2026-08-12', progress: 0, type: 'task' },
        { id: toTaskId('launch'), name: 'Launch', start: '2026-08-12', end: '2026-08-12', progress: 0, type: 'milestone' },
        { id: toTaskId('docs-task'), name: 'Write docs', start: '2026-08-06', end: '2026-08-11', progress: 0.2, type: 'task' },
      ],
      dependencies: [
        { from: toTaskId('design'), to: toTaskId('build'), type: 'FS' },
        { from: toTaskId('build'), to: toTaskId('review'), type: 'FS' },
      ],
    }),
  ),
);
 
gantt.on('task:moved', (task, prevStart) => {
  console.log(`${task.name} moved from ${prevStart}`);
});
 
gantt.mount(document.getElementById('gantt')!);

Using React or Vue instead? See the React guide and Vue guide.

How it compares

FluxGanttdhtmlx CommunityFrappe Gantt
LicenseMITMITMIT
Bundle (gzip, incl. required CSS)19.16 KiB editable · 7.35 KiB headless226.18 KiB14.89 KiB
LanguageTypeScript-first, branded IDsJavaScriptJavaScript, no types shipped
Dependency typesFS / SS / FF / SF (+ lag/lead)all fourFS only
Critical path (CPM)Built in, color-independent markerNo (PRO only)No
Working calendarTemporal-based, DST-correctYesNo
Headless (runs without a DOM)YesNoNo
React / Vue wrappersFirst-classNoNo

Frappe is smaller than an editable FluxGantt chart, and the full comparison says so rather than hiding it — along with where dhtmlx and Bryntum still win, how every number was measured, and the script that re-measures them.

Tiers

TierPriceIncludes
Core (MIT)FreeRendering, dependencies (FS/SS/FF/SF), hierarchy, critical path, React/Vue (Svelte/Angular planned), export PNG/SVG/JSON/CSV
Pro (perpetual)About $600–800/dev, planned, not yet on saleResource view + leveling, baselines, constraints, MS Project XML I/O, PDF branding. 12 months of updates, optional renewal. Use in SaaS products allowed, no OEM surcharge

Only the Core tier is documented here — it is the only tier that exists today. There is no hosted Cloud plan on the roadmap.

Run the examples

Nine examples ship in the repository — six vanilla pages, a React app, a Vue app and a headless snippet. The full catalogue is on the Examples page; the three apps are:

git clone https://github.com/thai-pc/fluxgantt
cd fluxgantt && pnpm install && pnpm build
pnpm --filter plain-html-demo dev   # or react-vite-demo / vue-vite-demo