Editing

This page explains how to change the site: correcting a wrong value, adding a component, writing guidance a page is missing, or reporting a page that is wrong.

Measured facts and authored prose

Every fact on a page is one of two kinds, and the kind decides where a change is made.

what it iswhere it changes
measuredtoken values, resolution chains, which components exist, what uses them, what Figma publishes, counts, and gapsin the product, or in the pipeline that reads it. Not on the page
authoredwhen to use a thing, when not to, what goes wrong, and what a picture showsin one file, which the page names in its footer

Measured facts cannot be edited on the page. They are read from a pinned commit of appsignal/appsignal-server on every build, so a value that is wrong here is either wrong in the product or was read incorrectly by the pipeline. The first is fixed in the product; the second is a bug to report.

The predecessor guide published these facts by hand, and by the time it was retired it listed twenty-five class names that no longer existed. Generating them is how this site avoids the same drift.

/colophon.md says where each kind of fact comes from.

Common changes

A token's value is wrong

Change it in the product's stylesheets. The new value appears here at the next build, everywhere it is used. There is no copy on the site to update.

A component is missing

A component gets a page as soon as it exists in the product and meets any one of these conditions: it is importable from the shared library, it carries a class root, or it has a Storybook module. You do not add components to this site. The generated page will have no guidance, will say so, and will name the file where guidance goes.

A page has no guidance

This is the most common gap, and filling it is the contribution the pipeline cannot make. Every page prints the path of its authored file in the footer, whether or not the file exists yet. Write that file and the prose appears at the next build.

One rule governs authored prose: it may not restate a derivable fact. Do not include token values, prop tables, or lists of class names. Those are generated and cannot go stale. Write what generation cannot produce: when to use the thing, when not to, and what goes wrong. Advice such as "sentence case, primary action rightmost" stays true in a way a list of class names does not.

A page is wrong

There are two kinds of report, and it helps to say which one you have.

An empty cell is neither. Generated pages print all of their axes, populated or not, and an empty one means the pipeline looked and found nothing. /gaps.md describes each kind of absence and who can close it.

Illustrations

Use illustrations where they make something clearer, but carry the key information in text. Coding agents read this site and cannot see images. Both renderings come from the same source, so a screenshot placed for a human reader is also on the page an agent reads, and whatever it conveys visually is lost there.

Split the job in two:

where it goes
what the picture isthe alt text
what the picture showsordinary prose, or a table cell beside it

Alt text reaches every reader, including screen readers and agents, because it is written in the file rather than added at render time. Write it as a description, not a label: "rounded rectangle, dashed purple border" is useful; "legend" is not. Keep it to one sentence. A paragraph in an alt attribute is tiring to hear read out.

The legend on /patterns/map.md is a good model. Its first column holds ten small screenshots, and each row also states in words what the treatment is and what the state means. The test is simple: cover the pictures and check that the table still answers the question.

The same test applies to every visual and structural device on a page. Each one is redundant encoding, and the passage should be complete and correct with all of it stripped. If removing the device changes the meaning, the device is doing work that belongs in the text.

Two things to avoid:

Images do not need to be small. An oversized image is fitted to the column rather than allowed to widen the page.

Where image files go

Images live in site-art/, in one of two directories.

what it holdshow it is shown
site-art/illustrations/drawings made for this sitebare, on the page's own background
site-art/screens/captures of the producton a white ground, inside a rounded border

The directory decides the treatment, and the file format does not. A capture is opaque light-mode product UI whatever it is saved as, so the frame gives it an edge of ours rather than a torn one where the capture stops. A drawing is made on a transparent ground against this site's palette, and a white ground behind it would wash it out.

Put a capture in a subdirectory named after the page that shows it, so the pictures on /patterns/map.md are in site-art/screens/patterns/map/.

The build enforces two rules here. Only .svg and .png files are copied to the site. Every file in site-art/ has to be referenced by a page, because a picture nothing shows should be deleted rather than half-kept.

Adding an image to a page

Write a markdown image reference: an exclamation mark, the alt text in square brackets, then the route in parentheses. The route is /assets/ followed by the file's path below site-art/.

The Map legend's selected-service swatch is stored at site-art/screens/patterns/map/legend-service-selected@2x.png, so the page that shows it contains this line:

![Rounded rectangle, blue border with a pale blue halo around it.](/assets/screens/patterns/map/legend-service-selected@2x.png)

which puts this on the page:

Rounded rectangle, blue border with a pale blue halo around it.

Start the route with /. Without it the route is read relative to the page, which resolves differently depending on where the page sits, and the build rejects it. Alt text is not optional either: an image without it fails the build.

Cards

A card is a box around one heading and a short passage. Reach for one to lift a single point out of the flow of a page: a recommendation, a warning, an example worth copying. Use an ordinary heading for anything the reader has to read in order, and for anything longer than a few sentences.

A card is written as a fence. The kind is required, and it says what the reader should do with the passage.

kindthe reader should
informationknow this
implementationdo this
prefercopy this
avoidnot copy this
cautionwatch out for this

This is the whole syntax:

:::card{kind=caution}
### A card is not a section

A card holds one point. A passage that has an order to it, or that runs past a
few sentences, is a section and wants an ordinary heading. A page of cards reads
as a menu rather than a document.

:::

which puts this on the page:

A card is not a section

A card holds one point. A passage that has an order to it, or that runs past a few sentences, is a section and wants an ordinary heading. A page of cards reads as a menu rather than a document.

The build enforces four rules.

Two things the build does not check. Put the polarity in an avoid card's own heading, so that "Don't use two primary buttons" reads correctly when it is quoted without the card around it. A prefer card beside an avoid is usually better than the avoid alone, with the prefer first.

The kinds are not drawn differently yet. All five render as the same box, so a card's meaning has to be in its heading and its prose, which is the same test the illustrations above have to pass.