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

Configuration

Reference for astro.config.ts, publier.config.yaml, theme.yaml, and meta.yaml.

Publier uses the following configuration files. The scaffolder creates the project-level files for you.

FileWhat it controlsRequired
astro.config.tsAstro integrations and Vite plugins✓
publier.config.yamlSite name, nav, search trigger, analytics, fonts, snippets✓ — at least site.name
theme.yamlColor preset + brand overrides—
meta.yaml (per folder)Optional metadata input for a custom route using readMetaYaml()—

astro.config.ts

docsShell() wires the Publier pipeline — theme tokens, callouts, remark/rehype plugins, default routes, and Mermaid auto-detection. The five framework integrations are registered explicitly (Publier warns at startup with a copy-paste list if any is missing — it never adds them for you):

astro.config.ts
import { defineConfig } from 'astro/config';
import { docsShell } from '@publier/shell/integration';
import expressiveCode from 'astro-expressive-code';
import mdx from '@astrojs/mdx';
import sitemap from '@astrojs/sitemap';
import pagefind from 'astro-pagefind';
import qwik from '@qwik.dev/astro';
export default defineConfig({
integrations: [
docsShell(),
expressiveCode(),
mdx(),
sitemap(),
pagefind(),
qwik({ clientRouter: true }),
],
});

Order matters twice: docsShell() comes first — astro-expressive-code ≥0.43 registers into the Markdown processor it finds at its own setup, so Publier’s processor must already be in place (with it last, code fences silently render as plain <pre><code>) — and expressiveCode() comes before mdx() so its plugins slot into the MDX pipeline. This is the same array publier new scaffolds.

Wired by docsShell()

Every wire-up is idempotent — Publier detects existing config and backs off.

Disableable defaults (on by default):

Wired by docsShell()DisableSkipped when
astro-mermaid (auto-detected)docsShell({ mermaid: false })already in integrations[] or not installed
prefetch (prefetchAll + viewport)docsShell({ prefetch: false })astro.config.ts already sets prefetch:
rehype-autolink-headingsdocsShell({ autolinkHeadings: false })—
rehype-external-links (target="_blank" on outbound links)docsShell({ externalLinks: false })—
Math (KaTeX, via remark-math + rehype-katex)docsShell({ math: false })—
Search UI (Pagefind dialog + button)docsShell({ search: false })—

Opt-in features (off by default):

FeatureEnablePeer deps
SnippetsdocsShell({ snippets: { directory: 'src/content/snippets' } })—

Driven by publier.config.yaml (inert when the key is absent):

  • vars: — expands {{var}} placeholders inside MDX text.
  • fonts: — emits Google Fonts links or @font-face blocks plus --font-sans / --font-serif / --font-mono overrides.
  • analytics: — injects provider snippets (GA4, PostHog, Plausible, Fathom, Umami) into <head>.
  • sidebar.hidden: true in page frontmatter — excludes the page from the auto-generated sidebar.

Ordering

Astro runs integrations in array order. Keep docsShell() first: it pins the Markdown processor that later integrations register into — astro-expressive-code ≥0.43 detects the processor at its own setup, so registering it before docsShell() silently drops all code-fence processing (Publier warns at startup when it sees this). Keep expressiveCode() before mdx(). Markdown plugin arrays are concatenated — Publier’s plugins run first, then yours.

src/content.config.ts

Register your content collections. Publier ships loaders and schemas for each:

src/content.config.ts
import { defineCollection } from 'astro:content';
import { docsLoader, blogLoader, contentLoader } from '@publier/shell/loaders';
import { docsSchema, blogSchema, changelogSchema } from '@publier/shell/schemas';
export const collections = {
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
blog: defineCollection({ loader: blogLoader(), schema: blogSchema }),
changelog: defineCollection({
loader: contentLoader({ base: './src/content/changelog' }),
schema: changelogSchema,
}),
};

docsSchema() accepts an extend option for adding custom frontmatter fields. If you extend, note that Astro 7 bundles zod v4 (astro/zod — the z behind astro:content schemas), so zod-v3-only idioms in schema extensions need updating.

publier.config.yaml

Project-root YAML file. docsShell() reports malformed supported sections as build errors. publier doctor checks YAML syntax only; use a build to validate the framework configuration.

publier.config.yaml
site:
name: My Docs # site name (OG images, RSS, meta tags)
url: https://docs.example.com # canonical URL for sitemaps
nav:
default:
links:
- label: GitHub
href: https://github.com/my-org/my-docs
external: true
snippets:
directory: src/content/snippets # reusable MDX fragments
search:
enabled: true # show the header search trigger
llms:
enabled: true # generate /llms.txt for the whole site

See Global settings for the full field list.

theme.yaml

Pick a built-in preset, then optionally override individual tokens:

theme.yaml
preset: maple # almond, aspen, catppuccin, dark, dusk, emerald, enterprise, light,
# maple, neutral, ocean, purple, ruby, solar, vitepress
colors:
primary: "oklch(65% 0.2 50)"

See Theming for the full token reference.

meta.yaml (per folder)

The default documentation route reads section metadata from publier.config.yaml:

publier.config.yaml
docs:
sidebar:
meta:
guides: { label: Guides, order: 20 }

Pages use sidebar.order frontmatter, with top-level order as the fallback. The nested field takes precedence from native 8.0.3.

For a custom docs route, readMetaYaml(basePath) from @publier/shell/search reads folder meta.yaml files into sidebar metadata. The custom route must merge that metadata and pass it to buildSidebar(). Creating the files alone does not change the default route.