---
title: "defineContentPlugin()"
description: "Author a plugin that adds typed methods to the Content instance."
canonical_url: "https://content.comark.dev/reference/plugins/define-content-plugin"
---
# defineContentPlugin()

> Author a plugin that adds typed methods to the Content instance.

## `defineContentPlugin(factory)`

Defines a plugin. The factory receives the plugin's options and returns a `{ name, setup }` object; `setup` receives the [`ContentPluginContext`](#contentplugincontext) and returns the methods to merge onto the Content instance. `name` identifies the plugin on the instance; a second plugin with the same name is ignored.

**Parameters:**

- `factory`: `(options?: TOptions) => { name: string, setup: (content: ContentPluginContext) => TMethods | void }`.

**Returns:** a plugin factory `(...args) => `[`ContentPlugin`](https://content.comark.dev/reference/types/plugins#contentplugin)`<TMethods>` to pass to [`comarkContent({ plugins })`](https://content.comark.dev/reference/content/comark-content). The returned methods are typed onto the instance.

```ts [plugin.ts]
import { defineContentPlugin } from 'comark-content'

export default defineContentPlugin<{ suffix?: string }>((options) => ({
  name: 'hello',
  setup(content) {
    content.hooks.hook('file:upsert', (source, key) => {
      console.log('indexed', source, key)
    })
    return {
      hello: () => `hello${options?.suffix ?? ''}`,
    }
  },
}))
```

## `ContentPluginContext`

The `content` handle passed to a plugin's `setup`. It exposes the manifest, cache, hooks, and registration helpers.

| Member             | Type                                                                                                                   | Description                                                                                                                                                                                               |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`             | `string`                                                                                                               | The [instance name](https://content.comark.dev/reference/content/comark-content#name). Namespace anything a plugin stores with it.                                                                        |
| `options`          | [`ContentOptions`](https://content.comark.dev/reference/types/content#contentoptions)                                  | The resolved options the Content instance was created with.                                                                                                                                               |
| `hooks`            | `Hookable<`[`ContentHooks`](https://content.comark.dev/reference/types/content#contenthooks)`>`                        | Subscribe to content-change events.                                                                                                                                                                       |
| `cache`            | [`Cache`](https://content.comark.dev/reference/types/content#cache)                                                    | The resolved cache.                                                                                                                                                                                       |
| `__manifest__`     | [`Manifest`](https://content.comark.dev/reference/types/content#manifest)                                              | The **live** in-memory index, read synchronously.                                                                                                                                                         |
| `logger`           | [`Logger`](https://content.comark.dev/reference/types/content#logger)                                                  | Logger for plugin diagnostics; respects `ContentOptions.logger`.                                                                                                                                          |
| `onError`          | [`OnErrorMode`](https://content.comark.dev/reference/types/content#onerrormode)                                        | Default reaction to parse/validation failures.                                                                                                                                                            |
| `perf`             | [`Perf`](https://content.comark.dev/reference/types/content#perf)                                                      | Timing recorder for [custom spans](https://content.comark.dev/reference/content/perf#custom-spans) — a no-op unless a [tracing plugin](https://content.comark.dev/plugins/built-in/tracing) is installed. |
| `setPerf`          | `(recorder: Perf) => void`                                                                                             | Install the recorder behind `content.perf` — for authoring a [custom tracing recorder](https://content.comark.dev/plugins/built-in/tracing#custom-recorders). First installed recorder wins.              |
| `init`             | `(opts?) => Promise<void>`                                                                                             | Trigger initialization.                                                                                                                                                                                   |
| `stat`             | `(key) => `[`ContentListFile`](https://content.comark.dev/reference/types/content#contentlistfiletdata)` \| undefined` | Look up one manifest entry.                                                                                                                                                                               |
| `getSource`        | `(name?) => `[`Source`](https://content.comark.dev/reference/types/content#source)` \| undefined`                      | The raw source, when the instance has one.                                                                                                                                                                |
| `snapshot`         | `() => Promise<`[`ParsedSnapshot`](https://content.comark.dev/reference/types/content#parsedsnapshot)`>`               | Every parsed file, bodies included.                                                                                                                                                                       |
| `addParser`        | `(extensions, parse) => void`                                                                                          | Register a [`Parser`](https://content.comark.dev/reference/types/content#parser) for new extensions.                                                                                                      |
| `addListingFields` | `(extensions, fields) => void`                                                                                         | Trim which `data` fields listings keep.                                                                                                                                                                   |
| `addServeHandler`  | `(section, handler) => void`                                                                                           | Add a custom section to [`handler()`](https://content.comark.dev/reference/content/handler).                                                                                                              |
| `update`           | `(file) => Promise<void>`                                                                                              | Store an already-parsed entry.                                                                                                                                                                            |
| `ingest`           | `(file) => Promise<void>`                                                                                              | Run `file:parsed` on a hand-built file, then store it.                                                                                                                                                    |
| `remove`           | `(key) => Promise<void>`                                                                                               | Drop an entry.                                                                                                                                                                                            |

::warning
Read the index through `__manifest__`, never the public [`manifest()`](https://content.comark.dev/reference/content/manifest) method. Hooks such as `file:bulk:load` fire **during** `init()`, and `manifest()` awaits initialization — awaiting it from a hook deadlocks.
::

## Usage

Adding a data endpoint plus the client method that reads it is the canonical pattern, so the client/server contract lives in one place. Use [`addServeHandler`](https://content.comark.dev/reference/content/add-serve-handler) to register a custom section on [`handler()`](https://content.comark.dev/reference/content/handler):

```ts [search-sections.ts]
import { defineContentPlugin } from 'comark-content'

export default defineContentPlugin(() => ({
  name: 'search-sections',
  setup(content) {
    content.addServeHandler('search-sections', () => jsonResponse(buildSearchSections(content)))
  },
}))
```

Register it with [`comarkContent({ plugins })`](https://content.comark.dev/reference/content/comark-content), then read it from the browser with a matching [`defineContentClientPlugin`](https://content.comark.dev/reference/plugins/define-content-client-plugin).


## Sitemap

See the full [sitemap](https://content.comark.dev/sitemap.md) for all pages.
