On this page

Extending TidyPress

Presentation plugins, component and Markdown hooks, custom collections, and custom docs forms.

Project-local presentation hooks for custom sections and docs forms.

For the general definePlugin() setup API—MDX components, stable slots, theme component overrides, named layouts, styles, scripts, Markdown plugins, and search providers—see Presentation API → Presentation plugins. Those contributions and the collection/form hooks below share the same generated manifest and dev reload path.

Two axes

TidyPress separates content location from page model:

AxisDeclared inUse for
Collectioncollections.<key>a site section and base path
Doc formdocs frontmatter forma page model inside the docs collection

Folders build URLs. They do not declare page models.

Built-in docs forms

Docs pages support:

formLayout
docdefault docs page with sidebar, table of contents, and chapter navigation
manualprocedural page chrome and step styling
---
title: Install guide
form: manual
order: 1
---

Doc pages can set part for chapter grouping:

---
title: Routing
part: Part I
order: 2
---

Doc chapter navigation follows the configured sidebar order when present, then frontmatter order.

Custom collections

Add another section with a built-in kind:

collections: {
  guides: {
    enabled: true,
    basePath: '/guides',
    kind: 'content',
    label: 'guides',
  },
}

Kinds: content, writing, projects, page.

Custom collection rendering

Project-local presentation code:

collections: {
  api: {
    enabled: true,
    basePath: '/api',
    kind: 'content',
    render: {
      presentation: './site/renderers/api-presentation.ts',
      views: './site/views/api/',
    },
  },
}

On tidypress dev and tidypress build:

  1. The config is validated.
  2. TidyPress writes a plugin manifest into the local cache (~/.cache/tidypress/.../codegen/).
  3. Custom Astro views resolve from your project via the @project alias.
  4. The engine imports the presentation module.
  5. RouteViewShell uses your view when a matching key exists.

Paths must be project-local ./ paths. Parent directory traversal is rejected.

collections.docs cannot set render. Docs pages use form.

Presentation module

Export createPresentation(site, context):

import type { TidyPressConfig } from '@tidypress/config'
import type { TidyPressPluginPresentation } from '@tidypress/engine/plugins'
 
export function createPresentation(
  site: TidyPressConfig,
  context: { collectionKey: string },
): TidyPressPluginPresentation {
  return {
    async buildIndex(route) {
      return {
        viewKey: `${context.collectionKey}:collection-index`,
        site,
        route,
        title: 'API',
        headings: [],
        pagefindIgnore: true,
      }
    },
    async buildEntry(route) {
      return {
        viewKey: `${context.collectionKey}:collection-entry`,
        site,
        route,
        title: route.slug ?? 'API entry',
        headings: [],
        pagefindIgnore: false,
      }
    },
  }
}

Prefix view keys with the collection key.

Optional Astro views

If render.views points to ./site/views/api/, TidyPress looks for:

collection-index.astro
collection-entry.astro
version-root.astro

Missing files are skipped. Built-in views are used as fallback.

Custom docs forms

Register custom forms with extensions.docForms:

extensions: {
  docForms: {
    'api-reference': {
      label: 'API reference',
      presentation: './site/renderers/api-reference-presentation.ts',
      views: './site/views/api-reference/',
    },
  },
}

Then use the form in docs frontmatter:

---
title: POST /v1/widgets
form: api-reference
---

Built-in form names cannot be overridden.

Development reload

During tidypress dev, changes to config, presentation modules, and optional views regenerate the plugin manifest and reload the browser.

If a plugin path or export is invalid, TidyPress fails before the server starts. Fix the config path or module export and run again.