Server-side rendering

@mykulyak/apigenie-docs/ssr renders the elements in Node with @lit-labs/ssr into declarative shadow DOM: the documentation is HTML that search engines index and readers see before any script runs. The hydrate entry point then makes it interactive without rendering it again.

import { renderApiReference, preloadSpecAsync, pathToRoute, seoMeta, seoHead } from "@mykulyak/apigenie-docs/ssr";

const context = await preloadSpecAsync("/openapi.yaml", yamlText);
const html = await renderApiReference({ specUrl: "/openapi.yaml", route: "operation/getPet", routing: "history", basePath: "/docs" });
const head = seoHead(seoMeta(context, pathToRoute("operation/getPet"), "/docs"), "https://example.com");
// The page: <head>${head}</head>
// <body>${html}<script type="module" src="…/apigenie-web-components-hydrate.js"></script></body>
Function
renderApiReference(options) Renders <apg-api-reference> on the page route. With spec, it reads that document first; without it, it renders the document preloaded for specUrl. It throws when no document is preloaded for specUrl or the document cannot be read.
preloadSpec(url, document, format?, extras?) Reads a document for the elements naming url in spec-url, and returns its context. OpenAPI and Swagger 2.0 text or values and documentation models are read at once. AsyncAPI documents, .proto and GraphQL text are read in the background; preload them with preloadSpecAsync before rendering.
preloadSpecAsync(url, document, format?, extras?) The same, resolving once AsyncAPI documents, .proto and GraphQL text are read with the configured module.
preloadedSpec(url) The context preloaded for url, if any.
clearSpecRegistry() Forgets every preloaded document, between two renders of different sites.
renderToString(template, renderInfo?) Renders a page of parts after preloadSpec, each part naming the document in spec-url.
routes(context) Every page of the reference, for a sitemap; the changelog page included when the context has one.
routeToPath(route), pathToRoute(path) The path of a page, and the page of a path.
seoMeta(context, route, basePath?) The title, description and path of a page.
seoHead(meta, origin?, alternates?) The <head> HTML of a page: title, description, the canonical link when origin is given, and the hreflang alternates.
specScript(context) The document as <script type="application/json" data-apg-spec>, which renderApiReference embeds.
docsScript(context) The extras of a docs bundle, as <script data-apg-docs>.
configureAsyncApiEngine(url), configureProtobufEngine(url), configureGraphQLEngine(url) Set the WebAssembly module that reads the documents of each standard.

Options of renderApiReference

Option
specUrl The key of the document; the elements of the page use it as spec-url. Required.
spec The document as text or a value. Left out, the document preloaded for specUrl is rendered.
route The page, such as operation/getPet; by default the overview.
routing, basePath, layout, theme As the attributes of <apg-api-reference>.
proxyUrl, oauth2RedirectUrl As proxy-url and oauth2-redirect-url.
hideTryIt, hideSchemas, showProblems As hide-try-it, hide-schemas and show-problems.
embedDocument Write the <script data-apg-spec> with the document; true by default.

The embedded document

The rendered markup embeds the document as <script type="application/json" data-apg-spec>, so the browser uses what the server rendered instead of fetching the document again. For an AsyncAPI document, a Protobuf file or a GraphQL schema it embeds the documentation model, which the browser reads without the module.

AsyncAPI documents, as text or values, need the module on the server too: call configureAsyncApiEngine(url) with the Node build (asyncapi.mjs, as a file: URL), then pass the document to renderApiReference or preloadSpecAsync. After preloadSpec it is not read yet. .proto text likewise needs configureProtobufEngine and protobuf.mjs, and GraphQL text configureGraphQLEngine and graphql.mjs. Their documentation models, which a docs bundle holds, are read without a module.

Was this helpful?