# Contributing to the docs

The documentation site is built from the Markdown files in this directory, in
place. There is nothing to register: write or edit a `.md` file under `docs/`,
and it is a page of the site, in the right section of the sidebar, found by the
search. The same files read fine on GitHub.

## Preview

```sh
make docs-dev      # live preview at http://localhost:4321/ichor/next/ (search needs the built site)
make docs-site     # the real build of the development docs into site/dist, with the search index
make docs-preview  # serve site/dist
make docs-site-all # every version, as published, into site/dist-all
```

This guide's commands are the one place that assumes the dev shell: run them
inside `nix develop`, or with the tools from
[The tools](https://ichor.maesh.dev/next/development/build-from-source/#the-tools) on your `PATH`.
When you write commands in a page, write them as if the tools are on `PATH`;
do not put `nix develop` or `nix develop -c` in a command block. `make docs-site` fails on a broken
internal link (a missing file, a missing page or a missing `#heading`), so a
Markdown-only change cannot publish one.

## Versions

You only ever edit the Markdown on `main`. That is published as the
development docs (`/next/`, "Unreleased (main)"). Each release tag `vX.Y.Z`
publishes the `docs/` it was tagged with as `/vX.Y.Z/`, and `/latest/` and the
site root lead to the newest release, so a release's docs are frozen by its tag
and nothing is copied. The version menu in the header lists them from
`versions.json`, which the workflow writes from the tags.

## Adding a page

Create `docs/<section>/<name>.md`, starting with a `# Title` heading. That is
all that is needed:

- **The URL** is the path without `.md`: `docs/guides/rotate-keys.md` is
  `/guides/rotate-keys/`. `README.md` or `index.md` in a directory is that
  directory's own page, and `docs/index.md`
  is the home page.
- **The section** is the directory. `guides/` is Guides, `design/` is Concepts,
  `reference/` is Reference and `adr/` is Decisions (newest first, collapsed
  until you are in it). Any other directory becomes a section of its own, listed
  after those; a directory inside a section becomes a collapsible group.
- **The title** is the front matter `title`, else the first `# ` heading. The
  site prints it as the page heading, so the Markdown's own `#` line is not
  shown twice.
- **The headings** `##` and `###` make the "On this page" list.

## Front matter (optional)

```yaml
---
title: A title that differs from the first heading
sidebar_label: A shorter name for the sidebar
sidebar_order: 1
---
```

Without `sidebar_order`, pages in a section are listed alphabetically by
title. Give a page a number to put it first (lower numbers come first; pages
without one come after). GitHub shows front matter as a small table, so use it
sparingly.

## Links and images

Link to other pages the way you would on GitHub, with relative paths:
`[Adopt and reclaim](adopt-and-reclaim.md)`, `[the design](../design/architecture.md#trust)`.
They become site links. A relative link that leaves `docs/`
(`../../internal/foo.go`, `../../test/harness/`) becomes a link to that file or
directory on GitHub. A link to something that does not exist fails the build.

Images live in `docs/images/` and are referenced the same way,
`![What it shows](../images/name.svg)`; the site serves the SVG and PNG files of
`docs/` at their own path. A missing image fails the build too. Diagrams have
their own section below.

## Callouts

Use GitHub's alert syntax; GitHub renders it too, and the site shows it as an
alert.

```markdown
> [!NOTE]
> Something worth knowing.

> [!WARNING]
> Something that can hurt.
```

The kinds are `NOTE`, `TIP`, `IMPORTANT`, `WARNING` and `CAUTION`.

> [!TIP]
> This box is the `TIP` kind.

## Code

Use fenced blocks with a language (` ```sh `, ` ```yaml `, ` ```go `). The site
highlights them (light and dark) and adds a copy button; there is nothing to add
by hand.

Every block must name its language, and `make docs-site` fails with the file
and line of one that does not. Use `sh` for shell commands, `console` for a
session that shows `$ ` prompts with their output, `yaml`, `json` and `go` for
source, and `text` for plain output, diagrams and file trees. The generated
pages under `reference/` are labeled by `make docs-reference`.

## What every page gets

Nothing here is written by hand. Each page has a "Copy page" menu (copy the
Markdown, view it, copy the link, share on devices that can), every `##` and
`###` heading has a link icon that copies the address of that section, and the
Markdown of every page is served as `<page>.md` next to it, with `/llms.txt`
(an index) and `/llms-full.txt` (all pages) for tools that read the docs. The
copied Markdown has its relative links rewritten to full URLs, so it still
works outside the site.

## Diagrams

Diagrams are [draw.io](https://www.drawio.com/) files in `docs/images/`, always
a pair:

- `NAME.light.drawio.svg` is the one you edit. It is an ordinary SVG, so GitHub
  and the site show it as an image, and it carries the whole draw.io model, so
  draw.io (the web app, the desktop app or the VS Code Draw.io extension) opens
  it as a diagram.
- `NAME.dark.drawio.svg` is the same diagram in the dark theme. It is exported
  from the light file and never edited by hand.

A page names the light file once, with an alt text that says what the diagram
shows and a one-line caption under it:

```markdown
![What the diagram shows, in a sentence or two.](../images/NAME.light.drawio.svg)

*A one-line caption.*
```

GitHub shows the light image. The site shows the dark one when the reader's
theme is dark, and each image links to its SVG, which opens at full size (the
page column is narrower than the diagram).

To change a diagram, open `docs/images/NAME.light.drawio.svg` in draw.io, edit
it and save it under the same name, then export the pair again:

```sh
make docs-diagrams                                              # every diagram
make docs-diagrams SOURCE=docs/images/NAME.light.drawio.svg     # one
```

`make docs-diagrams` runs the draw.io command line from the dev shell (under
`xvfb-run`, as draw.io is an Electron app), once for each theme. A new diagram
is drawn the same way and saved as `docs/images/NAME.drawio`;
`make docs-diagrams SOURCE=docs/images/NAME.drawio` writes the pair.

One model gives both files because every colour in it is a `light-dark()` pair,
which draw.io writes into the shape's style (Edit Style, Ctrl-E in draw.io), for
example `fillColor=light-dark(#EEF2FF,#232553);strokeColor=light-dark(#6366F1,#818CF8)`.
Copy a shape from an existing diagram to keep the look, which is one palette
throughout: neutral grey for boxes and groups, indigo for Ichor's own parts and
for what a person does, amber for what waits or is not authenticated, green for
done and red for no way back. Boxes are rounded, connectors are orthogonal with
labels on the line, text is 12 px or more, and a diagram is about 900 px wide.
The export drops the PNG copies of the labels that draw.io adds for viewers
without `foreignObject` (700 KB a diagram), as browsers and GitHub draw the live
text.
