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/coreimports no framework.@fluxgantt/reactand@fluxgantt/vuegive you a real<FluxGantt>component + hook / composable. - Correct dates. All date/time math goes through the Temporal API — timezone- and
DST-correct, not native
Dateguesswork. - 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 3Quick 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
| FluxGantt | dhtmlx Community | Frappe Gantt | |
|---|---|---|---|
| License | MIT | MIT | MIT |
| Bundle (gzip, incl. required CSS) | 19.16 KiB editable · 7.35 KiB headless | 226.18 KiB | 14.89 KiB |
| Language | TypeScript-first, branded IDs | JavaScript | JavaScript, no types shipped |
| Dependency types | FS / SS / FF / SF (+ lag/lead) | all four | FS only |
| Critical path (CPM) | Built in, color-independent marker | No (PRO only) | No |
| Working calendar | Temporal-based, DST-correct | Yes | No |
| Headless (runs without a DOM) | Yes | No | No |
| React / Vue wrappers | First-class | No | No |
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
| Tier | Price | Includes |
|---|---|---|
| Core (MIT) | Free | Rendering, 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 sale | Resource 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:
examples/plain-html-demo— vanilla@fluxgantt/coreexamples/react-vite-demo—@fluxgantt/reactexamples/vue-vite-demo—@fluxgantt/vue
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