tidypress
On this page

Extending TidyPress

Advanced rendering hooks for custom collections and custom docs forms.

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

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, 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.