Gauge chart
How far a number is from its goal: a half ring that fills up, and the number big in the middle.
Who this is for
People who build n8n workflows, and agents that send progress to Slack or email: revenue against the quarter's goal, tickets closed against the plan, storage used against the quota.
What the gauge preset draws
- A half ring, filled in proportion to
value / max, and the rest in grey. - The value as a big number in the middle, with
prefixandsuffixaround it. - Under it, the share and the goal:
74.5% of $50,000. When the value already is a percentage of 100, onlyof 100%.
Send a doughnut config with one dataset. The first number in data is the value. A value above max fills the ring and the number still shows the real value; a negative value leaves it empty.
The config
{
"type": "doughnut",
"data": { "datasets": [{ "data": [37250] }] },
"options": {
"plugins": {
"title": { "display": true, "text": "Q4 revenue goal" },
"chartpng": { "preset": "gauge", "max": 50000, "prefix": "$" }
}
}
}The preset and its options live under options.plugins.chartpng:
| Option | What it does |
|---|---|
preset | "gauge". |
max | A number above 0: the value at which the ring is full, such as a goal or a quota. Default 100. |
prefix | A string put before the value and the goal, such as "$". |
suffix | A string put after the value and the goal, such as "%". |
values | false hides the number and leaves the ring. |
Anything your config sets wins over the preset, the same as with the theme, so options.cutout sets the thickness of the ring. The colours are the first colour of the theme and a muted grey, light or dark by the background.
A config that does not fit is a 400 whose message says why, such as preset gauge needs type doughnut or preset gauge needs max to be a number above 0, the value that fills the gauge.
The GET URL
The whole config goes in c, URL-encoded. Paste the URL in an <img>, an email or a Slack image block. Past a few thousand characters, use a POST.
https://chartpng.dev/chart?c=%7B%22type%22%3A%22doughnut%22%2C%22data%22%3A%7B%22datasets%22%3A%5B%7B%22data%22%3A%5B37250%5D%7D%5D%7D%2C%22options%22%3A%7B%22plugins%22%3A%7B%22title%22%3A%7B%22display%22%3Atrue%2C%22text%22%3A%22Q4%20revenue%20goal%22%7D%2C%22chartpng%22%3A%7B%22preset%22%3A%22gauge%22%2C%22max%22%3A50000%2C%22prefix%22%3A%22%24%22%7D%7D%7D%7D&w=800&h=450&dpr=2The same chart with a POST
A POST takes the same fields in a JSON body. Use it from a server, or whenever the URL gets too long. The response is the PNG.
curl https://chartpng.dev/chart \
-H "Content-Type: application/json" \
-d '{"c": {"type":"doughnut","data":{"datasets":[{"data":[37250]}]},"options":{"plugins":{"title":{"display":true,"text":"Q4 revenue goal"},"chartpng":{"preset":"gauge","max":50000,"prefix":"$"}}}}, "w": 800, "h": 450, "dpr": 2}' \
-o gauge-chart.pngIn n8n
Build the config in a Code node and call https://chartpng.dev/chart with the HTTP Request node, as then8n guide shows. The templateweekly KPI report to Slack builds a KPI and a comparison and posts both images in one Slack message.
If a model wrote the config
Models often send near-JSON: a code fence around it, single quotes, a trailing comma. ChartPNG repairs the usual cases and lists what it changed in the X-ChartPNG-Fixes response header. Functions written as text are removed, never run. See lenient parsing.