Reference

Timeline Format

The Cronolog import/export format. Use this to construct, parse, or migrate timelines programmatically.

Building an external integration? The JSON feed uses this same schema. See the integration API docs for how to embed a Cronolog timeline in your own site.

Overview

Cronolog supports two import/export formats:

ZIP archive .zip

A ZIP file containing a timeline.json manifest plus image files. This is the full export — metadata, events, and all attached photos.

JSON file .json

A standalone JSON file. Identical schema to timeline.json inside the ZIP, but image fields are ignored on import.

When importing a ZIP, image files are read from the paths declared in each event's images[].path field. When importing a JSON file, all images arrays are ignored.

ZIP archive layout

timeline.zip
├── timeline.json          ← manifest (required)
├── images/
│   ├── cover.jpg          ← cover image (optional, path declared in manifest)
│   └── events/
│       ├── 0/             ← first event (index matches event order in manifest)
│       │   ├── photo.jpg
│       │   └── photo2.webp
│       ├── 1/
│       │   └── photo.jpg
│       └── …

Image filenames within each directory are taken from the original blob filenames. The directory index (0, 1, …) corresponds to the event's position in the events array.

JSON schema

Top-level fields

Field Type Required Notes
format_version integer no Always 1. Ignored on import.
source_timeline_id integer no Internal ID of the originating timeline. Ignored on import.
exported_at string no ISO 8601 datetime. Ignored on import.
timeline object yes Timeline metadata. See below.
taxonomy_terms array no Tag vocabulary for this timeline. See below. Omit or set to [] if unused.
events array yes Ordered array of event objects. See below.

timeline object

Field Type Required Notes
title string yes Display name of the timeline.
description_raw string no Plain text description. Supports *bold*, _italic_, - lists, and [text](url) links.
visibility string no "private" (default), "unlisted", or "public". Older exports may use a "publicly_visible" boolean instead; true maps to "unlisted".
sort_direction string no Display order: "asc" = oldest first (default), "desc" = newest first. Defaults to "asc" on import.
cover_image string no Path to cover image within ZIP (e.g. "images/cover.jpg"). Ignored for JSON-only imports.
cover_image_metadata object no Focal point and photo metadata for cover image. See metadata object below.

taxonomy_terms[] object

Defines the tag vocabulary for this timeline. Terms are referenced by name from each event's tags array. Parents are resolved by name, so list ancestor terms before their children, or let the importer sort it out (it makes multiple passes until all parents are resolved).

Field Type Required Notes
name string yes Term name. Max 50 characters. Case-insensitively unique within the timeline.
parent_name string no Name of the parent term. Omit or set to null for root-level terms.

events[] object

Events are imported in the order they appear in the array. The stored order on the timeline is determined by start_at after import, not array position.

Field Type Required Notes
title string yes Event title.
description_raw string no Plain text. Same markup support as timeline description.
date_input_raw string yes* The human-readable date string as originally entered (e.g. "June 1977", "1985", "late '90s"). Used for display. See date formats below.
end_date_input_raw string no End of a date range (e.g. "March 2004"). Omit for point-in-time events.
start_at string yes* ISO 8601 datetime. The computed start boundary for this event. Used for chronological ordering.
end_at string yes* ISO 8601 datetime. The computed end boundary. For a year event this is Dec 31 23:59:59.
precision string yes* "exact" or "bounded" or "symbolic".
precision_unit string yes* "day", "month", "year", or "phase".
display_label string no Human-readable date label shown on the timeline (e.g. "June 1977" or "1999 - 2005"). For ranged events (end_date_input_raw present), always recomputed from the raw inputs on import — any supplied value is replaced. For point-in-time events, derived from date_input_raw if omitted.
tags array no Array of tag name strings (e.g. ["Career", "Travel"]). Each name must match a term in taxonomy_terms[]. Unrecognised names are silently ignored on import.
images array no Ordered array of image objects. Ignored for JSON-only imports.

* Fields marked yes* are required when constructing JSON for import. When generating JSON programmatically, provide both date_input_raw (human-readable) and the computed start_at / end_at / precision / precision_unit fields.

images[] object

Field Type Notes
path string Path to the image file within the ZIP archive (e.g. "images/events/0/photo.jpg").
content_type string MIME type (e.g. "image/jpeg", "image/webp").
position integer 1-based display order within the event. Images are sorted by this value on import.
metadata object Optional. See metadata object below.

metadata object

Appears on both timeline.cover_image_metadata and each images[].metadata. All fields optional.

Field Type Notes
focal_x float Horizontal focal point as a fraction 0.0–1.0 (0 = left edge, 1 = right edge). Used for smart image cropping.
focal_y float Vertical focal point as a fraction 0.0–1.0 (0 = top edge, 1 = bottom edge).
photo_taken_at string ISO 8601 datetime when the photo was taken, if known.

Date formats for date_input_raw

Cronolog's date parser accepts a wide range of human-readable formats. The corresponding start_at, end_at, precision, and precision_unit values are derived from the input.

Input example precision_unit display_label
1985 year 1985
'85 / 85 year 1985
June 2003 month June 2003
jun 2003 / 2003-06 / 6/2003 month June 2003
June 15 2003 day June 15, 2003
2003-06-15 / 6/15/2003 day June 15, 2003
1980s / '80s phase The 1980s
early 1980s / early '80s phase Early 1980s
mid 1980s phase Mid 1980s
late 1980s / late '85 phase Late 1985
early oct 2027 phase Early October 2027
circa 1920 / ~1920 / ca. 1920 year 1920
1999 - 2005 / 1999 to 2005 year (start) 1999 - 2005
June 2003 - March 2004 month (start) June 2003 - March 2004
between 1940 and 1945 year (start) 1940 - 1945

Two-digit years use a rolling pivot: values ≤ the current two-digit year resolve to this century; larger values resolve to the previous century. Approximation prefixes (circa, ca., ~) are stripped before parsing.

Complete example

A minimal but complete timeline.json with two events — one exact date, one date range — and one image attachment.

{
  "format_version": 1,
  "source_timeline_id": 42,
  "exported_at": "2025-11-03T14:22:00Z",
  "timeline": {
    "title": "Life of Francis",
    "description_raw": "A record of my grandmother's life.",
    "visibility": "private",
    "sort_direction": "asc",
    "cover_image": "images/cover.jpg",
    "cover_image_metadata": {
      "focal_x": 0.5,
      "focal_y": 0.3
    }
  },
  "taxonomy_terms": [
    { "name": "Travel" },
    { "name": "Canada", "parent_name": "Travel" }
  ],
  "events": [
    {
      "title": "Moved to Vancouver",
      "description_raw": "She was 19. \"I only had one suitcase.\"",
      "date_input_raw": "1962",
      "end_date_input_raw": null,
      "start_at": "1962-01-01T00:00:00Z",
      "end_at": "1962-12-31T23:59:59Z",
      "precision": "bounded",
      "precision_unit": "year",
      "display_label": "1962",
      "tags": ["Travel", "Canada"],
      "images": []
    },
    {
      "title": "World tour",
      "description_raw": "First time abroad. Three months, twelve countries.",
      "date_input_raw": "July 1971",
      "end_date_input_raw": "September 1971",
      "start_at": "1971-07-01T00:00:00Z",
      "end_at": "1971-09-30T23:59:59Z",
      "precision": "bounded",
      "precision_unit": "month",
      "display_label": "July - September 1971",
      "tags": ["Travel"],
      "images": [
        {
          "path": "images/events/1/passport.jpg",
          "content_type": "image/jpeg",
          "position": 1,
          "metadata": {
            "focal_x": 0.48,
            "focal_y": 0.35,
            "photo_taken_at": "1971-08-15T00:00:00Z"
          }
        }
      ]
    }
  ]
}

Notes for agents and automated tools

  • Always provide both the human-readable date_input_raw and the computed start_at / end_at. The import uses the explicit datetime fields directly; date_input_raw is stored for display and future re-parsing.
  • For fuzzy dates, derive start_at and end_at from the boundaries implied by the precision: a year-precision date spans Jan 1 00:00:00 to Dec 31 23:59:59; a month-precision date spans the first to last day of the month.
  • All datetimes must be ISO 8601 strings in UTC (e.g. "1962-01-01T00:00:00Z").
  • end_at must always be greater than or equal to start_at.
  • For JSON-only imports (no ZIP), set images to an empty array or omit it entirely. Image fields in the manifest are silently ignored without a ZIP.
  • The events array can be empty. A timeline with no events is valid.
  • Tags are matched case-insensitively during import. Declare all terms in taxonomy_terms before referencing them in event tags. Terms not present in taxonomy_terms are silently ignored when tagging events.
  • Description fields support a small set of inline markup: *bold*, _italic_, - list item (line-starting hyphen), and [link text](https://url) for hyperlinks. Plain URLs are auto-linked. All other HTML is stripped on render.