---
title: "Page Actions"
description: "Add \"Open in LLM\" and \"Copy Markdown\" buttons to your doc pages"
canonical_url: "https://docs.farming-labs.dev/docs/customization/page-actions"
markdown_url: "https://docs.farming-labs.dev/docs/customization/page-actions.md"
last_updated: "2018-10-20"
agent:
  tokenBudget: 900
  task: "Configure Copy Markdown and Open in LLM actions for docs pages."
  outcome: "The selected actions appear in the intended position and produce canonical Markdown or provider URLs for the current page."
  appliesTo:
    framework:
      - "nextjs"
      - "tanstackstart"
      - "sveltekit"
      - "astro"
      - "nuxt"
    version:
      - ">=0.2.60"
    package:
      - "@farming-labs/docs"
  prerequisites:
    - "Machine-readable Markdown routes work for the docs entry."
    - "Configure github.url before using provider templates that require a GitHub source URL."
  files:
    - "docs.config.ts"
    - "docs.config.tsx"
    - "src/lib/docs.config.ts"
  sideEffects:
    - "Open in LLM can navigate users to an external provider with the configured prompt and page URL."
    - "Custom copy callbacks can emit analytics for copied documentation content."
  verification:
    - description: "Open a docs page, copy Markdown, and exercise each configured external provider action."
      expect: "Copied text matches the configured format and every provider URL contains the canonical current-page target."
  rollback:
    - "Disable pageActions or restore the previous provider, alignment, and copy settings."
  failureModes:
    - symptom: "Copy Markdown returns HTML or an empty response."
      resolution: "Verify the page .md route and shared docs API Markdown format before changing the button."
    - symptom: "A provider opens with an unresolved template token."
      resolution: "Use only documented URL template variables and configure github.url when githubUrl is required."
---

# Page Actions
URL: /docs/customization/page-actions
LLM index: /llms.txt
Description: Add "Open in LLM" and "Copy Markdown" buttons to your doc pages
Related: /docs/configuration, /docs/customization/agent-primitive, /docs/customization/ai-chat, /docs/customization/mcp

<!-- farming-labs:agent-contract:start -->
## Agent Contract

Task: Configure Copy Markdown and Open in LLM actions for docs pages.
Outcome: The selected actions appear in the intended position and produce canonical Markdown or provider URLs for the current page.

### Applies To

- Framework: `nextjs`, `tanstackstart`, `sveltekit`, `astro`, `nuxt`
- Version: `>=0.2.60`
- Package: `@farming-labs/docs`

### Prerequisites

- Machine-readable Markdown routes work for the docs entry.
- Configure github.url before using provider templates that require a GitHub source URL.

### Files

- `docs.config.ts`
- `docs.config.tsx`
- `src/lib/docs.config.ts`

### Side Effects

- Open in LLM can navigate users to an external provider with the configured prompt and page URL.
- Custom copy callbacks can emit analytics for copied documentation content.

### Verification

- Open a docs page, copy Markdown, and exercise each configured external provider action.
  - Expected: Copied text matches the configured format and every provider URL contains the canonical current-page target.

### Rollback

- Disable pageActions or restore the previous provider, alignment, and copy settings.

### Failure Modes

- Copy Markdown returns HTML or an empty response. — Recovery: Verify the page .md route and shared docs API Markdown format before changing the button.
- A provider opens with an unresolved template token. — Recovery: Use only documented URL template variables and configure github.url when githubUrl is required.
<!-- farming-labs:agent-contract:end -->

# Page Actions

Edit top-level `pageActions` in `docs.config.ts` or `docs.config.tsx`. Enable
`copyMarkdown` for clipboard output and `openDocs` for provider links; prefer
`openDocs.target: "markdown"` so the prompt receives the current machine-readable page. Configure
top-level `github` before using the `github` target or `{githubUrl}` template value.

First verify the page's `.md` route, then copy Markdown and open every configured provider from that
page. If copying returns HTML or an empty body, repair the Markdown route rather than the button. If
a provider URL contains an unresolved token, use only the documented template placeholders and
check the required `github.url`. To remove both actions, delete `pageActions` or set both
`copyMarkdown: false` and `openDocs: false`.

Page actions are buttons rendered above or below the page title. They let users interact with page content — copy it as Markdown, or open it in an LLM provider like ChatGPT or Claude.

## Quick Start

```ts title="docs.config.ts"
pageActions: {
  copyMarkdown: { enabled: true },
  openDocs: { enabled: true },
}
```

This adds two buttons: **Copy Markdown** and an **Open in...** dropdown.

## Configuration Reference

All options go inside the `pageActions` object in `docs.config.ts`:

```ts title="docs.config.ts"
export default defineDocs({
  pageActions: {
    // ... options
  },
});
```

---

## `pageActions.position`

Where to render the page action buttons relative to the page title.

| Type                             | Default         |
| -------------------------------- | --------------- |
| `"above-title" \| "below-title"` | `"below-title"` |

```ts
pageActions: {
  position: "above-title",
}
```

<Callout type="info" title="Reading time follows this slot">
  If reading time is active for the current page, the read-time label stays attached to the same
  title-area slot. `above-title` places it directly under the action row. `below-title` keeps it
  grouped in the below-title metadata area. This also applies when a page opts in with frontmatter
  like `readingTime: true` or `readingTime: 8`.
</Callout>

---

## `pageActions.alignment`

Control whether the action row is left- or right-aligned.

| Type                  | Default  |
| --------------------- | -------- |
| `"left" \| "right"` | `"left"` |

```ts title="docs.config.ts"
pageActions: {
  alignment: "right",
}
```

---

## Copy Markdown

### `pageActions.copyMarkdown`

Whether to show the "Copy Markdown" button. Copies the current page's content as Markdown to the clipboard.

| Type                              | Default |
| --------------------------------- | ------- |
| `boolean \| { enabled: boolean }` | `false` |

```ts
pageActions: {
  copyMarkdown: true,
  // or
  copyMarkdown: { enabled: true },
}
```

The object form also lets you customize the button text.

### `pageActions.copyMarkdown.label`

Button label shown before the page has been copied.

| Type     | Default        |
| -------- | -------------- |
| `string` | `"Copy page"` |

### `pageActions.copyMarkdown.copiedLabel`

Button label shown after a successful copy.

| Type     | Default      |
| -------- | ------------ |
| `string` | `"Copied!"` |

### `pageActions.copyMarkdown.format`

Content format that the button copies to the clipboard.

| Type                       | Default        |
| -------------------------- | -------------- |
| `"markdown" \| "text"` | `"markdown"` |

- `"markdown"` — fetches the page's public `.md` route and copies its markdown source.
- `"text"` — reads the visible text content of the rendered page without a network request.

```ts
pageActions: {
  copyMarkdown: { enabled: true, format: "text" },
}
```
```ts
pageActions: {
  copyMarkdown: { enabled: true, label: "Copy docs", copiedLabel: "Copied docs" },
}
```

### `pageActions.copyMarkdown.includeTitle`

Whether to prepend the current page title to the copied content.

| Type      | Default |
| --------- | ------- |
| `boolean` | `false` |

When enabled:
- In `"markdown"` format a `# Title` heading is added before the page content.
- In `"text"` format the plain title is prepended as a first line.

The title is not added if the content already begins with it.

```ts
pageActions: {
  copyMarkdown: { enabled: true, includeTitle: true },
}
```
---

## Open in LLM

The **Open in...** dropdown lets users send the current page to an LLM or tool. Built-in providers can target the public `.md` route, the rendered page, the source `.mdx` URL, or the GitHub edit URL.

### `pageActions.openDocs`

Enable the "Open in..." dropdown. Can be a boolean or an object with additional configuration.

| Type                        | Default |
| --------------------------- | ------- |
| `boolean \| OpenDocsConfig` | `false` |

```ts
pageActions: {
  openDocs: true,
}
```

When set to `true`, the built-in provider list is used: **ChatGPT** and **Claude**.

### `pageActions.openDocs.enabled`

Whether to show the "Open in..." dropdown.

| Type      | Default |
| --------- | ------- |
| `boolean` | `false` |

### `pageActions.openDocs.providers`

Custom list of LLM / tool providers to show in the dropdown. Use provider strings for the built-in presets, or objects when you need icons, labels, per-provider prompts, or a custom URL template.

| Type                 | Default           |
| -------------------- | ----------------- |
| `OpenDocsProvider[]` | Built-in defaults |

```ts title="docs.config.ts"
pageActions: {
  openDocs: {
    enabled: true,
    target: "markdown",
    providers: ["chatgpt", "claude", "cursor"],
  },
}
```

Built-in provider ids are `"chatgpt"`, `"claude"`, `"cursor"`, `"gemini"`, `"copilot"`, `"perplexity"`, and `"github"`.

### `pageActions.openDocs.target`

Controls which URL is inserted into `{url}` for the built-in provider prompt.

| Value        | Used for                                                        |
| ------------ | --------------------------------------------------------------- |
| `"markdown"` | Public `.md` route for the page. This is the default.           |
| `"page"`     | Rendered docs page URL.                                         |
| `"source"`   | Source-style `.mdx` URL.                                        |
| `"github"`   | GitHub edit URL, when the top-level `github` config is present. |

### `pageActions.openDocs.prompt`

Prompt text sent to built-in providers. It defaults to:

```ts
"Read this documentation: {url}"
```

You can make the handoff more specific:

```ts title="docs.config.ts"
pageActions: {
  openDocs: {
    enabled: true,
    target: "markdown",
    prompt: "Use this documentation while editing the codebase: {url}",
    providers: ["chatgpt", "claude", "perplexity", { id: "cursor", mode: "app" }],
  },
}
```

<Callout type="info" title="Agent-ready docs links">
  `target: "markdown"` sends providers to the public `.md` route for the current page. That route can
  return a sibling `agent.md` when the page has one. In Next.js, HTTP clients can also request the
  normal page URL with `Accept: text/markdown`, or send `Signature-Agent` when they identify
  themselves as an agent. See [Agent Primitive](/docs/customization/agent-primitive).
</Callout>

### Provider Objects

Provider objects can customize a preset while keeping its built-in URL:

```tsx title="docs.config.tsx"
import { SiClaude, SiOpenai } from "react-icons/si";

pageActions: {
  openDocs: {
    enabled: true,
    target: "markdown",
    providers: [
      { id: "chatgpt", name: "ChatGPT", icon: <SiOpenai className="size-4" /> },
      { id: "claude", name: "Claude", icon: <SiClaude className="size-4" /> },
      {
        id: "cursor",
        mode: "app",
        prompt: "Open this docs page in Cursor context: {url}",
      },
    ],
  },
}
```

### Custom URL Templates

Use `urlTemplate` when you need a provider that is not built in. This keeps the previous API working.

```ts title="docs.config.ts"
pageActions: {
  openDocs: {
    enabled: true,
    providers: [
      {
        name: "Internal AI",
        urlTemplate: "https://internal.example/new?prompt={prompt}",
        prompt: "Read this documentation: {markdownUrl}",
      },
    ],
  },
}
```

The `urlTemplate` string supports these placeholders:

| Placeholder     | Replaced with                                                                 |
| --------------- | ----------------------------------------------------------------------------- |
| `{prompt}`      | The resolved prompt text                                                       |
| `{url}`         | The selected target URL, controlled by `target`                                |
| `{pageUrl}`     | The rendered docs page URL                                                     |
| `{markdownUrl}` | The public `.md` route for the page                                            |
| `{sourceUrl}`   | The source-style `.mdx` URL for the page                                       |
| `{mdxUrl}`      | Alias for `{sourceUrl}`                                                        |
| `{githubUrl}` | GitHub **edit** URL for the current page (same as "Edit on GitHub"). Requires `github` in config. Use `urlTemplate: "{githubUrl}"` so "Open in GitHub" opens the file on GitHub. |

<Callout type="info" title="Legacy URL templates still work">
  Existing providers that use `name` and `urlTemplate` are still supported. For custom URL
  templates, `{url}` keeps the previous page-URL behavior unless you explicitly set `target`.
  New configs should prefer `target: "markdown"` with provider strings.
</Callout>

## Full Example

```ts title="docs.config.ts"
export default defineDocs({
  pageActions: {
    position: "below-title",
    copyMarkdown: { enabled: true },
    openDocs: {
      enabled: true,
      target: "markdown",
      prompt: "Read this documentation: {url}",
      providers: ["chatgpt", "claude", "cursor"],
    },
  },
});
```

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
Docs-scoped sitemap: [/docs/sitemap.md](/docs/sitemap.md).
Well-known sitemap: [/.well-known/sitemap.md](/.well-known/sitemap.md).
