Antora Project Structure Guide

Reference guide for setting up and organizing an Antora documentation project. Based on the domus-* ecosystem (15 spoke repos + 1 hub).

Standard Module Structure

Every Antora component follows this directory layout:

docs/                              (1)
├── antora.yml                     (2)
└── modules/
    └── ROOT/                      (3)
        ├── nav.adoc               (4)
        ├── pages/                 (5)
        │   ├── index.adoc
        │   └── topic/
        │       └── page.adoc
        ├── partials/              (6)
        │   └── reusable-table.adoc
        ├── examples/              (7)
        │   └── scripts/
        │       └── example.sh
        └── images/                (8)
            └── diagrams/
                └── architecture.svg
1 docs/ — Antora start path (configured in antora.yml or playbook)
2 antora.yml — component descriptor (name, title, version, attributes)
3 ROOT — default module name. Most projects only need ROOT.
4 nav.adoc — sidebar navigation tree
5 pages/ — publishable content. Every .adoc here becomes a URL.
6 partials/ — reusable content fragments. Included via include::partial$file.adoc[]
7 examples/ — code snippets. Included via include::example$file.sh[]
8 images/ — images and diagrams. Referenced via image::file.svg[]

antora.yml (Component Descriptor)

name: my-component          # Used in cross-references: xref:my-component::page.adoc[]
title: My Documentation     # Display name in UI
version: ~                  # ~ = versionless (recommended for docs-as-code)
start_page: ROOT:index.adoc
nav:
  - modules/ROOT/nav.adoc

asciidoc:
  attributes:
    # Global attributes available to ALL pages in this component
    icons: font
    source-highlighter: highlight.js
    attribute-missing: warn     # Catch typos in attribute references

    # Custom attributes (use instead of hardcoding values)
    domain: example.com
    server-ip: '10.0.0.1'
    author: Your Name

Images and Diagrams

Images go in modules/ROOT/images/. Organize with subdirectories:

images/
├── diagrams/           # D2, Mermaid, PlantUML rendered SVGs
│   ├── architecture/
│   ├── network/
│   └── security/
├── screenshots/        # UI screenshots
└── logos/              # Branding

Reference in pages:

// Simple image
image::diagrams/architecture/my-diagram.svg[Alt text,800]

// Image in collapsible block
[%collapsible]
====
image::screenshots/ise-dashboard.png[ISE Dashboard]
====
You do NOT need a separate images/ directory per module. One images/ directory at the module level is standard. Organize with subdirectories inside it.

Partials (Reusable Content)

Partials are content fragments included in multiple pages. Single source of truth.

partials/
├── tables/              # Reusable tables (project status, inventory)
├── trackers/            # Status trackers (priorities, blockers)
├── projects/            # Project documentation (modular lego pieces)
│   └── my-project/
│       ├── summary.adoc
│       ├── architecture.adoc
│       └── roadmap.adoc
└── nav/                 # Navigation partials (modular sidebar)

Include syntax:

// Include a partial
include::partial$tables/project-status.adoc[]

// Include with tag filtering (selective sections)
include::partial$trackers/priorities.adoc[tag=p0]

// Cross-component partial (from another repo)
include::infra-ops::partial$vlan-table.adoc[]

Examples (Code Snippets)

Examples are reusable code blocks included in pages.

examples/
├── scripts/
│   └── backup.sh
├── configs/
│   └── nginx.conf
└── api/
    └── curl-examples.sh

Include syntax:

// Include entire file
[source,bash]

include::example$scripts/backup.sh[]

// Include tagged region
[source,bash]

include::example$api/curl-examples.sh[tag=auth]


Cross-References

// Same component (single colon or none)
xref:topic/page.adoc[Link Text]

// Different component (DOUBLE colon required)
xref:infra-ops::runbooks/deployment.adoc[Deployment Guide]
xref:ise-linux::02-pki/certificate-enrollment.adoc[Cert Enrollment]

// CRITICAL: Use full paths from pages/ root in nested directories
// WRONG:  xref:sibling-page.adoc[Link]  (relative — breaks in subdirs)
// RIGHT:  xref:topic/subtopic/sibling-page.adoc[Link]

Navigation (nav.adoc)

// Inline navigation
* Section Title
** xref:pages/topic.adoc[Page Title]
*** xref:pages/topic/subtopic.adoc[Subtopic]

// Modular navigation (include partials for large navs)
* Projects
** xref:projects/index.adoc[Overview]

include::partial$nav/projects-chla.adoc[]

include::partial$nav/projects-personal.adoc[]

Hub-Spoke Architecture

For multi-repo documentation (like domus-*):

Hub: domus-docs (aggregator)
├── antora-playbook.yml        # Lists ALL spoke repos
├── ui-bundle.zip              # Custom UI theme
└── Deploys to: docs.example.com

Spoke: domus-captures          # Component: captures
Spoke: domus-infra-ops         # Component: infra-ops
Spoke: domus-ise-linux         # Component: ise-linux
Spoke: domus-netapi-docs       # Component: netapi
...

Playbook (hub):

content:
  sources:
    - url: https://github.com/user/domus-captures.git
      branches: main
      start_path: docs
    - url: https://github.com/user/domus-infra-ops.git
      branches: main
      start_path: docs

Local build (single spoke):

content:
  sources:
    - url: .
      branches: HEAD
      worktrees: true
      start_path: docs

Attributes — Never Hardcode

// WRONG — hardcoded values
Connect to `10.50.1.20` on port `9060`.

// RIGHT — use attributes from antora.yml
Connect to \{ise-ip} on port \{ers-port}.

// In code blocks, add subs=attributes+ to resolve attributes
[source,bash,subs=attributes+]

Quick Start: New Spoke Repo

mkdir -p docs/modules/ROOT/{pages,partials,examples,images}

Create docs/antora.yml:

name: my-component
title: My Documentation
version: ~
start_page: ROOT:index.adoc
nav:
  - modules/ROOT/nav.adoc
asciidoc:
  attributes:
    icons: font
    source-highlighter: highlight.js
    attribute-missing: warn

Create docs/modules/ROOT/nav.adoc:

* xref:index.adoc[Home]

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

= My Documentation
:description: What this component covers
:navtitle: Home

Welcome to the documentation.

Add to hub playbook, push, build.