Skip to content
Zeitlines

A project plan that lives next to the project

Drop a JSON file into the data folder and Zeitlines registers it as a timeline. Tasks, phases, milestones and dependencies are all in that one file, so the plan is reviewed, diffed and versioned exactly like the code it plans.

The whole setup

git clone https://github.com/zeitlines/zeitlines.git
cd zeitlines
npm install
cp your-plan.json data/
npm run dev

The build copies the file into the static output and registers it as a view named after the file. No configuration file to edit, no database to point at, no environment variables to set. Adding a second plan means adding a second file.

What a task can carry

An item needs a start and a label. Everything past that is optional, and the fields are the ones a plan actually uses rather than a generic property bag:

FieldWhat it does
end / duration Turns a point into a bar. Mutually exclusive; 7d, 2w, 90m and ISO durations all parse.
group The lane the bar sits in. Groups can nest, and a parent lane collapses.
icon A semantic key — milestone, launch, review, deadline, decision, bug and others — rendered as a glyph on the bar.
status Open, Doing or Done. A bar the timeline has already passed while its status says otherwise gets an overdue mark.
body Markdown, shown in the detail panel when the item is selected.
metadata.owner Who is on it. An e-mail links to the person; free text renders as-is.
metadata.dependsOn Ids of the items this one follows. Drawn as right-angle arrows.
metadata.tags Colour-coded labels you can filter and group by.

Phases across the top

A phase is a labelled ribbon pinned above the lanes, with a faint tint behind the items it spans — Discovery, Build, Rollout, whatever your stages are called. Phases need a label, a start and an extent, and they must not overlap in time. Touching boundaries and gaps are both fine.

That rule is enforced rather than documented: an overlapping phase is rejected on write, from the interface, the API and the agent tools alike, because overlapping ribbons used to let the phase underneath show through the gap and read as a rendering bug.

The file is checked, not just parsed

Add one line to the top of your plan and your editor knows the format:

"$schema": "../schema/timeline.schema.json"

That schema is generated from the viewer's own TypeScript types, so it cannot describe a field the code no longer reads. Unknown keys are errors rather than silently accepted — a typo in a field name surfaces in your editor instead of vanishing at render time.

Two constraints a schema cannot express are enforced anyway: an item's end must lie after its start, and phases must not overlap. Both are checked on every write path, and the interface refuses the edit with the reason shown under the field rather than accepting it and rendering a hairline bar.

Why keep the plan in git

A plan in a repository gets the things a plan in a hosted tool does not: a diff, a review, a history that says who moved the date and when, and a branch where you can try a different schedule without anybody else seeing it. When the plan and the work live in the same repository, a pull request can change both at once.

Related

Frequently asked questions

Can I make a Gantt chart without an account or a subscription?
Yes. A Zeitlines file-based timeline is a JSON file plus a static viewer you run locally or host anywhere. There is no account, no per-seat licence and no server component — the whole thing is the MIT-licensed source and one data file.
How do I set the length of a task?
Either give the item an end date or a duration such as 7d, 2w, 90m or the ISO form P7D. The two are mutually exclusive. An item with only a start renders as a point — a milestone.
Does Zeitlines draw dependency arrows?
Yes. Put the ids of the items something depends on into metadata.dependsOn and the viewer draws right-angle arrows between the bars and lists the dependencies in the detail panel.
Can I edit a file-based timeline in the browser?
No, and that is on purpose. A file source is read-only, because the file itself is the source of truth — letting the browser write to it would mean the JSON in your repository and the plan on screen could disagree. Editing in the browser is what the database-backed timelines are for.
Can I share the chart with someone who cannot run it?
Yes. npm run export -- <view> writes that view out as a standalone HTML file which opens straight in a browser, with no server behind it.