> For AI agents: the complete documentation index is available at https://rspress.rs/llms.txt, the full documentation bundle is available at https://rspress.rs/llms-full.txt.

# Plugin API

The previous section introduced the basic plugin structure. This page explains the plugin APIs and what each one can extend.

### globalStyles

- **Type**：`string`

Adds a global style file. Pass the absolute path of the style file:

```tsx title="plugin.ts"
import type { RspressPlugin } from '@rspress/core';
import path from 'path';

export function pluginForDoc(): RspressPlugin {
  // style path
  const stylePath = path.join(__dirname, 'some-style.css');
  return {
    // plugin name
    name: 'plugin-name',
    globalStyles: path.join(__dirname, 'global.css'),
  };
}
```

For example, if you want to modify the theme color, you can do so by adding a global style:

```css title="global.css"
:root {
  --rp-c-brand: #ffa500;
  --rp-c-brand-dark: #ffa500;
  --rp-c-brand-darker: #c26c1d;
  --rp-c-brand-light: #f2a65a;
  --rp-c-brand-lighter: #f2a65a;
}
```

### globalUIComponents

- **Type**：`(string | [string, object])[]`

Adds global components. Pass an array where each item is the absolute path of a component:

```tsx title="plugin.ts"
import type { RspressPlugin } from '@rspress/core';

export function pluginForDoc(): RspressPlugin {
  // component path
  const componentPath = path.join(__dirname, 'foo.tsx');
  return {
    // plugin name
    name: 'plugin-comp',
    // Path to global components
    globalUIComponents: [componentPath],
  };
}
```

Each `globalUIComponents` item can be either a component file path string or a tuple. In the tuple form, the first item is the component file path and the second item is the component props. For example:

```ts title="rspress.config.ts"
import { defineConfig } from '@rspress/core';
import type { RspressPlugin } from '@rspress/core';

export function pluginForDoc(): RspressPlugin {
  // component path
  const componentPath = path.join(__dirname, 'foo.tsx');
  return {
    // plugin name
    name: 'plugin-comp',
    globalUIComponents: [
      [
        path.join(__dirname, 'components', 'MyComponent.tsx'),
        {
          foo: 'bar',
        },
      ],
    ],
  };
}
```

When you register global components, Rspress automatically renders these React components in the theme without requiring manual imports.

Global components can implement many custom features, such as:

```tsx title="compUi.tsx"
import React from 'react';

// Need a default export
// Props come from your config
export default function PluginUI(props?: { foo: string }) {
  return <div>This is a global layout component</div>;
}
```

The component content is then rendered in the theme, for example to add a **BackToTop** button.

You can also use a global component to register side effects:

```tsx title="compSideEffect.tsx"
import { useEffect } from 'react';
import { useLocation } from '@rspress/core/runtime';

// Need a default export
export default function PluginSideEffect() {
  const { pathname } = useLocation();
  useEffect(() => {
    // Executed when the component renders for the first time
  }, []);

  useEffect(() => {
    // Executed when the route changes
  }, [pathname]);
  return null;
}
```

The component side effects then run in the theme. For example, side effects are useful for:

- Redirecting specific page routes.
- Binding click events on page `img` tags to implement image zoom.
- Reporting page view data when the route changes.

### builderConfig

- **Type**：`RsbuildConfig`

Rspress uses [Rsbuild](https://github.com/web-infra-dev/rsbuild) as its build tool. Configure Rsbuild through `builderConfig`. For specific configuration options, see [Rsbuild](https://rsbuild.rs/config/).

> To configure Rspack directly, use `builderConfig.tools.rspack`.

```tsx title="plugin.ts"
import type { RspressPlugin } from '@rspress/core';

export function pluginForDoc(slug: string): RspressPlugin {
  return {
    name: 'plugin-name',
    // Global variable definitions for build phase
    builderConfig: {
      source: {
        define: {
          SLUG: JSON.stringify(slug),
        },
      },
      tools: {
        rspack(options) {
          // Modify rspack config
        },
      },
    },
  };
}
```

> See [Build Config](https://rspress.rs/api/config/config-build.md) for more details.

### config

- **Type**：`(config: DocConfig, utils: ConfigUtils) => DocConfig | Promise<DocConfig>`

The type of `ConfigUtils` is as follows:

```ts
interface ConfigUtils {
  addPlugin: (plugin: RspressPlugin) => void;
  removePlugin: (pluginName: string) => void;
}
```

Modifies or extends the Rspress config itself. For example, use `config` to change the site title:

```tsx title="plugin.ts"
import type { RspressPlugin } from '@rspress/core';

export function pluginForDoc(): RspressPlugin {
  return {
    // Plugin name
    name: 'plugin-name',
    // Extend the Rspress config itself
    config(config) {
      return {
        ...config,
        title: 'New Document Title',
      };
    },
  };
}
```

To add or remove plugins, use `addPlugin` and `removePlugin`:

```tsx title="plugin.ts"
import type { RspressPlugin } from '@rspress/core';

export function pluginForDoc(): RspressPlugin {
  return {
    // Plugin name
    name: 'plugin-name',
    // Extend the config of Rspress itself
    config(config, utils) {
      // Add a plugin
      utils.addPlugin({
        name: 'plugin-name',
        // ... other config of the plugin
      });
      // Remove a plugin, pass in the name of the plugin
      utils.removePlugin('plugin-name');
      return config;
    },
  };
}
```

### beforeBuild/afterBuild

- **Type**：`(config: DocConfig, isProd: boolean) => void | Promise<void>`

Runs operations before or after the docs are built. The first parameter is the resolved docs config, and the second parameter indicates whether the current build is production:

```tsx title="plugin.ts"
import type { RspressPlugin } from '@rspress/core';

export function pluginForDoc(): RspressPlugin {
  return {
    name: 'plugin-name',
    // Hook to execute before build
    async beforeBuild(config, isProd) {
      // Do something here
    },
    // Hook to execute after build
    async afterBuild(config, isProd) {
      // Do something here
    },
  };
}
```

:::tip
When `beforeBuild` runs, all plugins' `config` hooks have already been processed, so the `config` parameter represents the final docs configuration.
:::

### markdown

- **Type**：`{ remarkPlugins?: Plugin[]; rehypePlugins?: Plugin[] }`

Extends Markdown/MDX compilation. Use `markdown` to add custom remark/rehype plugins or MDX `globalComponents`:

```tsx title="plugin.ts"
import type { RspressPlugin } from '@rspress/core';

export function pluginForDoc(): RspressPlugin {
  return {
    name: 'plugin-name',
    markdown: {
      remarkPlugins: [
        // Add custom remark plugin
      ],
      rehypePlugins: [
        // Add custom rehype plugin
      ],
      globalComponents: [
        // Register global components for MDX
      ],
    },
  };
}
```

### extendPageData

- **Type**: `(pageData: PageData) => void | Promise<void>`

```tsx title="plugin.ts"
import type { RspressPlugin } from '@rspress/core';

export function pluginForDoc(): RspressPlugin {
  return {
    name: 'plugin-name',
    // Extend the page data
    extendPageData(pageData, isProd) {
      // You can add or modify properties on the pageData object
      pageData.a = 1;
    },
  };
}
```

After extending the page data, you can access the page data through the `usePageData` hook in the theme.

```tsx
import { usePageData } from '@rspress/core/runtime';

export function MyComponent() {
  const { page } = usePageData();
  // page.a === 1
  return <div>{page.a}</div>;
}
```

### addPages

- **Type**: `(config: UserConfig) => AdditionalPage[] | Promise<AdditionalPage[]>`

The `config` parameter is the docs config from `rspress.config.ts`, and the `AdditionalPage` type is:

```tsx
interface AdditionalPage {
  routePath: string;
  filepath?: string;
  content?: string;
}
```

Adds additional pages. Return an array from `addPages`; each item is a page config. Use `routePath` to specify the page route, and use `filepath` or `content` to specify the page content. For example:

```tsx
import path from 'path';
import type { RspressPlugin } from '@rspress/core';

export function docPluginDemo(): RspressPlugin {
  return {
    name: 'add-pages',
    addPages(config, isProd) {
      return [
        //  Supports the absolute path of a real file (`filepath`) and reads md(x) content from disk
        {
          routePath: '/filepath-route',
          filepath: path.join(__dirname, 'blog', 'index.md'),
        },
        //  Supports directly passing md(x) content through the `content` parameter
        {
          routePath: '/content-route',
          content: '# Demo2',
        },
      ];
    },
  };
}
```

`addPages` accepts two parameters: `config` is the current documentation site config, and `isProd` indicates whether the current build is production.

### routeGenerated

- **Type**：`(routeMeta: RouteMeta[]) => void | Promise<void>`

This hook receives all route metadata. Each route metadata item has the following structure:

```ts
export interface RouteMeta {
  // route path
  routePath: string;
  // file absolute path
  absolutePath: string;
  // The page name, as part of the chunk filename
  pageName: string;
  // language of the current route
  lang: string;
}
```

Example:

```tsx title="plugin.ts"
import type { RspressPlugin } from '@rspress/core';

export function pluginForDoc(): RspressPlugin {
  return {
    // plugin name
    name: 'plugin-routes',
    // Hook to execute after route generated
    async routeGenerated(routes, isProd) {
      // Do something here
    },
  };
}
```

### addRuntimeModules

- **Type**: `(config: UserConfig, isProd: boolean) => Record<string, string> | Promise<Record<string, string>>;`

Adds additional runtime modules. For example, use `addRuntimeModules` to expose compile-time information to docs:

```tsx title="plugin.ts"
import type { RspressPlugin } from '@rspress/core';

export function pluginForDoc(): RspressPlugin {
  return {
    // Plugin name
    name: 'plugin-name',
    // Add additional runtime modules
    async addRuntimeModules(config, isProd) {
      const fetchSomeData = async () => {
        // Mock asynchronous request
        return { a: 1 };
      };
      const data = await fetchSomeData();
      return {
        'virtual-foo': `export default ${JSON.stringify(data)}`,
      };
    },
  };
}
```

You can then use the `virtual-foo` module in a runtime component:

```jsx
import myData from 'virtual-foo';

export function MyComponent() {
  return <div>{myData.a}</div>;
}
```

:::tip TIP

This hook is executed after the `routeGenerated` hook.

:::

### i18nSource

- **Type**: `(source: Record<string, Record<string, string>>) => Record<string, Record<string, string>> | Promise<Record<string, Record<string, string>>>`

Adds or modifies internationalization (i18n) text data. Use this hook to extend or override the theme's i18n text.

The `source` parameter is an object with the following structure:

```ts
{
  [textKey: string]: {
    [locale: string]: string;
  }
}
```

The first-level `textKey` is the text key, the second-level `locale` is the language code (for example, `zh` or `en`), and the value is the translated text for that language.

Usage example:

```tsx title="plugin.ts"
import type { RspressPlugin } from '@rspress/core';

export function pluginForDoc(): RspressPlugin {
  return {
    // Plugin name
    name: 'plugin-name',
    // Add or modify i18n text
    i18nSource(source) {
      // Add new text
      return {
        ...source,
        customKey: {
          zh: '自定义文案',
          en: 'Custom Text',
        },
        anotherKey: {
          zh: '另一个文案',
          en: 'Another Text',
        },
      };
    },
  };
}
```

If your plugin also provides runtime components, read these texts with the `useI18n` hook:

```tsx
import { useI18n } from '@rspress/core/runtime';

export function MyComponent() {
  const t = useI18n();
  return <div>{t('customKey')}</div>;
}
```
