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.
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
View the data
| region | change |
|---|---|
| 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
View the data
| Year | Coast | Plains | Hills |
|---|---|---|---|
| 2016 | 22% | 12% | 5% |
| 2018 | 34% | 20% | 9% |
| 2020 | 51% | 33% | 16% |
| 2022 | 63% | 47% | 27% |
| 2024 | 72% | 58% | 40% |
| 2026 | 78% | 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
View the data
| Name | score |
|---|---|
| North Alpha | 12 |
| North Bravo | 35 |
| North Charlie | 58 |
| Mid Alpha | 44 |
| Mid Bravo | 71 |
| Mid Charlie | 90 |
| Mid Delta | 66 |
| South Bravo | 27 |
:::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 →
| Northport | 1,250,000 | +3.1% | $18k |
| Riverton | 310,000 | +0.4% | $13k |
| Eastvale | 640,000 | −1.2% | $9,200 |
| Lakeside | 95,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:
- Year 1DiplomacyTalks over river water break downRelations sink to their lowest point.
- Year 3Debt defaultThe smallest country defaults on its debtDebt had reached 107% of GDP.
- Year 6RecoveryThe economy climbs backGrowth 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.
A quiet year.
A quiet year.
A quiet year.
:::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
- What sets it off
- Debt passes 100% of GDP.
- It has happened before
- Sri Lanka defaulted on its foreign debt in 2022.
- Most exposed
Food emergency
- 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
:::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
:::methodssets a numbered list of steps in a smaller size, like the end of a long story.:::sourcesis for citations and data downloads.:::figureplaces an image:src,alt,title,subtitleandnote.:::wideruns Markdown at the full page width.:::htmlpasses raw HTML through untouched. Together withscripts:in the front matter, it lets you build a bespoke interactive, such as the simulation sliders in the original piece.