Your first Antora site

This tutorial teaches the docs-as-code workflow by building it. In about 45 minutes you'll create a documentation component inside a product repository, write a few pages in AsciiDoc, assemble them into a site with Antora, and make the kind of change (a reusable snippet, a cross-reference) that shows why this toolchain is worth the setup.

You don't need to know AsciiDoc or Antora. You do need to be comfortable running commands in a terminal and making git commits.

What you'll build

Two directories that mirror how real teams organize this:

  • widget/: a stand-in for your product repository, with a docs/ directory holding the documentation component.
  • docs-site/: the playbook repository that knows how to assemble one or more components into a published site.

Keeping them separate from the start matters: the product team owns the content, the docs platform owns the site, and neither blocks the other.

Prerequisites

  • Node.js 18 or newer. Antora is a Node application. Check with node --version.
  • git, with any name/email configured.
  • A browser for admiring the result.

1. Create the documentation component

Antora doesn't crawl your repository looking for docs; it reads a component, a directory with a descriptor file and a fixed layout. Create the skeleton:

mkdir -p widget/docs/modules/ROOT/pages
cd widget
git init

The layout under docs/ is Antora's standard structure:

docs/
├── antora.yml <- component descriptor
└── modules/
└── ROOT/ <- the default module
├── nav.adoc <- navigation tree
├── pages/ <- one .adoc file per page
├── partials/ <- reusable snippets
└── examples/ <- code samples for inclusion

ROOT is the module whose pages sit at the component's root URL; extra modules (say, admin/) become URL subpaths when you need them. Don't invent a different layout; the fixed structure is what lets Antora resolve references between files without configuration.

Now the descriptor. Create docs/antora.yml:

name: widget
title: Widget
version: '1.0'
nav:
- modules/ROOT/nav.adoc

Two things deserve attention. The name is the component's stable identity in URLs and cross-references. Pick it once, keep it lowercase, and never brand it. And version is quoted because YAML would otherwise read 1.0 as a number; Antora wants a string.

2. Write the first pages

Create docs/modules/ROOT/pages/index.adoc:

= Widget Documentation
:description: What Widget is and where to start.
Widget is a small service that does one thing well. These docs cover
installing it, operating it, and understanding why it behaves the way
it does.
== Where to start
* If you're new, start with xref:install.adoc[Install Widget].
* If Widget is already running, see the operations pages in the
navigation.

And a second page, docs/modules/ROOT/pages/install.adoc:

= Install Widget
:description: Install Widget from a release tarball.
This page walks through a first-time installation.
== Download and unpack
[source,bash]
----
curl -LO https://example.com/widget/widget-1.0.tar.gz
tar -xzf widget-1.0.tar.gz
----
== Verify the installation
[source,bash]
----
widget --version
----
NOTE: If the command isn't found, make sure the unpacked directory is on
your `PATH`.

That's most of the AsciiDoc you need on day one: =/== for headings, * for bullets, [source,bash] + ---- fences for code, NOTE: for admonitions, and xref: for links between pages. The xref:install.adoc[] form is the habit to build early: Antora resolves it at build time and complains if the target doesn't exist, which is the difference between a build warning and a customer finding a 404.

Finally, the navigation tree, docs/modules/ROOT/nav.adoc, an AsciiDoc list of xrefs that becomes the site's sidebar:

* xref:index.adoc[Overview]
* xref:install.adoc[Install]

Commit the component:

git add docs
git commit -m "Add the Widget documentation component"

The commit matters more than it looks: Antora reads content from git, not from loose files. An uncommitted page doesn't exist as far as a normal build is concerned.

3. Create the playbook and build the site

The playbook repository is the site's recipe. Set it up next to widget/:

cd ..
mkdir docs-site && cd docs-site
git init
npm init -y
npm install @antora/cli@3.1 @antora/site-generator@3.1

Create antora-playbook.yml:

site:
title: Widget Docs
start_page: widget::index.adoc
content:
sources:
- url: ../widget
branches: HEAD
start_path: docs
ui:
bundle:
url: https://gitlab.com/antora/antora-ui-default/-/jobs/artifacts/HEAD/raw/build/ui-bundle.zip?job=bundle
snapshot: true

Reading it top to bottom: the site's start page is the index.adoc page of the widget component; the content comes from the git repository at ../widget (a local path during development, an https:// URL in production), reading the current branch (HEAD), with the component rooted at docs/; and the look and feel comes from Antora's default UI bundle, which is a separate artifact precisely so content builds never depend on a frontend toolchain.

Build it:

npx antora antora-playbook.yml

Open build/site/index.html in your browser. You have a documentation site: sidebar navigation from your nav.adoc, a component/version selector, and your two pages — built from a git repository, by a command a CI runner can execute.

4. Make the change that shows the point

Suppose both pages need the same warning about supported platforms. In a wiki you'd paste it twice and the copies would drift. Here, you write it once.

Create widget/docs/modules/ROOT/partials/supported-platforms.adoc:

WARNING: Widget 1.0 supports Linux (x86_64 and arm64) and macOS 13+.
Windows support is planned for 2.0.

Then pull it into install.adoc (and anywhere else) with one line:

include::partial$supported-platforms.adoc[]

The partial$ prefix is an Antora resource ID family; it says "resolve this from the partials/ directory of this module." The same pattern gives you example$ for code samples and image$ for figures, and it keeps working when a page moves, because nothing is a relative file path.

Commit in widget/, rebuild in docs-site/:

cd ../widget
git add docs && git commit -m "Single-source the supported-platforms warning"
cd ../docs-site
npx antora antora-playbook.yml

Reload the page. The warning renders in place — and the day platform support changes, you'll edit one file and every page that includes it will be correct in the next build.

To see the safety net work, try breaking something: change a page's xref to xref:intsall.adoc[] and rebuild. Antora logs an error naming the page and the unresolved target. In the CI how-to you'll promote that from a log line to a failed build.

What you learned

  • A documentation component is a conventional directory in the product's repository: antora.yml plus modules/*/pages, partials/, and examples/.
  • The playbook repository assembles components into a site; content teams and the docs platform stay decoupled.
  • Antora reads content from git, which is what makes versions-from- branches possible later.
  • xref: and include::partial$...[] are the two AsciiDoc habits that pay rent immediately: validated links and single-sourced content.

Where next