The Markdown format

A data story is a Markdown file. The story editor writes it for you, but you can also write or tweak one by hand. This page shows the building blocks. Every example is a working one for the Wikidata profile.

Let the editor write the hard parts

The JSON inside map, graph, embed and music blocks is checked strictly by SHMARQL. The easiest way to get it right is to make the node in the editor, then Export and copy the block from story.md. The examples below are complete, minimal starting points.

Front matter

---
title: Vermeer in Wikidata
description: Where the paintings of Johannes Vermeer are today.
keywords: [Vermeer, Wikidata]
language: en
license: CC BY 4.0
lodeon:
  htmlMeta:
    description: Where the paintings of Johannes Vermeer are today.
  openGraph:
    title: Vermeer in Wikidata
    type: article
  jsonLd:
    "@context": https://schema.org
    "@type": ScholarlyArticle
    headline: Vermeer in Wikidata
---

title is the page title. Everything under lodeon: goes into the page head: htmlMeta as <meta name=…> tags, openGraph as <meta property="og:…"> tags, and jsonLd as a <script type="application/ld+json"> block. The editor fills all of this from the metadata panel. The lodeon: section also marks the page as a data story.

SPARQL Query: shmarql

```shmarql {title="Paintings by Johannes Vermeer" kg="wikidata"}
SELECT ?painting ?paintingLabel WHERE {
  ?painting wdt:P170 wd:Q41264 .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
LIMIT 20
```
  • kg is the profile name. Without it, the default profile is used and the table is made on the server.
  • title is shown above the table.
  • The query runs in the reader's browser, through the read-only /api/sparql/<kg>.

Plotly Visualization: lodeon-visualization

The body is JSON. The runtime only needs a Plotly figure (data, layout, config):

```lodeon-visualization {title="Paintings per painter"}
{
  "renderer": "plotly",
  "figure": {
    "data": [{"type": "bar",
              "x": ["Rembrandt", "Jan Steen", "Frans Hals", "Pieter de Hooch", "Johannes Vermeer"],
              "y": [751, 482, 307, 201, 36]}],
    "layout": {"height": 360, "yaxis": {"title": {"text": "Paintings"}}}
  }
}
```

The editor stores more: the source (sourceMode sparql, csv, tsv or url, with the query or data), chartType, the column mapping, the editable plotlyDataJson/layoutJson/configJson and the table data. That is what lets you edit the chart again later.

RAWGraphs Visualization: lodeon-rawgraphs

```lodeon-rawgraphs {title="A chart from RAWGraphs"}
{
  "renderer": "rawgraphs",
  "svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"200\" height=\"60\"><rect width=\"120\" height=\"40\" fill=\"#0072B2\"/></svg>"
}
```

Readers see the svg. The editor also stores the RAWGraphs projectJson and a summary, so the chart can be rendered again from the project.

Leaflet Map: lodeon-leaflet

```lodeon-leaflet {title="Two museums"}
{
  "renderer": "leaflet",
  "featureCollection": {
    "type": "FeatureCollection",
    "features": [
      {"type": "Feature", "geometry": {"type": "Point", "coordinates": [4.885278, 52.36]},
       "properties": {"label": "Rijksmuseum", "resource": "http://www.wikidata.org/entity/Q190804", "category": "Amsterdam"}},
      {"type": "Feature", "geometry": {"type": "Point", "coordinates": [4.314306, 52.080389]},
       "properties": {"label": "Mauritshuis", "resource": "http://www.wikidata.org/entity/Q221092", "category": "The Hague"}}
    ]
  },
  "tileLayerId": "openStreetMap",
  "height": 420,
  "initialView": "fitBounds",
  "center": [52.2, 4.6],
  "zoom": 8,
  "fitBoundsMaxZoom": 12,
  "clustering": {"enabled": false, "disableAtZoom": null, "showCoverageOnHover": true,
                 "spiderfyOnMaxZoom": true, "spiderfyDistanceMultiplier": 1.5},
  "legend": {"enabled": true, "position": "bottomRight", "title": "City"},
  "popupFields": ["label", "resource", "category"],
  "markerStyle": {"radius": 7, "color": "#005A8D", "fillColor": "#0072B2", "fillOpacity": 0.8, "weight": 2},
  "caption": "Two museums with paintings by Vermeer."
}
```
  • GeoJSON coordinates are longitude, latitude; center is latitude, longitude (as in Leaflet).
  • tileLayerId must be one of the map backgrounds in the LODEON settings (openStreetMap by default).
  • initialView is fitBounds (zoom to the data) or configured (use center and zoom).
  • Features carry their own data. The map doesn't run a query when it is read.

Graph Explorer: lodeon-graph-explorer

```lodeon-graph-explorer {title="Around Vermeer"}
{
  "renderer": "graphExplorer",
  "knowledgeGraphProfileId": "wikidata",
  "items": [{"iri": "http://www.wikidata.org/entity/Q41264", "label": "Johannes Vermeer"}],
  "direction": "outgoing",
  "depth": 1,
  "maxNodes": 60,
  "maxEdgesPerNode": 25,
  "showLiterals": false,
  "height": 520
}
```

The graph is fetched live from /api/explorer/<profile>/expand each time the page is read, starting from the items.

IIIF Object: lodeon-iiif

By URL (one manifest or info.json per line in url):

```lodeon-iiif {title="Rembrandt, Portrait of Eleazar Swalmius"}
{
  "renderer": "iiif",
  "sourceMode": "url",
  "url": "https://iiif.kmska.be/iiif/2/968/manifest.json",
  "viewMode": "single",
  "height": 520
}
```

From a query, run live through the profile. The query returns ?manifest (or ?imageInfo), and optionally ?label and ?resource:

```lodeon-iiif {title="Paintings in the SMK"}
{
  "renderer": "iiif",
  "sourceMode": "sparql",
  "knowledgeGraphProfileId": "wikidata",
  "query": "SELECT ?resource ?label ?manifest WHERE { ?resource wdt:P170 wd:Q5598 ; wdt:P6108 ?manifest . FILTER(STRSTARTS(STR(?manifest), \"https://api.smk.dk/\")) SERVICE wikibase:label { bd:serviceParam wikibase:language \"en\". ?resource rdfs:label ?label . } } LIMIT 10",
  "resultMapping": {"manifest": "manifest", "imageInfo": "imageInfo", "label": "label", "resource": "resource"},
  "viewMode": "gallery",
  "galleryReferenceStrip": "horizontal"
}
```

Embed Remote Content: lodeon-embed

```lodeon-embed {title="A map from the Wikidata Query Service"}
{
  "renderer": "iframe",
  "url": "https://query.wikidata.org/embed.html#%23defaultView%3AMap%0ASELECT%20%3Fm%20%3Fc%20WHERE%20%7B%20%3Fp%20wdt%3AP170%20wd%3AQ41264%20%3B%20wdt%3AP195%20%3Fm%20.%20%3Fm%20wdt%3AP625%20%3Fc%20%7D",
  "aspectRatio": "16:9",
  "caption": "Collections with paintings by Vermeer."
}
```
  • The URL's origin must be in nodes.embed.allowedOrigins, or the block shows a warning instead. The sandbox and allow of the frame also come from those settings, not from the block.
  • For a gallery, add "urls": […] (or "items": [{"url": …, "label": …}]), "viewMode": "gallery" and "galleryReferenceStrip": "horizontal", "vertical" or "none".
  • aspectRatio is 16:9, 4:3, 1:1, … or custom together with "height": <pixels>.

Music Notation: lodeon-verovio

```lodeon-verovio {title="Frère Jacques"}
{
  "renderer": "verovio",
  "items": [
    {
      "id": "frere-jacques",
      "data": "@clef:G-2\n@keysig:\n@timesig:4/4\n@data:4'CDEC/CDEC/EF2G/4EF2G/",
      "format": "pae",
      "label": "Frère Jacques",
      "resource": "http://www.wikidata.org/entity/Q825728",
      "resourceLabel": "Frère Jacques (nursery rhyme)",
      "bindings": {},
      "status": {"state": "ready", "messages": []}
    }
  ],
  "viewMode": "single",
  "selectedItemId": "frere-jacques",
  "documentLayout": "responsive",
  "initialZoom": 1,
  "paginatedPageHeight": 1400,
  "visibleMetadataFields": [],
  "playback": {"tempoMultiplier": 1, "loop": false, "volume": 0.8},
  "compare": {"aItemId": null, "bItemId": null, "synchronizedZoom": true, "aZoom": 1, "bZoom": 1,
              "playbackMode": "a", "loopSequence": false, "tempoMultiplier": 1,
              "targetKey": null, "showTransposed": false},
  "caption": ""
}
```

format is pae (Plaine & Easie) or mei (MEI). viewMode is single, list, grouped (by resource) or compare (two items side by side, set with compare.aItemId and compare.bItemId).

Media Asset

Media assets are plain Markdown or HTML pointing into the story's assets/ folder:

[![The Night Watch](assets/images/night-watch.jpg "The Night Watch")](https://commons.wikimedia.org/wiki/File:La_ronda_de_noche,_por_Rembrandt_van_Rijn.jpg)

The Night Watch. Rembrandt van Rijn, The Night Watch, 1642, Public domain

<audio controls src="assets/audio/interview.mp3"></audio>

<video controls src="assets/videos/tour.mp4"></video>

The editor adds a caption line from the asset's metadata, and with extended metadata switched on a collapsible table with all fields.

Story Metadata

The Story Metadata node becomes an HTML block, made from the project metadata when the Markdown is written:

<section class="tile lodeon-story-metadata" aria-label="About this story">
<dl>
<dt><strong>Author:</strong></dt>
<dd><strong>Josiah Carberry</strong>, …</dd>
<dt><strong>License:</strong></dt>
<dd>CC BY 4.0</dd>
</dl>
</section>

Ordinary Markdown

Everything from writing documentation pages works in stories too: headings, lists, tables, quotes, images, /// blocks and ```sparql code blocks with a ▶ run link.