On this page

Plugin API reference

Presentation plugins, collection presentations, route views, and search-provider contracts.

TidyPress extensions are project-local modules compiled into a generated manifest during dev and build. Paths stay in the repository and are validated before the engine imports them.

Presentation plugin

 import { definePlugin } from 'tidypress'
 
export default definePlugin({
  name: 'brand-system',
  setup(context) {
    context.addStyle('./src/styles/brand.css')
    context.addMdxComponent('Metric', './src/components/Metric.astro')
  },
}) 
addMdxComponent(name, component) method
Register or replace a global MDX component.
addSlot(slot, component) method
Insert a project Astro component at a stable named slot.
addThemeComponent(name, component, options?) method
Replace or wrap a public UI boundary.
addLayout(name, component) method
Register a named page canvas used by frontmatter layout.
addStyle(path) method
Bundle project CSS or link a supported stylesheet.
addScript(path) method
Bundle a project browser script.
addRemarkPlugin(path) method
Extend Markdown before HTML conversion.
addRehypePlugin(path) method
Extend the HTML syntax tree.
addSearchProvider(path) method
Register a project browser search implementation.

UI component boundaries

ui.components and addThemeComponent accept these stable names:

 RouteView · RouteViewShell
Document · DocumentHead · Analytics · ThemeBoot · BodyScripts · RootShell
Navbar · Footer · Home
DocLayout · DocHeader · DocSidebar · Toc
Search · CodeBlock · PageLayout · NotFound 

String values replace the original component. Object values accept { component, mode: 'replace' | 'wrap' }. Overrides receive their component props plus Original; wrappers receive the rendered original in their slot.

Collection presentation

 import type { TidyPressPluginPresentation } from '@tidypress/engine/plugins'
 
export function createPresentation(site, { collectionKey }): TidyPressPluginPresentation {
  return {
    async buildIndex(route) {
      return { viewKey: `${collectionKey}:collection-index`, site, route, title: 'API', headings: [], pagefindIgnore: false }
    },
    async buildEntry(route) {
      return { viewKey: `${collectionKey}:collection-entry`, site, route, title: route.slug ?? 'Entry', headings: [], pagefindIgnore: false }
    },
  }
} 
buildIndex(route) async method required
Return the route-view bundle for the collection index.
buildEntry(route) async method required
Return the route-view bundle for an entry or version-root route.

Set the module through collections.<key>.render.presentation. Optional Astro views live in the directory from render.views and use the filenames collection-index.astro, collection-entry.astro, and version-root.astro. Missing optional files use the collection kind’s baseline shell. A registered file that cannot load is a build error rather than a silent fallback.

Docs forms

Custom form keys are registered under extensions.docForms. Each descriptor can provide label, presentation, and views. The page selects it with frontmatter form: your-key. Built-in doc and manual names are reserved.

Search provider

 import { defineSearchProvider } from 'tidypress'
 
export default defineSearchProvider({
  async search(query, options) {
    return [{ url: '/docs/result', title: `Result for ${query}`, collection: options?.collection }]
  },
}) 
search(query, options?) async method required

Return { url, title, excerpt?, collection? }[]. The module runs in the browser, so do not embed private credentials.

Reload and failure behavior

During development, config and manifest changes advance the manifest epoch and reload registered modules. Invalid paths, missing required exports, unsafe parent traversal, and broken registered views fail with actionable errors.