close
  • English
  • Plugin API

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

    globalStyles

    • Typestring

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

    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:

    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:

    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:

    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:

    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:

    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

    • TypeRsbuildConfig

    Rspress uses Rsbuild as its build tool. Configure Rsbuild through builderConfig. For specific configuration options, see Rsbuild.

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

    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 for more details.

    config

    • Type(config: DocConfig, utils: ConfigUtils) => DocConfig | Promise<DocConfig>

    The type of ConfigUtils is as follows:

    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:

    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:

    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:

    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:

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

    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:

    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:

    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:

    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:

    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:

    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:

    import myData from 'virtual-foo';
    
    export function MyComponent() {
      return <div>{myData.a}</div>;
    }
    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:

    {
      [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:

    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:

    import { useI18n } from '@rspress/core/runtime';
    
    export function MyComponent() {
      const t = useI18n();
      return <div>{t('customKey')}</div>;
    }