API reference pages
An API reference page is one OpenAPI specification plus one shortcode. Choose Swagger UI when readers need to try requests, or Redoc for browsing endpoint descriptions and schemas. Both runtimes ship with the theme and load only on pages that use them in HTML output, without a CDN. Swagger UI’s online validator is disabled; remote specifications and API requests still contact their configured hosts.
Three steps: put the specification file under static/, create a page with the
shortcode, and change the page type to swagger if it needs the dedicated
shell.
Where the specification file goes
The specification goes under static/, is published unchanged at the site root,
and both shortcodes then receive a URL the browser can fetch:
where the specification lives
static/
openapi/
- docs-demo.yamlpublished as /openapi/docs-demo.yaml
content/
docs/
write/
- openapi.mdthis page
Do not put the specification beside the page. Both shortcodes treat a local
value as a path under static/; neither resolves page resources. A .yaml
beside a content page is a page resource, and Hugo does not publish it merely
because its name appears in one of these shortcodes, so the browser gets a 404.
A remote specification (starting https://…) is accepted by both shortcodes,
but that is a network dependency, and it exposes the reader’s metadata to that
host. Intranet deployments and sites with a CSP should use a same-origin
specification. Only http and https are accepted: any other scheme, a
protocol-relative //host, or an empty value warns and the shortcode renders
nothing.
To try the examples, download docs-demo.yaml and save
it as static/openapi/docs-demo.yaml in your site. It describes a demonstration
cluster-management API with no reachable server behind it.
Swagger UI
swagger has one named parameter, src, whose value is a URL from the site
root. It passes through the theme’s URL validation, so a subpath deployment
resolves correctly:
In your local preview, this displays expandable API operations, request
parameters and response schemas. “Try it out” sends requests to the
specification’s servers address; the sample has no working backend.
This page shows Swagger UI source and a live Redoc example below. Both widgets have known accessibility limitations; see Limits.
Redoc
redoc takes exactly one positional parameter, the specification path. A
second parameter warns and the shortcode renders nothing.
An http or https URL remains remote. Any other accepted value is a path
under static/; leading and non-leading slash forms are equivalent. For
example, openapi/docs-demo.yaml and /openapi/docs-demo.yaml both become
https://example.com/preview/openapi/docs-demo.yaml when the site baseURL is
https://example.com/preview/. Unlike swagger, Redoc receives this absolute
URL based on baseURL.
The theme pins five attributes — hide-hostname, hide-logo,
suppress-warnings, lazy-rendering, native-scrollbars — and hides the
Redocly brand mark with CSS. Redoc’s remaining attributes are not exposed to
authors; a site that needs them overrides
layouts/_shortcodes/redoc.html.
The dedicated page shell
API reference pages tend to be wide and long, which is what the swagger page
type is for:
swagger is one of the theme’s default shell types (params.ui.shell_types
defaults to [docs, book, blog, swagger], and a site that overrides the list
needs to keep it). It differs from the docs shell in exactly two ways: an
extra td-swagger class on <body> for styling hooks, and no version banner.
Sidebar, table of contents, breadcrumbs, pager and page end all behave normally.
Shells and page width are covered fully in Layouts and page types.
Output
| Output | What appears |
|---|---|
| HTML | The full interactive Swagger UI / Redoc; the runtime loads on demand from local files, with no CDN, and only in this output |
| A labelled static link showing the specification’s address; neither runtime loads | |
| Markdown | A plain Markdown link, [OpenAPI specification](/openapi/example.yaml); it does not degrade into an endpoint list |
| RSS | The same plain link |
Outside HTML an API reference is a pointer, not a reference. To put endpoint information into print or agent output as well, describe the key endpoints in prose on the same page; body text outside the shortcode survives intact in all four outputs.
Limits
- Both components derive their container ID from the page address and the shortcode’s ordinal, so several on one page never collide.
- The two can coexist on one page, but the page becomes long and its HTML output loads both runtimes. Pick one for a production site.
- Neither interface is fully accessible: Swagger UI has unnamed server controls and scrollable regions without keyboard access; Redoc’s operation descriptions have insufficient colour contrast. Assess these limitations against your site’s accessibility requirements. Excluding a widget from an automated check does not make it conformant; provide readable endpoint documentation when an embedded widget is unsuitable.
redocaccepts no attribute parameter: a second positional argument warns and the shortcode renders nothing.- A local
redocpath is rooted understatic/; a leading/is optional, and page resources are not resolved. - The specification must be fetchable by the browser: put it in
static/and confirm the file exists underpublic/after a build. - There is no mock server: Swagger UI’s “Try it out” makes a real request to whatever
serversnames, and the address in the sample specification is not reachable.
Verify
- The build is warning-free:
hugo --printPathWarnings --panicOnWarning. - The specification really was published:
ls public/openapi/docs-demo.yaml, or openhttp://localhost:1313/openapi/docs-demo.yaml. - Endpoints expand on the page and their schemas appear; the browser console shows no 404 and no cross-origin error.
- Disconnect from the external network while keeping the local preview server reachable, then reload: local runtimes and a same-origin specification should still appear.
Related
- Writing pages — page front matter and body basics
- Layouts and page types —
shell_types, page width and the sidebar - AI-agent support — why a component that is interactive only in HTML needs prose beside it
- Code Blocks — the lighter alternative of request / response examples instead of a whole UI