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

Integrations

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

Publier sits on top of Astro 7, so every Astro integration works. Publier auto-wires the ones you actually need (MDX, resumable islands, syntax highlighting, Mermaid when present) and reads declarative opt-ins from publier.config.yaml for analytics, fonts, and content variables.

@publier/openapi

Generate MDX pages and interactive components from an OpenAPI 3.x or AsyncAPI 2/3 spec. The API Reference section of this site is built with it.

Terminal window
pnpm add @publier/openapi

Point publier.config.yaml at your spec and Publier auto-generates pages under /api at build time:

publier.config.yaml
integrations:
openapi: ./openapi.yaml # or an array of paths for multi-spec merge
asyncapi: ./events.yaml

Or call the server-side API yourself for full control:

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) plus a meta.yaml per group subdirectory that orders them on the sidebar.

See the OpenAPI guide for the full walkthrough.

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.

Zero-config — docsShell() wires up the search modal and the index automatically. The dialog opens on ⌘K or the header search button and inherits your theme tokens, so it matches the rest of the site in both light and dark mode.

To opt out of search entirely:

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.

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

All scripts respect placement: head | body and 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: [email protected]

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