---
title: "Test documentation changes | Writers' Toolkit documentation"
description: "Test documentation changes by running a local documentation web server"
---

# Test documentation changes

Every project keeps technical documentation that’s published to the website in the `docs/sources` directory. That documentation is published to the `content/docs` directory in the website repository.

Additionally, every project uses [GNU Make](https://www.gnu.org/software/make/) to perform tasks related to technical documentation. To learn more about GNU Make, refer to [GNU Make Manual](https://www.gnu.org/software/make/manual/).

To see a list of targets and their descriptions, run `make help` from the `docs/` directory. If you are in the website repository, run `make help` from the root of the repository instead.

The output is similar to the following:

console ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```console
Usage:
  make <target>

Targets:
  help             Display this help.
  docs-rm          Remove the docs container.
  docs-pull        Pull documentation base image.
  make-docs        Fetch the latest make-docs script.
  docs             Serve documentation locally, which includes pulling the latest `DOCS_IMAGE` (default: `grafana/docs-base:latest`) container image. To not pull the image, set `PULL=false`.
  docs-debug       Run Hugo web server with debugging enabled. TODO: support all SERVER_FLAGS defined in website Makefile.
  vale             Run vale on the entire docs folder which includes pulling the latest `VALE_IMAGE` (default: `grafana/vale:latest`) container image. To not pull the image, set `PULL=false`.
  update           Fetch the latest version of this Makefile and the `make-docs` script from Writers' Toolkit.
```

To run the local documentation web server, run `make docs` from the `docs/` directory. If you are in the website repository, run `make docs` from the root of the repository instead.

> Note
> 
> Running `make docs` from the wrong directory, produces the output `make: Nothing to be done for 'docs'.` or `make: *** No rule to make target 'docs'. Stop.`, and the local documentation web server is not started. To run the local documentation web server, ensure that you are in the right directory.

The output message of a successful build includes a URL that you can follow to view the changes to the documentation in the browser. Refer to an [example of a successful build](#example-successful-build).

## Run with specific projects

Each repository has a list of projects to build by default when running `make docs`, defined by the `PROJECTS` variable in `docs/variables.mk`. To override the defaults, provide the `PROJECTS` option to `make docs`. The argument is a space-separated list of names of the projects.

The project name for a repository is the sub-directory of the `/docs/` directory in the website where the repository publishes documentation. For example:

- For Grafana, the `PROJECT` is `grafana` derived the URL `https://grafana.com/docs/grafana/`.
- For Grafana Cloud, the `PROJECT` is `grafana-cloud` derived from the URL `https://grafana.com/docs/grafana-cloud/`.

> Note
> 
> You must have the repository cloned locally for any projects specified in the space separated list to `PROJECTS` for the command to succeed.

To build only the Grafana documentation:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
make docs PROJECTS=grafana
```

To build Grafana and Grafana Cloud documentation:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
make docs 'PROJECTS=grafana grafana-cloud'
```

If your local repository name doesn’t match the upstream repository name. You can use the `PROJECTS` option to override the directory.

For example, if you have the Tempo repository `tempo` cloned into a directory called `tempo-doc-work`.

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
make docs PROJECTS=tempo::tempo-doc-work
```

The format is `<PROJECT>[:VERSION[:REPOSITORY[:DIRECTORY]]].` The example mounts the `PROJECT` `tempo`, at the default `VERSION` (since the `VERSION` argument is empty), using the `REPOSITORY` `tempo-doc-work`, and the default documentation `DIRECTORY` `docs/sources`. This example builds the Tempo documentation from the local working directory, `tempo-doc-work`, instead of the standard `tempo` directory.

## Understand Hugo output from `make docs`

When you run `make docs`, Hugo renders the Markdown files and outputs warnings and error messages.

These messages are in the following format:

text ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```text
<LEVEL> [LANGUAGE] <MESSAGE>
```

where:

- *`<LEVEL>`* is one of `WARN` or `ERROR`
- *`<LANGUAGE>`* may be present
- *`<MESSAGE>`* is the issue

### Example: Successful build

If the `make docs` command runs correctly, the console prints a message similar to the following:

![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```none
View documentation locally:
  http://localhost:3002/docs/grafana/latest/

Press Ctrl+C to stop the server
```

> Note
> 
> To test Grafana tutorial changes, the address is `http://localhost:3002/docs/grafana/latest/tutorials/`.

### Example: Page not found

Hugo emits `REF_NOT_FOUND` warnings indicating the filename and location of such references when building the docs, for example with `make docs` in `grafana/grafana` or `make server-quick` in `grafana/website`:

![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```none
WARN 2022/08/04 21:35:37 [en] REF_NOT_FOUND: Ref "../../enterprise": "/hugo/content/docs/grafana/next/administration/roles-and-permissions/access-control/assign-rbac-roles.md:14:47": page not found
```

In this example,

- `Ref "../../enterprise"` is the destination of the reference that Hugo can’t resolve
- `\/hugo/content/docs/grafana/next/administration/roles-and-permissions/access-control/assign-rbac-roles.md` is the document containing the reference, where the path after `/next/` is relative to the documentation root of the component repository
- `:14` represents the line number containing the unresolved reference
- `:47` represents the character in that line where the unresolved reference begins

If you see this error, then the reference’s destination is invalid. This may be due to a typo in the reference or having the incorrect path to the destination directory. Fix the error by correcting the reference target.

For more information about linking, refer to [Links](/docs/writers-toolkit/write/links/).

### Example: Rebuild failed due to missing shortcode

In this example, the rebuild fails because the file `contribute-documentation/_index.md` is missing a closing shortcode for `admonition` on line 152.

![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```none
ERROR Rebuild failed: assemble: "/hugo/content/docs/writers-toolkit/contribute-documentation/_index.md:152:1": failed to extract shortcode: shortcode "admonition" must be closed or self-closed
```

### Extended usage

Refer to the following sections for examples of more complicated usage of `make docs`.

#### Mount documentation to a different version

![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```none
make docs PROJECTS=grafana:next
```

#### Mount `v9.3.x` and the default version of Grafana documentation together

Run the following command from the root of the repository to add a worktree that contains the `v9.3.x` branch:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
git worktree add v9.3.x origin/v9.3.x
```

Change to the `docs/` directory:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
cd docs
```

Run `make docs` with both versions:

![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```none
make docs 'PROJECTS=grafana grafana:v9.3.x:grafana'
```

To remove the worktree, run the following command from the root of the repository:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
git worktree remove v9.3.x
```

### Arguments

Each argument to the `make-docs` script is a project to be mounted into the local build. Each argument has four fields separated by colons (`:`), and optional fields can be omitted.

`<PROJECT>[:VERSION[:REPOSITORY[:DIRECTORY]]]`

- *`<PROJECT>`* : is the sub-directory of the `/docs/` directory in the website where the repository publishes documentation.
  
  For example:
  
  - For Grafana, *`<PROJECT>`* is `grafana` (`https://grafana.com/docs/grafana/`)
  - For Grafana Cloud, *`<PROJECT>`* is `grafana-cloud` (`https://grafana.com/docs/grafana-cloud/`).
  
  Pseudo projects mount multiple source directories.
  
  - `logs`: mounts Loki and Grafana Enterprise Logs (GEL) directories.
  - `metrics`: mounts Mimir, the `mimir-distributed` Helm chart, and Grafana Enterprise Metrics (GEM) directories.
  - `traces`: mounts Tempo and Grafana Enterprise Traces (GET) directories.
  
  > Note
  > 
  > Pseudo projects don’t support the *`<REPOSITORY>`* or *`<DIR>`* fields.
- *`<VERSION>`* : is the name of the version directory to mount the documentation in.
  
  The *`<VERSION>`* field is optional and defaults to `latest` for versioned projects and is empty for other projects.
- *`<REPOSITORY>`* : is the name of the directory that the project is cloned to.
  
  The *`<REPOSITORY>`* field is optional and defaults to the script’s internal mapping of project names to repository names. For most projects, this is the same as the project name.
- *`<DIRECTORY>`* : is the directory path within the repository containing the technical documentation documentation.
  
  The *`<DIRECTORY>`* field is optional and defaults to the script’s internal mapping of project names to documentation source directories. For most projects, it’s the `docs/sources` directory.

#### `REPOS_PATH`

The `REPOS_PATH` environment variable is a colon-separated list of paths in which to look for project repositories. The script only checks for projects in the directories specified in `REPOS_PATH`.

By default, the script determines the `REPOS_PATH` to be the parent directory of the current project. If you keep all repositories in the same directory, you don’t need to set `REPOS_PATH`.

With a directory structure similar to the following output from the `tree -L 1 -d ~/ext/grafana` command:

console ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```console
/home/username/ext/grafana
├── agent
├── grafana
├── loki
├── mimir
├── phlare
├── technical-documentation
├── tempo
├── website
└── writers-toolkit

9 directories
```

When you run `make docs` from the Grafana repository, the script sets `REPOS_PATH` to be `/home/username/ext/grafana`.

#### `DEBUG`

The `DEBUG` environment variable disables output filtering and enables extra debug logging to help with troubleshooting.

If you experience confusing behavior with the `make docs` procedure, report the problem via a GitHub issue or, for Grafana Labs employees, in the #docs Slack channel and provide the full command and output using `make docs DEBUG=true`.

## Stop running a local build

To stop the `make docs` command, press Commmand/Ctrl + C.

Sometimes an old build process can be running in another terminal. If this is the case, when you run `make docs`, you see output similar to the following:

console ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```console
docker: Error response from daemon: driver failed programming external connectivity on endpoint eloquent_nightingale (eb2c4546727b41bbc44354ac616a14404c57f30c312f6869b147c578ac5de6bf): Bind for 0.0.0.0:3002 failed: port is already allocated.
make: *** [docs] Error 125
```

To remove an old build process, do one of the following:

- Open Docker Desktop, go to **Containers**, and stop all running containers or just the one for your local build.
- To remove all running containers, run `docker rm -f $(docker ps -q)`.
