agentleFS
Registry

Tufte-style figures for articles

skill · published by agentleFS · version 1 · approved by frdchang@gmail.com on 2026-10-16

Decide whether an article needs a figure at all; if it does, draw one quiet, self-contained Tufte-style SVG through an architect, designer, critic and reader-proxy loop.

Mount
SKILL.md

Tufte-style figures for articles

A figure is the most expensive thing in a post: the reader stops reading to look at it. So this skill starts by asking whether the article needs one. Most do not. When one does, it extracts what the reader must see, draws it with as little ink as the content allows, and has a critic and a newcomer check it before it ships.

For charts of measured series over time (stacked areas, lines, slopegraphs), use the sister skill tufte-charts, which draws them from data. This skill is for explanatory figures: flows, scopes, comparisons, before and after, and small sets of numbers.

Step 1. Does this article need a figure?

Read the whole article. Write its point in one sentence. Then apply the tests.

A figure earns its place when the article has structure the reader must hold in their head all at once:

Structure in the articleExampleForm that usually fits
A flow with three or more actors, or the same flow over timea plan moving ChatGPT → Claude → Gemini over a weekparallel timelines, one lane per way of working
A comparison across three or more options and two or more attributes, where the answer is a patternwhich AI can read which project: each its own, except one that all candot matrix, rows × columns
A before / after of a systemthe vault on one computer vs in the cloudtwo small multiples, same layout, same scale
A hierarchy or scope boundarya skill applies in its folder and every folder below; an agent's scope sits inside its parent'sindented tree with brackets, or nested bars
Where something goes, or how far it reachesthe text of one file goes to a lab, your computer or a search vendorfan-out with labelled ends, or bands of reach
Numbers that differ in size, or change over timelines per file in twelve repos, against a 200-line guidedot plot to scale with a reference line; series over time → tufte-charts

It does not earn its place when:

  • the point is a single claim ("ChatGPT and Claude can't share memory") that one sentence states;
  • it is a how-to whose steps are already a numbered list (connect guides, install steps);
  • it is an opinion, a recommendation or a ranked list (a "best skills" post: the table is the figure);
  • the comparison has many words per cell and no pattern: the reader must read the cells, not see a shape. A text table does this better;
  • the figure would only repeat a table already in the article, or decorate it (a logo, a stock image, a box per heading).

Edge cases. If an attribute in a table does form a pattern (a diagonal, one full column, a nesting), that one attribute may earn a dot matrix; the rest stays in the table. Two posts on the same subject may use the same figure grammar, but each figure must answer its own article's question.

When no figure is needed, say so and stop. Report:

No figure: <one-line reason, naming the test it fails>.
Carried by: <the table / the numbered steps / the sentence that already does it>.

If the article already has a figure that fails the tests, recommend removing it. A text table may be offered instead; never draw "something" to fill the space.

Step 2. Extract the informational content

Before any drawing, the information architect writes a brief. Use the article's own words.

Point (one sentence):      what the reader should believe after looking
The one comparison:        A vs B, on what (this is what the accent colour marks)
Entities (≤ 7 if possible): the things the reader must recognise, named as the article names them
Relations:                 who reads / writes / contains / sends / replaces what
Quantities:                every number, with unit and source; "none" if none
Leave out:                 true things the figure must not carry (they stay in the text)
Form:                      from the table in Step 1, and why
Caption (one sentence):    the takeaway, for the italic line under the image
Alt text (1–3 sentences):  what is shown and what it shows

Rules for the brief:

  • One comparison per figure. If you find two, either they are one comparison seen twice (small multiples) or the article needs to choose.
  • Real names, not placeholders: viewer@projects/launch, not "Scope A"; "Claude, ChatGPT, Gemini", not "AI 1–3".
  • Every entity in the figure appears in the article. Nothing new is introduced by the picture.
  • Quantities are drawn to scale, or not drawn as sizes at all.

Step 3. Draw it the Tufte way, in SVG

Tufte's principles, made concrete:

  1. Maximise data-ink; erase the rest. Every mark either carries information or helps the eye find it. No gradients, shadows, glows, 3D, rounded "cards", background bands, decorative icons, emoji, clip art or logos. No box around a label that would read fine as free text. A box is allowed only when the thing is a container (a folder, a vault, a file) and says so.
  2. Label directly. Names sit next to the mark they name. No legend when a label can sit at the line's end, beside the dot or over the column. Put a colour key in a sentence ("red: one agentleFS folder") rather than a legend box.
  3. Small multiples for comparison. Before / after and option A / option B get the same layout, the same order of rows, the same scale and the same type sizes, side by side or stacked, so only the difference changes.
  4. Layering and separation. Structure is thin and light: 1 px hairlines in a faint grey, dotted or dashed guides at low opacity. Content is ink. The point is the one accent colour. Three visual layers at most: faint structure, ink content, accent emphasis.
  5. One accent colour, for the point only. The accent marks the side of the one comparison the reader should notice (the shared folder, the move, the outlier). Never colour by category for decoration. A second hue needs a reason the reader would name.
  6. Show quantities to scale. A length, position or area stands for its number, from a stated zero or a labelled reference (a range frame, a 200-line guide). Print the number beside the mark. Lie factor 1: the drawn change equals the data change.
  7. Readable typography, clear reading order. One serif face (ET Book, then Palatino, Georgia), a monospace face only for code and paths. Text horizontal, never rotated. At the figure's own width: title 21–26 px italic, labels 16–20 px, notes 14–16 px, nothing under 13 px. The eye goes top-left to bottom-right: title, the comparison's first side, its second side, the takeaway.
  8. Words and pictures together. The title names the question the figure answers or its claim ("Where the text of one file goes"). A short subtitle may give the comparison. Methods, caveats and "not a measurement" go in one small grey italic footnote.

The house style these posts already use:

RoleLightDark
paper (background)#fffff8#111111
ink (content)#111111#ecebe4
ink2 (secondary content)#4a4741#cfccc2
grey (notes, labels)#6b675f#a8a49a
faint (hairlines, rings only, never text)#c9c4b8#4a4741
accent (the point)#a33a2c#e2735f

Every text colour meets WCAG AA (4.5:1) on its paper. Typical shapes: dot matrices (filled dot = yes, hollow ring = no), timelines with dotted day hairlines, indented trees with thin brackets, fan-out arrows with small solid heads, bands separated by a single faint rule with spaced small-caps labels.

Step 4. The multi-agent designer loop

Run four roles in sequence. Use separate subagents where you can; at the least, make each pass separately and write its output down. Each role sees only what is listed.

  1. Information architect (sees: the article). Applies Step 1. Either stops with "No figure", or writes the brief from Step 2, including the form.
  2. Designer (sees: the brief, this skill, one or two existing figures for style). Draws figure.svg to the technical rules below. Renders it to PNG in light and dark mode at the blog's column width and looks at it before handing it on.
  3. Tufte critic (sees: the brief and the rendered figure, light and dark). Audits, and lists each finding as blocking or minor:
    • data-ink: every mark that carries nothing (boxes, extra rules, repeated labels, decoration);
    • chartjunk: gradients, shadows, 3D, icons, heavy grids, moiré dashes;
    • labelling: any legend that could be direct labels; any unlabelled mark; rotated or tiny text;
    • accent: used for more than the one comparison, or not on it;
    • scale: any quantity not to scale, any axis or reference without a label;
    • fidelity: any entity, number or claim not in the brief, or in the brief and missing.
  4. Reader-proxy (sees: ONLY the rendered figure, plus the caption if the post shows one; never the article or the brief). A newcomer who looks for 10 seconds, then writes: the point in one sentence; the two things being compared; anything it could not read or did not understand. A fresh agent with no context plays this best.

Iterate. The designer fixes every blocking finding and every reader-proxy confusion, then the critic and the reader-proxy run again. It ships when the critic has no blocking findings and the reader-proxy's sentence matches the brief's point in substance. After three rounds without that, go back to the information architect: the form is wrong, the comparison is two comparisons, or the article does not need a figure.

Step 5. Technical rules for the SVG

  • Self-contained. One .svg file. No external images, scripts, <foreignObject>, @import or web-font URLs (an SVG shown through <img> cannot load them). Fonts are a system stack, or a subset WOFF2 embedded as a data: URI in @font-face.
  • An opaque background. The first drawn element is a rect covering the whole viewBox, filled with paper, and every <text> has an explicit fill. Reason: Safari ignores prefers-color-scheme inside an SVG loaded as an image, so a transparent figure with near-black text vanishes on a dark page. With an opaque paper rect it stays readable everywhere.
  • Dark mode is optional, and switches background and text together. One @media (prefers-color-scheme: dark) block redefines every colour variable, paper included, so no state can show dark text on dark paper. Add [data-theme="light"] / [data-theme="dark"] overrides so a page that inlines the SVG can force one.
  • A viewBox, width and height. 520–720 user units wide, height as the content needs (keep it under about 1.6× the width; a taller figure is usually two figures or one that says too much). The rect covers the viewBox exactly, including any negative origin.
  • Accessible. role="img", aria-labelledby pointing at a <title> (the figure's name) and a <desc> (the alt text from the brief).
  • Size budget. Under 20 KB with system fonts; under 64 KB with an embedded font subset. No raster images, no hidden layers, no editor metadata. Coordinates rounded to one decimal.
  • Stored beside the post as blog/<slug>/figure.svg (or <folder>/figure.svg for other articles), and linked from the markdown as

    ![<alt text: what is shown and what it shows, 1–3 sentences>](figure.svg)
    
    *<caption: the takeaway in one sentence>*

    One figure per article by default. A second figure must pass Step 1 on its own and is named for what it shows (figure-scopes.svg).

A starting skeleton:

<svg xmlns="http://www.w3.org/2000/svg" class="tf" viewBox="0 0 600 400" width="600" height="400"
     role="img" aria-labelledby="t d">
<title id="t">Where the text of one file goes</title>
<desc id="d">One to three sentences: what is shown, and what it shows.</desc>
<style>
.tf{--paper:#fffff8;--ink:#111;--ink2:#4a4741;--grey:#6b675f;--faint:#c9c4b8;--acc:#a33a2c}
@media (prefers-color-scheme: dark){
  .tf{--paper:#111;--ink:#ecebe4;--ink2:#cfccc2;--grey:#a8a49a;--faint:#4a4741;--acc:#e2735f}}
.tf[data-theme="light"]{--paper:#fffff8;--ink:#111;--ink2:#4a4741;--grey:#6b675f;--faint:#c9c4b8;--acc:#a33a2c}
.tf[data-theme="dark"]{--paper:#111;--ink:#ecebe4;--ink2:#cfccc2;--grey:#a8a49a;--faint:#4a4741;--acc:#e2735f}
.bg{fill:var(--paper)}
text{font-family:'ET Book',et-book,Palatino,'Palatino Linotype','Book Antiqua',Georgia,serif;fill:var(--ink)}
.title{font-size:23px;font-style:italic}
.lab{font-size:18px}
.note{font-size:15px;fill:var(--grey)}
.acc{fill:var(--acc)}
.rule{stroke:var(--faint);stroke-width:1;fill:none}
.line{stroke:var(--ink2);stroke-width:1.3;fill:none}
.line-acc{stroke:var(--acc);stroke-width:2;fill:none}
</style>
<rect class="bg" x="0" y="0" width="600" height="400" fill="#fffff8"/>
<text class="title" x="0" y="28" fill="#111">…</text>
<!-- content: faint structure, ink content, one accent -->
</svg>

The fill attributes on the rect and the title are the fallback for a renderer that ignores the stylesheet; the stylesheet overrides them.

Check it before it ships:

xmllint --noout figure.svg                                  # well-formed
wc -c figure.svg                                            # within the size budget
grep -nE 'Gradient|filter|<image|foreignObject|@import|https?://[^"]*\.(woff|ttf|png|jpg)' figure.svg  # expect nothing
rsvg-convert -w 1360 figure.svg -o figure.light.png         # look at it at 2x

Look at it in dark mode too (a browser with an emulated dark colour scheme), and once as Safari would show it: the light version on a dark page. Both must read.

Checklist

  • Step 1 answered in writing: figure needed, or "No figure" with the reason and what carries the structure.
  • A brief with one point, one comparison, the entities, relations, quantities and what to leave out.
  • Every entity and number in the figure is in the article; nothing is invented.
  • No gradients, shadows, 3D, icons, decorative boxes or legend boxes.
  • Every mark labelled directly; text horizontal and at least 13 px.
  • Hairlines faint; one accent colour, on the comparison and nowhere else.
  • Quantities to scale, with the numbers printed.
  • Before / after or option comparisons share layout, order and scale.
  • Opaque paper rect over the whole viewBox; every text has a fill; dark mode, if present, switches paper and ink together.
  • viewBox, <title>, <desc>, role="img"; self-contained; within the size budget.
  • Critic: no blocking findings. Reader-proxy: got the point in 10 seconds without the article.
  • Saved as figure.svg beside the post, linked ![alt](figure.svg) with meaningful alt text and a one-line italic caption.

Credits

  • Edward Tufte, The Visual Display of Quantitative Information (2nd ed., 2001) and Envisioning Information (1990): data-ink, chartjunk, small multiples, layering and separation, direct labelling, the lie factor. Beautiful Evidence (2006): words and pictures together, sparklines. Principles only; no text or figure is copied.
  • The critique loop follows the shape of multi-agent figure generation with separate feedback agents, e.g. PlotGen (Goswami et al., 2025, arXiv:2502.00988), whose ablation found the visual-feedback agent the most valuable.
  • The opaque-background rule comes from WebKit's handling of prefers-color-scheme in SVG images (WebKit bug 199134).
  • The palette and type are those of the agentleFS blog's figures and the tufte-charts skill.