Obsidian Charts Skill
Assumes the user already has the Charts community plugin (phibr0/obsidian-charts) installed and enabled.
Decide the data source first
Before writing any codeblock, pick the source — it changes the syntax:
| Source | Use when | Pattern |
|---|---|---|
| Inline literal | Small, hand-typed series | chart codeblock with labels: + series: |
| Markdown table in same note | Data already lives in a table | chart codeblock with id: <blockId> |
| Markdown table in another note | Shared data table | chart codeblock with id: + file: |
| Dataview / Dataviewjs query | Data is computed/aggregated | dataviewjs codeblock calling window.renderChart(...) |
| Frontmatter values | Comparing notes by property | Dataviewjs + renderChart (Dataview required) |
If the user is unsure, look at the note. A table → use table linking. A query → use renderChart. Loose numbers in prose → inline literal.
Quick start — inline data
```chart
type: bar
labels: [Mon, Tue, Wed, Thu, Fri]
series:
- title: Hours focused
data: [4, 3, 5, 2, 6]
beginAtZero: true
width: 80%
```
Quick start — from a table in the same note
| | Q1 | Q2 | Q3 | Q4 |
| - | - | - | - | - |
| Revenue | 10 | 14 | 12 | 18 |
| Cost | 8 | 9 | 11 | 13 |
^revenue
```chart
type: bar
id: revenue
layout: rows
beginAtZero: true
```
layout: rows reads each table row as a series; layout: columns reads each column as a series. Add select: [Revenue] to restrict which rows/columns are charted. Add file: <OtherNote> to point at a ^blockId in another note.
Quick start — from a Dataview query
Requires the Dataview plugin with JS enabled.
```dataviewjs
const pages = dv.pages('"Journal"').where(p => p.mood);
window.renderChart({
type: 'line',
data: {
labels: pages.map(p => p.file.name).array(),
datasets: [{
label: 'Mood',
data: pages.map(p => p.mood).array(),
tension: 0.3,
}]
}
}, this.container);
```
Core parameters (chart codeblock)
| Key | Values | Notes |
|---|---|---|
type |
bar line pie doughnut radar polarArea |
Required |
labels |
[a, b, c] |
Required for non-table source |
series |
list of { title, data } |
Required for non-table source |
id |
block ID | Use instead of labels/series to pull from a table |
file |
note basename | Pairs with id for cross-note tables |
layout |
rows | columns |
Table-source only |
select |
[name1, name2] |
Filter rows/cols from a table |
beginAtZero |
bool | Force y-axis to start at 0 |
stacked |
bool | Stack series (bar/line) |
tension |
0–1 | Line curve smoothing |
fill |
bool | Fill area under line |
width |
80% etc. |
Chart width |
legend |
bool | Show legend |
legendPosition |
top bottom left right |
|
bestFit |
bool | Draw trend line (line/scatter) |
bestFitTitle |
string | Label for trend line |
bestFitNumber |
number | Series index for trend |
labelColors |
bool | Color labels by series |
time |
day month year etc. |
Treat labels as dates |
indexAxis |
x | y |
y makes horizontal bar chart |
xMin xMax yMin yMax |
number/date | Axis bounds |
xTitle yTitle |
string | Axis labels |
See REFERENCE.md for the full parameter list, renderChart API, color/styling, multi-series patterns, and troubleshooting.
Workflow when helping the user
- Locate the data. Read the note, identify whether the data is a table (does it have a
^blockId?), a query result, or loose values. - Pick the chart type. Comparing categories →
bar. Trend over time →line. Parts of a whole →pie/doughnut. Multi-dimensional →radar. - If using a table, confirm there is a
^blockIdline beneath it. If not, add one — without it, the chart cannot reference the table. - Draft the codeblock inline in the note (don't make a new file unless the user asks).
- Pick
layoutcarefully —rowsvscolumnsis the most common "why is my chart wrong" issue. If the chart looks transposed, flip it. - Tell the user to open the note in Reading view or Live Preview to render the chart; Source view shows the raw codeblock.
Common gotchas
- No render in Source mode — switch to Live Preview or Reading view.
- Table reference fails — the
^blockIdmust be on its own line immediately after the table, andid:in the codeblock must match exactly (no^). layoutmismatch — series and labels look swapped; fliprows↔columns.- Date axis flat / unsorted — set
time: day(ormonth/year) so the plugin treats labels as dates. renderChartundefined — the Charts plugin isn't enabled, or the codeblock isn'tdataviewjs(it must be —dataviewwon't work for JS).- Series with mismatched lengths — every
dataarray must matchlabels.length(pad withnullfor missing points).