Skip to content
Zeitlines

A product roadmap you host, with pricing attached

A product roadmap in Zeitlines is a database-backed timeline with the product-roadmap plugin switched on. Beyond the usual phases and lanes it carries a pricing model: tiers, features, and a matrix cell for every pair — each of which can say from which version it applies.

What the setup looks like

You need a Postgres database, because a roadmap of this kind is edited rather than written. Beyond that, enabling the roadmap behaviour on a timeline is a row in a table rather than a schema change — the plugin registry stores which plugins a timeline carries and their configuration, so switching it on is an insert.

  1. Point the deployment at Postgres and run the migrations.
  2. Create the timeline and its items, either in the browser or by importing a JSON file with npm run db:import -- your-roadmap.
  3. Seed the pricing model once, then edit it cell by cell in the pricing view.

The pricing model is the source, not a copy

The model lives normalised in its own tables — features, tiers, the matrix cell by cell, the highlight cards, and the ordered list of versions. The server assembles those into one shape that the viewer, the Markdown export and the public endpoint all read. There is one place to change a price, and everything that shows it follows.

That endpoint is the part worth knowing about if you have a marketing site:

GET /api/pricing/<timeline-id>   → 200 application/json

It needs no session and no token, and the response has the internal row versions stripped out. Your pricing page fetches it at build time and renders whatever it likes; nobody has to keep a second copy of the tiers in sync by hand.

Editing it

The pricing view renders the matrix with a cell for every tier and feature. A cell is a click: on, off, or on-from-a-version. Features and tiers are added, renamed, reordered and deleted in place, and the card view of the same model updates with them.

Every one of those actions is its own request against its own row, which is what makes concurrent editing safe. The alternative — replacing the whole model on each save — is exactly what used to lose edits, so it now exists only as an explicit bulk seed.

Where the roadmap and the pricing meet

Because the plugin knows the pricing model, it also contributes item fields derived from it: Version, Tier and Features. They appear in the item form under the plugin's own heading, and they work everywhere a built-in field does — you can group the timeline by tier, or filter it down to one version, without any of that being special-cased in the core.

What it costs

Nothing in licence terms: Zeitlines is MIT-licensed and there is no paid tier. What it costs is the hosting — a static site plus a Postgres database — and the setup time to point one at the other.

Related

Frequently asked questions

Can a Zeitlines roadmap be public while the rest stays internal?
Yes, and that split is deliberate. The deployment can sit behind a Google sign-in with an allowed-domain whitelist, while the assembled pricing model of a roadmap is served from a separate endpoint that carries no auth requirement. A public pricing page can read it; the roadmap behind it stays gated.
How does the pricing matrix handle versions?
The roadmap carries an ordered list of version labels, and every cell of the tier × feature matrix can name the version it becomes available from. A cell with no version applies from the start. That is what turns the matrix into a roadmap rather than a snapshot: it says when a tier gains a feature, not only whether it has one.
What happens when two people edit the pricing matrix at the same time?
Each write targets one row — one feature, one tier, one cell — and carries the row version it was based on in an If-Match header. A write based on a stale version comes back as 409 rather than overwriting. Wholesale replacement exists only as an explicit seeding operation.
Can I keep the pricing model in Markdown as well?
Yes. npm run export:pricing writes a Markdown mirror of the model, which is useful when the same numbers have to appear in a document that is reviewed rather than rendered.