---
title: "Building & Previewing"
guide-section: "Build & Deploy"
bread-crumbs: false
tags: [Build]
---

# Building & Previewing

The `great-docs build` command is the main way you interact with Great Docs on a day-to-day basis.
It reads your `great-docs.yml` configuration, discovers your package's API, generates Quarto source
files, and renders everything into a static HTML site. This page explains what happens during a
build, how to preview your site locally, and how to troubleshoot common issues.

## The Build Pipeline

When you run `great-docs build`, the following steps execute in order:

1. The `great-docs/` output directory is created (or refreshed) with all required assets:
stylesheets, JavaScript files for dark mode toggling, sidebar filtering, the GitHub stars widget,
and other interactive features.

2. Your `great-docs.yml` is read. A `_quarto.yml` file is generated (or updated) in the output
directory with the Quarto project configuration, including navbar links, sidebar structure, and
theme settings.

3. A landing page (`index.qmd`) is generated from your project's `README.md`. If you have a logo
configured, a hero section with the logo, package name, tagline, and badges is added automatically.

4. If a user guide directory exists (by default `user_guide/`), all `.qmd` files are copied into
the output directory with numeric prefixes stripped from filenames. The sidebar is organized by
`guide-section` frontmatter metadata.

5. If Click CLI documentation is enabled, Great Docs discovers your CLI commands and generates a
reference page for each one.

6. Custom sections defined in `great-docs.yml` (examples, tutorials, blog posts, etc.) are processed
and copied to the output directory.

::: {.version-only versions=">=0.6"}
7. If `custom_pages` is configured, or if the fallback `custom/` directory exists, custom HTML pages
are discovered. Passthrough pages are converted into generated `.qmd` files and raw pages are copied
through unchanged.
:::

8. If the changelog is enabled and a GitHub repository URL exists in `pyproject.toml`, GitHub
Releases are fetched and a `changelog.qmd` file is generated.

9. The Agent Skills file (`skill.md`) is generated or copied. If you have a curated `SKILL.md` in
`skills/<package-name>/`, it is used directly. Otherwise, a skill file is auto-generated from your
package metadata. See [Agent Skills](38-agent-skills.qmd) for details.

10. `llms.txt` and `llms-full.txt` files are generated. These provide AI-friendly summaries of your
package documentation. See [llms.txt](39-llms-txt.qmd) for details.

11. Source link metadata (`_source_links.json`) is generated, mapping each documented symbol to its
file and line numbers on GitHub.

12. Quarto renders all the source files into HTML. A post-render script runs to apply final
transformations: injecting source links, processing cross-references (GDLS), cleaning up Sphinx/RST
artifacts, and generating companion Markdown (`.md`) files for each page.

After all steps complete, the finished site is in `great-docs/_site/`.

## Preview Mode

To view your site locally with live reload:

```{.bash filename="Terminal"}
great-docs preview
```

This starts a local development server and opens your default browser. When you edit source files
(user guide pages, docstrings, configuration), the site rebuilds automatically and the browser
refreshes to show your changes.

Preview mode is ideal during the writing process because it lets you see how content will look in
the final rendered site without committing or deploying anything.

## Build Options

The `great-docs build` command accepts several options that control its behavior.

### Watch Mode

Watch mode keeps the build process running and automatically rebuilds when files change. This is
similar to preview mode but without starting a local server:

```{.bash filename="Terminal"}
great-docs build --watch
```

This is useful when you want to rebuild continuously but view the output in a different way (for
example, opening the HTML files directly or using a separate static file server).

### Clean Build

If you suspect stale files in the output directory are causing issues, you can force a completely
fresh build. Delete the `great-docs/` directory and rebuild:

```{.bash filename="Terminal"}
rm -rf great-docs/ && great-docs build
```

Since the `great-docs/` directory is ephemeral and fully generated from `great-docs.yml` plus your
source files, deleting it is always safe.

## Build Output Structure

After a successful build, the output directory has this layout:

```{.default filename="great-docs/"}
great-docs/
├── _quarto.yml          # Generated Quarto config
├── index.qmd            # Landing page
├── great-docs.scss      # Theme stylesheet
├── *.js                 # Interactive features (dark mode, sidebar, etc.)
├── llms.txt             # LLM-friendly summary
├── llms-full.txt        # Full API docs for LLMs
├── skill.md             # Agent Skills file
├── _source_links.json   # GitHub source link metadata
├── reference/           # API reference pages
│   ├── index.qmd
│   ├── MyClass.qmd
│   └── ...
├── user-guide/          # User guide pages (from user_guide/)
├── recipes/             # Recipe pages (from recipes/)
├── scripts/
│   └── post-render.py   # HTML post-processing script
└── _site/               # Final rendered HTML
    ├── index.html
    └── ...
```

The `_site/` subdirectory contains the final HTML output. This is the directory you deploy to your
hosting service (GitHub Pages, Netlify, Vercel, etc.).

Everything outside of `_site/` is intermediate Quarto source. You generally do not need to inspect
these files, but they can be useful for debugging rendering issues.

## Building from a Remote Repository [version-badge new 0.11] {#from-repo}

The `--from-repo` flag lets you build documentation for any Git-hosted package without cloning it
yourself. Great Docs handles the entire workflow: cloning the repository, creating an isolated
virtual environment, installing the package and its dependencies, running the full build pipeline,
and copying the finished site to a local directory.

```{.bash filename="Terminal"}
great-docs build --from-repo https://github.com/owner/package.git
```

The built site is copied to `./great-docs/_site/` by default. Use `--output-dir` to put it somewhere
else:

```{.bash filename="Terminal"}
great-docs build --from-repo https://github.com/owner/package.git --output-dir /tmp/my-site
```

### Branch or Tag

By default the repository's default branch is cloned. Use `--branch` to check out a specific branch
or tag:

```{.bash filename="Terminal"}
great-docs build --from-repo https://github.com/owner/package.git --branch v2.0.0
```

### Clone Depth

Great Docs inspects the target project's `great-docs.yml` to decide how much Git history to fetch.
If the project uses multi-version docs or page dates, a full clone is performed automatically.
Otherwise a lightweight tag-only clone is used.

Use `--shallow` to force a minimal `--depth 1` clone. This is the fastest option but disables
versioned documentation and page dates:

```{.bash filename="Terminal"}
great-docs build --from-repo https://github.com/owner/package.git --shallow
```

### Previewing After Build

Add `--preview` to start a local server and open the site in your browser as soon as the build
finishes:

```{.bash filename="Terminal"}
great-docs build --from-repo https://github.com/owner/package.git --preview
```

### Previewing a Previously Built Site

If you have already built a site with `--from-repo` (or received a site directory from someone
else), use `great-docs preview --site-dir` to serve it without any project context:

```{.bash filename="Terminal"}
great-docs preview --site-dir /tmp/my-site
```

This starts the same local HTTP server and opens your browser, just like the regular
`great-docs preview` command.

## Previewing a PR or CI Build [version-badge new 0.16] {#pr-preview}

When someone opens a pull request, reviewing the rendered docs usually means checking out the
branch and rebuilding locally, or setting up a preview host (Netlify, Cloudflare Pages,
per-PR GitHub Pages). But if your CI already builds and uploads the site as an artifact
(as the [recommended workflow](14-deployment.qmd) does) you can fetch that exact build and
view it locally (with no hosting setup):

```{.bash filename="Terminal"}
great-docs preview --pr 302             # newest CI docs build for PR #302
great-docs preview --run 18273645521    # a specific workflow run
great-docs preview --branch fix-mcp     # newest build for a branch
```

Great Docs resolves the pull request to its most recent successful docs run, downloads the
`docs-html` artifact, caches it locally, and serves it with the usual preview server.

### Authentication

Downloading a workflow artifact requires a GitHub token with **Actions: read** (this is
true even for public repositories). Great Docs looks for credentials in this order, so pick
whichever is convenient:

- `GITHUB_TOKEN` or `GH_TOKEN` in your environment
- a `.env` file with `GITHUB_TOKEN=...` (auto-detected, or point at one with `--env-file`)
- the [`gh`](https://cli.github.com/) CLI: run `gh auth login`, then add `--use-gh` to let
  `gh` perform the download end-to-end

```{.bash filename="Terminal"}
gh auth login
great-docs preview --pr 302 --use-gh
```

::: {.callout-note}
Great Docs never accepts a token as a command-line argument (it would leak into your shell
history). Use an environment variable, a `.env` file, or `gh` instead.
:::

### Jumping to a specific page

Use `--path` to open the browser directly at a page within the site instead of the home
page, useful when a review comment is about one specific reference or guide:

```{.bash filename="Terminal"}
great-docs preview --pr 302 --path reference/index.html
```

### Other options

| Option | Purpose |
| --- | --- |
| `--repo owner/repo` | Target a repo explicitly (default: detected from `git remote origin`). |
| `--artifact <name>` | Fetch a differently-named artifact (default: `docs-html`). |
| `--no-open` | Serve without launching a browser. |
| `--refresh` | Ignore the local cache and re-download. |
| `--port <n>` | Serve on a specific port. |

::: {.callout-warning}
## Fork pull requests

A site built from a fork contains contributor-authored HTML and JavaScript, which your
browser will execute when you preview it locally (the same trust level as reviewing their
diff). Great Docs warns you when a build comes from a fork.
:::

::: {.callout-tip}
## Advertise it in CI

If you scaffolded your CI with [`great-docs setup-github-pages`](14-deployment.qmd), this is
already wired up: on every pull request the workflow prints a log notice **and** posts a
sticky PR comment with the exact `great-docs preview` command, pinned to that run.

To add it to a hand-maintained workflow, use the `great-docs ci` helpers. `ci notice` prints
a log annotation; `ci pr-comment` posts (and keeps updated) a sticky comment on the pull
request. Both pin the command to the run that produced the build with `--run`, so a reviewer
reproduces exactly the build they're looking at:

```{.yaml filename=".github/workflows/docs.yml"}
      # In the build job (great-docs is already installed):
      - name: How to preview this build locally
        if: github.event_name == 'pull_request'
        run: great-docs ci notice --run ${{ github.run_id }} --pr ${{ github.event.number }}

      # In a separate job with 'permissions: pull-requests: write':
      - name: Post preview instructions to the PR
        run: pipx run great-docs ci pr-comment --run ${{ github.run_id }} --pr ${{ github.event.number }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
:::

## Using the Python API

In addition to the CLI, you can drive the build programmatically:

```{.python filename="Python"}
from great_docs import GreatDocs

docs = GreatDocs()
docs.install()   # Initialize the output directory
docs.build()     # Run the full build pipeline
docs.preview()   # Start the preview server
```

The `GreatDocs` class accepts a `project_path` argument if your working directory is not the project
root:

```{.python filename="Python"}
docs = GreatDocs(project_path="/path/to/my-project")
docs.install()
docs.build()
```

## Troubleshooting

### Quarto Errors

If the build fails during the Quarto rendering step, the error output will include Quarto's own
messages. Common causes include:

- A `.qmd` file with invalid YAML frontmatter. Check that all frontmatter blocks are enclosed
between `---` markers and that the YAML is well-formed.
- A reference to a file that does not exist. If you renamed or deleted a user guide page, make
sure the `guide-section` frontmatter in other files does not depend on it.
- A Quarto version incompatibility. Great Docs is tested with Quarto 1.4 and later. Run
`quarto --version` to check your installed version.

### Missing API Reference Pages

If some symbols are missing from the rendered API reference, run `great-docs scan` to see what Great
Docs discovers. Items that appear in the scan output but not in the reference may be excluded by the
`exclude` list in `great-docs.yml` or may not be listed in the `reference` config sections.

### Dynamic Introspection Failures

If Great Docs reports an error during dynamic introspection, it will automatically retry with static
analysis. If you see this retry message frequently, you can set `dynamic: false` in `great-docs.yml`
to skip the dynamic pass entirely. See [Configuration](configuration.qmd) for details.

### Stale Output

If your site looks correct in some places but outdated in others, the most reliable fix is a clean
rebuild: delete the `great-docs/` directory and run `great-docs build` again. The output directory
is fully regenerated each time, so there is no risk in deleting it.

## Build Timings [version-badge new 0.12] {#build-timings}

Every time `great-docs build` runs, it records how long each page takes to render and writes the
results to `great-docs/_site/build-timings.json`. This helps you identify slow pages that are
bottlenecks in your build.

### Viewing Timings

Use the `great-docs timings` command to display a sorted table (slowest pages first):

```{.bash filename="Terminal"}
great-docs timings
```

```{.default}
  Build time: 2026-05-06 14:32:01
  Total: 47.2s across 38 pages

  Page                              Time
  ─────────────────────────────────────────────────
  reference/GT.qmd                  12.4s  ████████████
  reference/GT.tab_style.qmd         6.1s  ██████
  user-guide/theming.qmd             4.8s  █████
  reference/GT.fmt_number.qmd        3.9s  ████
  ...
```

Pages served from the [Quarto freeze cache](freeze.qmd) are marked with a ❄ indicator. This view
makes it easy to spot which pages are worth optimizing or splitting up.

### Filtering Results

Show only the top N slowest pages:

```{.bash filename="Terminal"}
great-docs timings --top 5
```

For multi-version builds, filter by version:

```{.bash filename="Terminal"}
great-docs timings --version 0.10
```

These filters are useful when you only care about a specific slice of the build.

### Custom Output Directories

If you built with a custom `--output-dir`, pass the same path:

```{.bash filename="Terminal"}
great-docs timings --output-dir ./public
```

This ensures the command can locate `build-timings.json` regardless of where the site was rendered.

### JSON Output

For scripting or CI integration, use `--json` to get the raw data:

```{.bash filename="Terminal"}
great-docs timings --json
```

The JSON format is convenient for piping into other tools like `jq` or for building custom
dashboards.

### CI Integration

The `great-docs setup-github-pages` workflow automatically uploads `build-timings.json` as a
separate artifact named **build-timings** in each CI run. You can download it from the workflow
run's Artifacts section on GitHub to compare build performance over time. This makes it easier to
track regressions and monitor improvements across commits.

## Next Steps

The build pipeline is designed to be fast and predictable. For most projects, `great-docs build` is
really all you need. When something goes wrong, the troubleshooting tips above probably cover the
most common causes.

- [Deployment](deployment.qmd) covers publishing your built site to GitHub Pages
- [Configuration](configuration.qmd) covers all `great-docs.yml` options
- [Link Checker](link-checker.qmd) explains how to validate links across your site
