Broadsheet

Reference

Every Building Block, With the Markdown That Makes It

A working catalog of what Broadsheet can put on a page. Each example shows the block and the Markdown you write to get it. Copy what you need into your own story.

Style guideAll examples use inline data

A story is a Markdown file with front matter on top. Plain paragraphs sit in a narrow reading column. Blocks fenced with ::: add charts, tables and other pieces. Every ## heading starts a new section.

The header

The header comes from front matter at the top of the file:

---
title: If Every Indian State Became Its Own Country, Which Ones Would Last?
kicker: A thought experiment          # small caps line above the headline
deck: One or two sentences under the headline.
date: 2026-09-26
byline: Your Name                      # optional
meta:                                  # optional facts under the rule
  - "**Illustrative model, not a forecast**"
  - Starting figures are rounded 2023–24 estimates
draft: true                            # hidden from the published build
scripts: [sim.js]                      # optional custom JS in the story folder
styles: [extra.css]                    # optional custom CSS in the story folder
image: cover.png                       # optional link-preview image (otherwise one is drawn for you)
---

Callouts and notes

A callout pulls one finding out of the text. Use it for the sentence you most want readers to remember.

:::callout
**A callout** pulls one finding out of the text.
:::

A note is small print: caveats, rounding and definitions.

Bar charts

A bar chart draws one bar per row. If any value is negative, the bars grow left and right from a centre line.

Change in rainfall from the long-run average

Monsoon season, percent above or below normal

South Peninsula+14%
Central+6%
Northwest−3%
East and Northeast−11%
Illustrative numbers.
View the data
regionchange
South Peninsula+14%
Central+6%
Northwest−3%
East and Northeast−11%
:::chart
type: bar
title: Change in rainfall from the long-run average
subtitle: Monsoon season, percent above or below normal
data: data/rainfall.csv        # or an inline list, as in this example
label: region                  # column with the bar names
value: change                  # column with the numbers
format: { type: number, suffix: "%", sign: true }
negativeLabel: Drier           # axis captions for diverging bars
positiveLabel: Wetter
highlight: [Northwest]         # rows to emphasise
sort: desc                     # desc (default), asc or none
width: mid                     # col, mid (default) or wide
note: Illustrative numbers.
:::

Line charts

Data can be wide (an x column plus one column per line) or long (set series, x and y). With eight or fewer lines, each gets its own color and a legend. With more, set colorBy: last to color each line by where it ends.

Share of homes with a broadband connection

Three illustrative regions

CoastPlainsHills
0%25%50%75%100%201620182020202220242026Coast 78%Plains 67%Hills 52%
View the data
YearCoastPlainsHills
201622%12%5%
201834%20%9%
202051%33%16%
202263%47%27%
202472%58%40%
202678%67%52%
:::chart
type: line
data: data/broadband.csv
x: year
yFormat: percent               # see "Number formats" below
yDomain: [0, 1]
yTicks: [0, 0.25, 0.5, 0.75, 1]
xFirst: Start                  # optional labels for the first and last x
xLast: Today
refLines:                      # dashed reference lines
  - { y: 0.5, label: Half of homes }
labels: [Coast]                # label these lines at the right edge ("all" labels every line)
labelExtremes: 2               # also label the top and bottom 2
highlight: [Hills]             # draw these lines heavier
colorBy: last                  # color by final value on a scale
scale: diverging               # or sequential
domain: [0, 1]
:::

Tile maps

A tile map places one square per place on a grid and colors it by value. Give each row a col and row position.

A four-by-three grid

SEAA112B135C158A244B271C290D266B327
Score
050100
View the data
Namescore
North Alpha12
North Bravo35
North Charlie58
Mid Alpha44
Mid Bravo71
Mid Charlie90
Mid Delta66
South Bravo27
:::chart
type: tiles
data: data/places.csv
id: id                         # short code printed on the tile
name: name                     # full name for tooltips
col: col                       # grid position
row: row
value: score
scale: diverging               # diverging (default) or sequential
domain: [20, 80]               # values outside are clamped
tooltip:                       # extra tooltip rows
  - { key: population, label: People, format: number }
annotations:                   # grid-unit labels such as seas or neighbours
  - { text: "BAY OF\nBENGAL", x: 4.4, y: 5.5 }
:::

Tables

Tables can be sorted by clicking a column heading. The first column stays in place when the table scrolls sideways.

Four made-up cities

Swipe the table sideways for more columns →

Northport1,250,000+3.1%$18k
Riverton310,000+0.4%$13k
Eastvale640,000−1.2%$9,200
Lakeside95,000−2.7%$7,300
:::table
data: data/cities.csv
sort: growth                   # initial sort column
order: desc                    # asc or desc
key: city                      # links rows to other charts (see below)
columns:
  - { key: city, label: City, swatch: { value: growth, scale: diverging } }
  - { key: growth, label: Growth, format: +percent:1, tone: sign }
  - { key: clock, label: Years, labels: { 21: "20+" } }   # show text for specific values
:::

Timelines

A flat timeline lists events with a date column on the left:

  1. Year 1
    Diplomacy
    Talks over river water break down
    Relations sink to their lowest point.
  2. Year 3
    Debt default
    The smallest country defaults on its debt
    Debt had reached 107% of GDP.
  3. Year 6
    Recovery
    The economy climbs back
    Growth returns to 5% a year.

A grouped timeline puts events under headings, one per year for example. Each event can have a body and a "What happens next" note. Add filter: true to let readers narrow it to one country or to major events only.

2major events1trade deal
Year 1Monsoon 14% below normal
Food emergency
Drought hits Eastvale
It grows only half of the food it eats.
What happens next: Rationing starts and prices rise.
Trade
Northport and Riverton form a customs union
Tariffs and inspections end.
Year 2Monsoon near normal

A quiet year.

Year 3
Debt default
Lakeside defaults on its debt
Debt reached 104% of GDP.
What happens next: Creditors accept a write-down.
:::timeline
data: data/future.json         # a list of groups, or of flat items
limitGroups: 8                 # the rest hide behind "Show all"
groupNoun: years               # "Show all 20 years"
filter: true                   # country dropdown + "major only" checkbox
filterAll: All countries
majorLabel: Crises only
quiet: A quiet year.           # shown for groups with no events
quietFiltered: Nothing major for {name}.
nextLabel: "What happens next:"
stats:                         # summary numbers above the log
  - { value: 71, label: major crises }
:::

Each group is { title, note, tone: bad, items: [...] }. Each item can have kind, title, body, next, tone (crisis, soft or good), keys (the places it involves) and major: true. Flat items also take when, and limit sets how many to show at first.

Cards

A card grid sets several items side by side. Each card can have labelled fields: plain text, a quotation set in serif, or a short ranked list of mini bars. The bars link to other charts by name.

Debt default

2 places hit this in most futures
What sets it off
Debt passes 100% of GDP.
It has happened before
Sri Lanka defaulted on its foreign debt in 2022.
Most exposed
Lakeside92%
Eastvale64%

Food emergency

1 place hits this in most futures
What sets it off
A failed monsoon in a place that can't grow or buy enough food.
Most exposed
Rare under these assumptions.
:::cards
data: data/crises.json         # or items: [...]
columns: 3                     # 2 on tablets, 1 on phones
tone: neg                      # dot and bar color: neg, pos, accent or none
:::

Each card is { title, stat, text, tone, fields: [...] }. A field is { label, text }, { label, text, quote: true } or { label, bars: [{ name, value }], format, max, empty }.

Stats

8 yrs
Survival clock. In half of all futures, the country gets this far before its first crisis.
100%Chance of at least one crisis in 20 years
−45%Income in year 20 compared with staying whole
:::stats
hero: { value: "8", unit: yrs, text: "**Survival clock.** ..." }
columns: 2
items:
  - { value: 100%, label: Chance of a crisis, tone: neg }   # tone: pos or neg
  - { value: "13 of 30", label: Survive 20 years, wide: true }
:::

Linked selection

Charts on the same page are linked by a key, which is the label or name column unless you set key:. Select Northport in a table, and Northport lights up in every other chart with the same key. The demo story links its tile map, bar chart, line chart and table this way.

Number formats

Use format, yFormat and column formats to control how numbers print:

Format 0.426 prints as 12400 prints as
number 0.43 12,400
int 0 12,400
percent 43% —
percent:1 42.6% —
+percent +43% —
pct (already in percent) 0% 12,400%
usd / usd-k $0 $12,400 / $12k
{ type: number, suffix: "m" } 0.43m 12,400m

Everything else

  • :::methods sets a numbered list of steps in a smaller size, like the end of a long story.
  • :::sources is for citations and data downloads.
  • :::figure places an image: src, alt, title, subtitle and note.
  • :::wide runs Markdown at the full page width.
  • :::html passes raw HTML through untouched. Together with scripts: in the front matter, it lets you build a bespoke interactive, such as the simulation sliders in the original piece.