Skip to content
✨ Publier v1 is live — a polished docs platform built for the open web.
On this page

Integrations

OpenAPI, Mermaid, KaTeX, search, analytics — the integrations Publier ships or auto-detects, and how to add your own.

Publier builds on Astro 7. The scaffolder explicitly registers MDX, Qwik, syntax highlighting, sitemap, and Pagefind integrations; docsShell() warns when a required integration is missing and does not add it. It supplies Publier’s Markdown pipeline, detects Mermaid when installed, and reads analytics, fonts, and content variables from publier.config.yaml. See Configuration for the integration order.

The Astro config snippets below focus on individual options. Apply those options to your existing configuration and retain the scaffolded integration array; the snippets do not replace the complete config.

@publier/openapi

Generate MDX pages from an OpenAPI 3.x spec. The API Reference section of this site is built with it. AsyncAPI has partial content-source and component APIs, but no MDX file generator; see the AsyncAPI limits.

Terminal window
pnpm add @publier/openapi yaml

Generate pages with the server-side API before building. The reserved integrations.openapi and integrations.asyncapi configuration fields do not run a generator today.

scripts/generate-api.ts
import { generateFiles } from '@publier/openapi/generate';
import { readFileSync } from 'node:fs';
import { parse } from 'yaml';
generateFiles({
spec: parse(readFileSync('./openapi.yaml', 'utf-8')),
outputDir: './src/content/docs/api',
groupBy: 'tag',
per: 'operation',
});

The generator emits one MDX file per operation (with per: 'operation', the default shown above). It also emits meta.yaml inputs for custom routes. The default docs route discovers the MDX pages and uses docs.sidebar.meta in publier.config.yaml for section labels and ordering; it does not read the generated metadata files.

See the OpenAPI guide for the full walkthrough.

Run the script with bun scripts/generate-api.ts, then publier build.

Publier’s search is powered by Pagefind. After every build, the scanner runs against your emitted HTML and writes a static index that ships alongside your site. There’s no server component and no proprietary index format.

The scaffold registers astro-pagefind explicitly to build the index. Keep pagefind() in your Astro integration array; docsShell() supplies the search dialog but does not register the indexer. The dialog opens on Cmd/Ctrl+K or the header search button and inherits your theme tokens.

To disable Publier’s search dialog:

astro.config.ts
import { docsShell } from '@publier/shell/integration';
export default defineConfig({
integrations: [docsShell({ search: false })],
});

When search: false, the dialog is skipped; the header search button becomes a no-op unless you wire your own publier:search-toggle listener. Also remove pagefind() if you want to stop generating its index, and set search.enabled: false in publier.config.yaml to hide the header trigger.

Dev-server note: the index is only generated at build time. On a brand-new clone with no prior build, the dialog opens but shows “Search index not ready yet — run a production build to generate it.” Run publier build once; subsequent publier dev sessions serve the previously-built index transparently.

Diagrams — Mermaid

Install the packages and Publier picks them up automatically. No config changes.

Terminal window
pnpm add astro-mermaid mermaid

Then use fenced mermaid blocks in any MDX file:

```mermaid
flowchart LR
A[MDX] --> B(Publier) --> C[Static HTML]
```

Dark/light theme follows ThemeToggle automatically.

To disable Mermaid even when the packages are installed, pass docsShell({ mermaid: false }) explicitly.

Math — KaTeX

Install the peer deps and opt in via docsShell({ math: true }):

Terminal window
pnpm add remark-math rehype-katex katex
astro.config.ts
import { defineConfig } from 'astro/config';
import tailwind from '@tailwindcss/vite';
import { docsShell } from '@publier/shell/integration';
export default defineConfig({
integrations: [docsShell({ math: true })],
vite: { plugins: [tailwind()] },
});

Then write inline or display math in any MDX file:

Inline: $E = mc^2$
Block:
$$
\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
$$

See the Math Equations guide for the full reference.

Analytics

Declare analytics in publier.config.yaml — Publier injects the provider snippets into <head> at build time. Five providers are supported out of the box, plus arbitrary custom scripts.

Google Analytics 4

publier.config.yaml
analytics:
ga4:
measurementId: G-XXXXXXXXXX

PostHog

publier.config.yaml
analytics:
posthog:
apiKey: phc_xxxxxxxx
host: https://app.posthog.com # optional, defaults to https://app.posthog.com

Plausible

publier.config.yaml
analytics:
plausible:
domain: example.com
selfHosted: https://plausible.my-host.com # optional, for self-hosted instances

Fathom

publier.config.yaml
analytics:
fathom:
siteId: ABCDEFGH

Umami

publier.config.yaml
analytics:
umami:
websiteId: 00000000-0000-0000-0000-000000000000
src: https://analytics.my-host.com/script.js

Custom scripts

Need a tag that isn’t one of the built-in providers? Add arbitrary scripts:

publier.config.yaml
analytics:
scripts:
- src: https://my-cdn.example.com/my-tag.js
async: true
- content: "window.dataLayer = window.dataLayer || [];"
placement: head

Custom scripts with no placement, or with placement: head, are injected into the head. The current shell does not inject scripts marked placement: body; that placement is not supported by the automatic path. External scripts support the async / defer flags.

Custom fonts

Declare web fonts in publier.config.yaml — Publier injects the <link>/@font-face declarations and overrides the --font-sans / --font-serif / --font-mono CSS variables:

publier.config.yaml
fonts:
heading:
family: Inter
googleFontsUrl: https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap
body:
family: Inter
googleFontsUrl: https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap
mono:
family: JetBrains Mono
src: /fonts/JetBrainsMono-Regular.woff2
weight: "400"

Google Fonts and local @font-face sources are both supported; local files are referenced relative to public/.

Content variables

Centralize repeated strings (version numbers, product names, URLs) in publier.config.yaml:

publier.config.yaml
vars:
productName: My Product
version: "2.5.0"
supportEmail: support@example.com

Use them with {{key}} interpolation in any MDX/Markdown text:

Install {{productName}} v{{version}}: `pnpm add my-product@{{version}}`.
Need help? Email {{supportEmail}}.

Code blocks are not interpolated — placeholders inside fenced code are rendered literally.

Adding your own remark/rehype plugins

Publier auto-wires the standard plugins. Append your own via Astro’s markdown config:

astro.config.ts
import { defineConfig } from 'astro/config';
import { docsShell } from '@publier/shell/integration';
import remarkSmartypants from 'remark-smartypants';
import rehypeExternalLinks from 'rehype-external-links';
export default defineConfig({
integrations: [docsShell()],
markdown: {
remarkPlugins: [[remarkSmartypants, { dashes: 'oldschool' }]],
rehypePlugins: [[rehypeExternalLinks, { target: '_blank', rel: ['noopener'] }]],
},
});

User plugins run after Publier’s built-ins. See Plugins for the full list and execution order.

More