Navigation
How OpenAPI tags, paths, models, and webhooks become browsable docs.printing press builds navigation from the OpenAPI contract itself.
That means the sidebar, overview page, operation breadcrumbs, tag pages, model groups, and webhook section all come from
the same rendered documentation model. There is no second navigation file to keep in sync. The spec owns the shape, and
printing press turns that shape into stable pages.
The navigation model is composed from:
- root-level OpenAPI tags
- operation tags
- operation paths and operation IDs
- component models
- webhooks
- diagnostics counts, when diagnostics mode is enabled
OpenAPI 3.2 hierarchical tags
OpenAPI 3.2 allows tags to describe hierarchy. printing press reads parent relationships from the root tags list
and builds a tree from them.
Use this when the API already has a product, domain, or workflow structure:
openapi: 3.2.0
info:
title: Travel API
version: 1.0.0
tags:
- name: Travel
summary: Travel
kind: nav
- name: Bookings
summary: Bookings
parent: Travel
description: Booking lifecycle operations.
- name: Payments
summary: Payments
parent: Travel
description: Payment capture and refund operations.
paths:
/bookings:
get:
tags:
- Bookings
summary: List bookings
operationId: listBookings
responses:
"200":
description: OK
In that shape, Travel is the parent navigation group. Bookings and Payments are child groups. Operations tagged
with Bookings appear under the Travel > Bookings path and get breadcrumbs back through that same hierarchy.
kind: nav marks a tag as a grouping node. Use it for a parent that exists to organize the docs, not to own operations
directly.
Each tag also gets its own generated tag page under tags/*.html. If the tag has a markdown description, that
description is rendered on the tag page before the operation list.
OpenAPI 3.1 flat tags
OpenAPI 3.1 tags are flat, and printing press treats them that way.
openapi: 3.1.0
info:
title: Travel API
version: 1.0.0
tags:
- name: Bookings
description: Booking lifecycle operations.
- name: Payments
description: Payment capture and refund operations.
paths:
/bookings:
get:
tags:
- Bookings
summary: List bookings
operationId: listBookings
responses:
"200":
description: OK
The root tags list defines the visible operation groups. Operations are assigned by tag name, so the value in
operation.tags should match the root tag name.
If a root tag is declared but never receives an operation or child tag, printing press removes it from the rendered
navigation. Empty placeholders do not clutter the docs.
Slug matching and stable URLs
Every generated page gets a URL-safe slug.
Tag names, operation IDs, model names, and synthetic path groups are normalized into lower-case, kebab-case URL segments. Long slugs are bounded, and collisions get a numeric suffix so pages stay addressable.
Operations prefer operationId for their page slug:
operationId: listBookings
That becomes:
operations/list-bookings.html
If there is no operationId, printing press falls back to the HTTP method and path.
Stable operation IDs are the cleanest way to keep links durable across releases. Tag slugs and model slugs follow the same URL-safe rules, so generated links work in static, published, and served output.
Inside the rendered docs, those slugs become the matching key for navigation state. The current operation or model slug opens the right group, marks the active link, and connects breadcrumbs back to generated tag, operation, and model pages.
Path fallback
Some specs use no operation tags. Others use one or two broad tags across a large API, which makes the sidebar almost useless.
When tags are missing, unknown, or too coarse, printing press composes operation navigation from path patterns.
It reads the first meaningful path segments and turns them into navigation groups:
/v1/accounts/{accountId}/transactions
becomes:
Accounts > Transactions
Version prefixes like v1, path parameters like {accountId}, and action-only segments like get, list, create,
update, and delete are skipped so the navigation stays resource-focused.
When a path group has multiple useful second-level segments, printing press creates a parent and child structure. When
there is only one useful segment, it stays flat.
Coarse tag fallback
Large APIs sometimes tag every operation with the same vendor, product, or umbrella tag.
For that shape, printing press can treat the API as effectively untagged and reuse the same path-pattern grouping. By
default, this happens when a spec has enough operations and only a very small number of distinct operation tags.
So a large spec that tags everything as:
tags:
- name: plaid
paths:
/accounts:
get:
tags:
- plaid
/transactions:
get:
tags:
- plaid
can render as:
Accounts
Transactions
instead of one giant plaid bucket.
This is not a replacement for good tags. It is a safety net for specs that were authored for validation, not for docs.
Models and webhooks
Operation tags are only one part of the navigation.
printing press also builds a model section from OpenAPI components. Schemas, responses, parameters, request bodies,
headers, security schemes, examples, links, and callbacks are grouped by component type when they exist.
Webhooks are rendered as their own navigation section, separate from request-response operations.
The result is one sidebar with:
- API overview
- diagnostics, when diagnostics mode is enabled
- operations
- models
- webhooks
Authoring guidance
Use OpenAPI 3.2 hierarchical tags when the API has a real information architecture.
Use OpenAPI 3.1 flat tags when the API is smaller, or when a single operation group is enough.
Keep root tag names and operation tag values identical. summary is a better place for a cleaner display label.
Prefer stable operationId values. They produce better operation page URLs than method-and-path fallback slugs.
Let the path fallback clean up unfinished specs, not define the long-term documentation structure.