Troubleshooting
Solutions to common issues setting up, running, and building a Publier site.
publier.config.yaml isn’t being picked up
Malformed YAML or invalid supported configuration stops setup; Publier does not warn and continue with defaults. Read the parse error or Invalid publier.config.yaml diagnostic in the dev-server or build output. The file must include a site mapping with a non-empty site.name.
Validate the YAML syntax with any linter (e.g. yamllint) or against the published JSON Schema. publier doctor checks whether the YAML parses; it does not validate the full schema. Use the published JSON Schema for option validation.
Dev server refuses to start
Publier’s dev server must run under Bun — publier dev spawns bunx --bun astro dev internally. Equivalent direct invocation:
bunx --bun astro devScaffolded projects ship dev/build/preview scripts that already point at bunx --bun astro, so bun run dev works out of the box. Only hand-rolled scripts that call astro through Node (e.g. plain astro dev under npm run) need adjusting.
Q30 — module already imported (or “duplicate runtime”)
Qwik v2 throws Q30 when two instances of @qwik.dev/core end up in the module graph — typically because Vite pre-bundled a dependency that also imports Qwik. Publier guards against this automatically. If you see Q30 after customizing astro.config.ts, check that you are not spreading the existing vite plugin array:
vite: { plugins: [...(config.vite?.plugins ?? []), myPlugin()],}Astro already concatenates — spreading doubles every plugin. Pass only new entries:
vite: { plugins: [myPlugin()],}Q14 — Invalid JSX node during astro build
Q14 during static generation almost always traces back to one of two patterns:
- Importing a Qwik island from MDX —
@publier/shell/qwikexportsAskAi, acomponent$()island. Importing it directly at the top of an MDX file can cause the SSG pipeline to emit a fragment containing stale vnodes. Move the import into a small.tsxwrapper component and import that wrapper instead. (Components from@publier/shell/componentsare plain Astro — no Q14 risk there.) - Components that render
<slot />conditionally — an{cond && <slot />}pattern inside a Qwikcomponent$trips Q14 on SSG. Always render the slot unconditionally and let the conditional live inside the slot body.
My sidebar doesn’t show a new page
Check in order:
- Is the file under
src/content/docs/? Only files under thedocscollection appear in the docs sidebar. - Does it have the required
title:in the frontmatter? A missing title fails content validation; check the build or dev-server error. - Did you set
sidebar.hidden: truein the frontmatter? That filters the page even though it still builds as a route. - Did you restart the dev server after adding a new directory? Astro’s content collection watcher occasionally misses a brand-new folder; restart
publier devto pick it up.
Search dialog shows nothing
The Pagefind index is produced at build time — the dev server serves whatever index was written by the last build. Two fixes:
- Test search after a build:
publier build && bun run preview— Cmd/Ctrl+K works on the preview server identically to production. - Inspect the index directly: after
publier build,dist/pagefind/holds the WASM index and fragment files. An empty directory means the production build did not complete — confirm yourPUBLIER_TOKENis valid and re-run the build.
If you set docsShell({ search: false }) in astro.config.ts, shell skips wiring the Pagefind dialog entirely — Cmd/Ctrl+K does nothing and the nav SearchButton becomes a no-op.
My component renders but doesn’t respond to clicks
Most interactive components ship as plain Astro + web components — no client directive needed. Tabs, Accordion, Tooltip, CopyButton, ImageZoom, ColorSwatch, PackageInstall, and all OpenAPI primitives activate automatically once their markup is on the page.
Only one user-facing component is a Qwik island and needs client:load:
<AskAi client:load />docsShell() mounts the site-wide search dialog without a per-page import or client directive. Keep the scaffold’s explicit pagefind() integration to generate its production index; see Search.
If you add a client directive to an Astro component (<Tabs client:idle />), Astro will warn at build time that the directive is ignored — remove it. If an Astro component doesn’t activate, the root cause is almost always one of: the page isn’t rebuilding (restart publier dev), the page failed to load required runtime scripts (check the browser console for errors), or CSS scoping hid the interactive area (inspect element to see if the hit target is visible and pointer-events aren’t none).
content.config.ts at the project root is ignored
Keep the scaffold’s content configuration at src/content.config.ts. A config at the project root is ignored — your collections won’t be registered, and every page in src/content/docs/ will 404.
my-site/├── src/│ ├── content.config.ts ← CORRECT│ └── content/└── content.config.ts ← IGNORED (legacy location)@qwik.dev/astro peer-dep warning
docsShell() warns when the Qwik integration is not registered. Install its packages if needed:
pnpm add @qwik.dev/astro @qwik.dev/coreImport qwik from @qwik.dev/astro and add qwik({ clientRouter: true }) to integrations yourself, then restart the dev server. Installing the package alone does not register it. Keep the integration order shown in Configuration; scaffolded projects already include this entry.
OG image doesn’t render
@publier/native depends on two optional peers that are not installed by default:
pnpm add satori @resvg/resvg-jsThe error message includes the exact command when these are missing.
check-types recurses into package internals
Run bun run check-types and see errors inside node_modules/@publier/...? Some Publier packages ship TypeScript source (rather than pre-compiled .d.ts), so tsc walks into them by default. Two workarounds:
- Add
"skipLibCheck": trueto your project’stsconfig.json— cheapest fix, skips type-checking of allnode_modules. - Use a narrower
tsconfig.check.jsonthat excludesnode_modules/@publier/from the checked paths while keeping type checks for the rest of your dependencies.