# Writing docs

> The writing rules for docs.welldot.org, how pages are organized and ordered, how to add a page, which pages are generated, and how to run and check the site locally.

## Who reads these docs

- **Geologists and hydrogeologists**, often reading English as a second language. They need to know what each field means in the field.
- **Developers** building tools, databases and editors on the format. They need code that works against the current packages.
- **AI agents** working for either group, reading the same pages as Markdown.

Write for all three: plain sentences, one idea each, no marketing language, no jargon a field geologist would not use unless it is explained.

## The rules

1. **Link to the spec, don't restate it.** The specification in `spec/` is the only place a rule is stated. A page that depends on a rule explains it in plain words and links to the spec heading, for example `[level sign convention](/format/spec/v2/format-reference#level-sign-convention)`. If a guide needs a rule the spec lacks, the spec gets the rule first.
2. **Full examples use `well` fences.** Every complete `.well` document is a ` ```well ` fence or a `::well-preview{example="<id>"}` block, so CI validates it. Fragments and deliberately invalid snippets use `json` fences.
3. **Two entry points.** Geologist-facing pages (getting started, concepts) explain field meaning without code. Developer pages show code, checked against the current package APIs.
4. **Frontmatter.** Every page has a `title` and a `description`. The description is used in search results, `llms.txt` and SEO, so make it a full sentence that says what the page covers.
5. **No duplicate title.** The page header shows `title`. Omit a leading `# Heading` in the body, or make it identical to `title`.
6. **Sentence case** for titles and headings: "Getting started", not "Getting Started".
7. **Code that runs.** Run new snippets against the packages before publishing. State the output only when you have seen it.

The [content components](/contributing/components) page lists the blocks you can use: callouts (`::note`, `::tip`, `::warning`, `::caution`), `::code-group`, `::tabs`, `::steps`, `::do-dont`, `mermaid` diagrams and `::well-preview`.

::warning
`check:examples` only reads a `::well-preview{example="…"}` attribute written on one line. Keep the whole opening line together.
::

## Links and anchors

- Link site pages by path: `/format/concepts/units-and-precision`.
- Spec pages are at `/format/spec/v2/<file>`, `/format/spec/reference/fgdc-textures` and `/format/spec/v1/well-format`. Heading anchors are the ones GitHub generates, so ``## `bore_hole[].drilling_method` `` becomes `#bore_holedrilling_method--recommended-values-since-v23`. Copy them from the rendered page or GitHub; do not guess.
- Object pages: `/format/reference/objects/<object>` (for example `bore-hole`). API pages: `/<package>/api/<kind>/<Name>`. Changelogs: `/<package>/changelog`.
- The JSON Schema is linked at `https://welldot.org/schema/v2/well.schema.json`, never copied.
- Repository files are linked on GitHub: `https://github.com/welldothq/welldot/blob/main/<path>`.

`check:links` fails the build on a broken link or anchor, including links into the spec.

## Adding a page

Pages live in `apps/docs/content/en/` and their path is their route. Numeric prefixes set the sidebar order and are dropped from the route: `format/2.concepts/3.vocabularies.md` is `/format/concepts/vocabularies`.

```text
content/en/
  index.md                     the landing (layout: landing)
  format/                      the .well format section
    index.md                   section home
    1.getting-started/ 2.concepts/ 3.guides/ 4.reference/ 5.spec/ 6.changelog.md
  core/ utils/ render/         one section per package
    index.md  1.getting-started/  2.guides/   (api/ is generated)
  ai/  contributing/
```

1. Create the file in the right folder, with a numeric prefix for its position.
2. Add `title` and `description` frontmatter. `navigation.title` sets a shorter sidebar label.
3. Write the page following the rules above.
4. Run the checks below.

A directory without an `index.md` appears in the sidebar as a group named after the folder.

## Generated pages

Never edit these by hand; they are rebuilt on every `dev`, `build` and `generate` and are not committed:

- `content/en/<package>/api/**`: the API reference, generated from the TSDoc in the package sources by TypeDoc. To change it, edit the TSDoc.
- `content/en/format/reference/objects/**`: the object reference, generated from the JSON Schema. To change it, change the Zod schemas in `@welldot/core` (and the spec).

The spec pages under `/format/spec` and the package changelogs are read straight from `spec/` and `packages/*/CHANGELOG.md`.

## Run the site locally

The docs need Node 22.5 or later (they use Node's built-in SQLite).

```bash
pnpm install
pnpm turbo build --filter=docs^...   # build the packages the docs read
pnpm --filter docs dev               # http://localhost:3001
```

Before opening a pull request:

```bash
pnpm --filter docs check:examples    # every .well snippet validates
pnpm --filter docs generate          # the site builds
pnpm --filter docs check:links       # every link and anchor resolves
```

## Translations

This release is English only. Pages are organized so a Portuguese edition can be added under `content/pt/` later; an English edit never waits for a translation, and a translation that falls behind is flagged automatically.
