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, and this page is available as Markdown at https://rspress.rs/api/config/config-basic.md.
close
  • English
  • Basic config

    root

    • Type: string
    • Default: docs

    Specifies the docs root directory. For example:

    rspress.config.ts
    import { 
    function defineConfig<const Config extends UserConfig>(config: () => Promise<Config>): UserConfigAsyncFn (+1 overload)

    Define an async Rspress configuration function. Use this overload when you need to perform async operations during configuration, such as fetching remote data, reading files, or dynamically generating config.

    @paramconfig - An async function that returns the Rspress configuration.@returnsThe same async function (enables type checking and IDE autocompletion).@example
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig(async () => {
      const remoteConfig = await fetchConfig();
      return {
        title: remoteConfig.title,
      };
    });
    defineConfig
    } from '@rspress/core';
    export default
    function defineConfig(config: UserConfig): UserConfig (+1 overload)

    Define a static Rspress configuration object.

    @paramconfig - The Rspress configuration object.@returnsThe same configuration object (enables type checking and IDE autocompletion).@example
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      title: 'My Site',
    });
    defineConfig
    ({
    UserConfig.root?: string | undefined

    The root directory of the site.

    @default'docs'
    root
    : 'docs',
    });

    This option supports both relative and absolute paths. Relative paths are resolved from the current working directory (cwd).

    You can also pass the docs root as a CLI argument:

    rspress dev docs
    rspress build docs

    base

    • Type: string
    • Default: /

    Deployment base path. For example, if you plan to deploy your site to https://foo.github.io/bar/, then you should set base to "/bar/":

    rspress.config.ts
    import { 
    function defineConfig<const Config extends UserConfig>(config: () => Promise<Config>): UserConfigAsyncFn (+1 overload)

    Define an async Rspress configuration function. Use this overload when you need to perform async operations during configuration, such as fetching remote data, reading files, or dynamically generating config.

    @paramconfig - An async function that returns the Rspress configuration.@returnsThe same async function (enables type checking and IDE autocompletion).@example
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig(async () => {
      const remoteConfig = await fetchConfig();
      return {
        title: remoteConfig.title,
      };
    });
    defineConfig
    } from '@rspress/core';
    export default
    function defineConfig(config: UserConfig): UserConfig (+1 overload)

    Define a static Rspress configuration object.

    @paramconfig - The Rspress configuration object.@returnsThe same configuration object (enables type checking and IDE autocompletion).@example
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      title: 'My Site',
    });
    defineConfig
    ({
    UserConfig.base?: string | undefined

    Base path of the site.

    @default'/'
    base
    : '/bar/',
    });

    siteOrigin

    • Type: string
    • Default: ""

    The optional deployment origin of the site, for example https://foo.github.io.

    Rspress uses this value together with base when generated files need absolute URLs, such as sitemap.xml, llms.txt links, or plugin outputs. The full URL concatenation order is siteOrigin + base + routePath.

    If siteOrigin is not configured, Rspress uses base + routePath as the fallback.

    If your site is deployed to https://foo.github.io/bar/, set siteOrigin to "https://foo.github.io" and base to "/bar/":

    rspress.config.ts
    import { 
    function defineConfig<const Config extends UserConfig>(config: () => Promise<Config>): UserConfigAsyncFn (+1 overload)

    Define an async Rspress configuration function. Use this overload when you need to perform async operations during configuration, such as fetching remote data, reading files, or dynamically generating config.

    @paramconfig - An async function that returns the Rspress configuration.@returnsThe same async function (enables type checking and IDE autocompletion).@example
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig(async () => {
      const remoteConfig = await fetchConfig();
      return {
        title: remoteConfig.title,
      };
    });
    defineConfig
    } from '@rspress/core';
    export default
    function defineConfig(config: UserConfig): UserConfig (+1 overload)

    Define a static Rspress configuration object.

    @paramconfig - The Rspress configuration object.@returnsThe same configuration object (enables type checking and IDE autocompletion).@example
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      title: 'My Site',
    });
    defineConfig
    ({
    UserConfig.siteOrigin?: string | undefined

    Origin of the site, such as https://example.com.

    siteOrigin
    : 'https://foo.github.io',
    UserConfig.base?: string | undefined

    Base path of the site.

    @default'/'
    base
    : '/bar/',
    });

    title

    • Type: string
    • Default: "Rspress"

    Site title. Rspress uses this as the HTML page title. For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      title: 'My Site',
    });

    description

    • Type: string
    • Default: ""

    Site description. Rspress uses this as the HTML page description. For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      description: 'My Site Description',
    });

    icon

    • Type: string | URL
    • Default: ""

    Site icon. Rspress uses this path as the page icon. For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      icon: '/favicon.ico',
    });

    For a normal path, Rspress resolves the icon from the public directory. You can also use a CDN URL, the file:// protocol, or a URL object for a local absolute path.

    lang

    • Type: string
    • Default: "en"

    Default language of the site. See i18n for more details.

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      lang: 'en',
      locales: [
        {
          lang: 'en',
          // ...
        },
        {
          lang: 'zh',
          // ...
        },
      ],
    });

    locales

    • Type: Locale[]
    • Default: undefined

    Configures the supported languages and site information for each language.

    export interface Locale {
      lang: string;
      label: string;
      title?: string;
      description?: string;
    }
    FieldDescription
    langLanguage code. Must match the corresponding directory name under the docs root.
    labelDisplay text in the navbar language switcher.
    titleSite title for this language.
    descriptionSite description for this language.

    Set the top-level lang to one of these language codes to select the default language. Rspress omits the language prefix from the default language's routes.

    For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      lang: 'en',
      locales: [
        {
          lang: 'en',
          label: 'English',
          title: 'My Site',
          description: 'My site description',
        },
        {
          lang: 'zh',
          label: '简体中文',
          title: '站点标题',
          description: '站点描述',
        },
      ],
    });

    For the complete setup, see i18n. For language-specific theme options such as nav and sidebar, see themeConfig.locales.

    i18nSourcePath

    • Type: string
    • Default: path.join(cwd, 'i18n.json')

    Specifies the path of the i18n text data source file. By default, Rspress reads from i18n.json in the current working directory. For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    import path from 'path';
    
    export default defineConfig({
      i18nSourcePath: path.join(__dirname, 'config/i18n.json'),
    });
    Tip

    This has the same effect as placing an i18n.json at the project root. If you also configure i18nSource, the i18nSource will be merged with and take priority over the data loaded from i18nSourcePath.

    i18nSource

    • Type: Record<string, Record<string, string>> | ((value: Record<string, Record<string, string>>) => Record<string, Record<string, string>> | Promise<Record<string, Record<string, string>>>)
    • Default: {}

    Use this option to modify Rspress's built-in i18n text or add text for custom components. It is usually used together with useI18n.

    Tip

    This has the same implementation and effect as i18n.json. You can use either one. i18nSource has higher priority than i18n.json and supports functions.

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

    Here is an example of modifying Rspress's built-in i18n text:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    export default defineConfig({
      i18nSource: {
        editLinkText: {
          en: '📝 Edit this page on Gitlab',
          zh: '📝 在 Gitlab 上编辑此页',
        },
      },
    });

    i18nSource can also be a function, for example:

    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      i18nSource: async source => {
        for (const key of Object.keys(source)) {
          source[key]['en_US'] = source[key]['en'];
        }
        return source;
      },
    });

    Here are the built-in i18n texts in Rspress:

    import type { I18nText } from '@rspress/core';
    
    // cspell:disable
    export const DEFAULT_I18N_TEXT = {
      languagesText: {
        zh: '语言',
        en: 'Languages',
        ja: '言語',
        ko: '언어',
        ru: 'Языки',
      },
      themeText: {
        zh: '主题',
        en: 'Theme',
        ja: 'テーマ',
        ko: '테마',
        ru: 'Тема',
      },
      versionsText: {
        zh: '版本',
        en: 'Versions',
        ja: 'バージョン',
        ko: '버전',
        ru: 'Версии',
      },
      menuTitle: {
        zh: '菜单',
        en: 'Menu',
        ja: 'メニュー',
        ko: '사이드바 메뉴',
        ru: 'Меню',
      },
      outlineTitle: {
        zh: '目录',
        en: 'ON THIS PAGE',
        ja: '目次',
        ko: '이 페이지 목차',
        ru: 'ОГЛАВЛЕНИЕ',
      },
      scrollToTopText: {
        en: 'Back to top',
        zh: '回到顶部',
        ja: 'トップに戻る',
        ko: '맨 위로',
        ru: 'Наверх',
      },
      lastUpdatedText: {
        en: 'Last Updated',
        zh: '最后更新于',
        ja: '最終更新',
        ko: '업데이트 날짜',
        ru: 'Последнее обновление',
      },
      lastUpdatedAuthorText: {
        en: 'by',
        zh: '作者',
        ja: '更新者',
        ko: '작성자',
        ru: 'автор',
      },
      prevPageText: {
        en: 'Previous page',
        zh: '上一页',
        ja: '前のページ',
        ko: '이전 페이지',
        ru: 'Предыдущая страница',
      },
      nextPageText: {
        en: 'Next page',
        zh: '下一页',
        ja: '次のページ',
        ko: '다음 페이지',
        ru: 'Следующая страница',
      },
      sourceCodeText: {
        en: 'Source Code',
        zh: '源码',
        ja: 'ソースコード',
        ko: '소스 코드',
        ru: 'Исходный код',
      },
      searchPlaceholderText: {
        en: 'Search',
        zh: '搜索',
        ja: '検索',
        ko: '검색',
        ru: 'Поиск',
      },
      searchPanelCancelText: {
        en: 'Cancel',
        zh: '取消',
        ja: 'キャンセル',
        ko: '취소',
        ru: 'Отмена',
      },
      searchNoResultsText: {
        en: 'No matching results',
        zh: '未找到与之匹配的结果',
        ja: '一致する結果が見つかりません',
        ko: '일치하는 결과가 없습니다',
        ru: 'Нет результатов, соответствующих запросу',
      },
      searchSuggestedQueryText: {
        en: 'Try searching for different keywords',
        zh: '试试搜索不同关键词',
        ja: '別のキーワードで検索してみてください',
        ko: '다른 키워드로 검색해 보세요',
        ru: 'Попробуйте поискать по другим ключевым словам',
      },
      'overview.filterNameText': {
        en: 'Filter',
        zh: '筛选',
        ja: 'フィルター',
        ko: '필터',
        ru: 'Фильтр',
      },
      'overview.filterPlaceholderText': {
        en: 'Search API',
        zh: '搜索 API',
        ja: 'API を検索',
        ko: 'API 검색',
        ru: 'API поиска',
      },
      'overview.filterNoResultText': {
        en: 'No matching API found',
        zh: '未找到匹配的 API',
        ja: '一致する API が見つかりません',
        ko: '일치하는 API가 없습니다',
        ru: 'Не найден подходящий API',
      },
      openInText: {
        en: 'Open in {{name}}',
        zh: '在 {{name}} 中打开',
        ja: '{{name}} で開く',
        ko: '{{name}}에서 열기',
        ru: 'Открыть в {{name}}',
      },
      copyMarkdownText: {
        en: 'Copy Markdown',
        zh: '复制 Markdown',
        ja: 'Markdown をコピー',
        ko: '마크다운 복사',
        ru: 'Скопировать Markdown',
      },
      copyMarkdownLinkText: {
        en: 'Copy Markdown link',
        zh: '复制 Markdown 链接',
        ja: 'Markdown リンクをコピー',
        ko: '마크다운 링크 복사',
        ru: 'Скопировать ссылку в формате Markdown',
      },
      editLinkText: {
        en: 'Edit this page',
        zh: '编辑此页面',
        ja: 'このページを編集',
        ko: '이 페이지 편집',
        ru: 'Отредактировать страницу',
      },
      codeButtonGroupCopyButtonText: {
        en: 'Copy code',
        zh: '复制代码',
        ja: 'コードをコピー',
        ko: '코드 복사',
        ru: 'Скопировать код',
      },
      codeButtonGroupWrapButtonText: {
        en: 'Toggle code wrap',
        zh: '切换代码换行',
        ja: 'コードの折り返しを切り替え',
        ko: '코드 줄바꿈 전환',
        ru: 'Переключить перенос кода',
      },
      notFoundText: {
        en: 'PAGE NOT FOUND',
        zh: '页面未找到',
        ja: 'ページが見つかりません',
        ko: '페이지를 찾을 수 없음',
        ru: 'СТРАНИЦА НЕ НАЙДЕНА',
      },
      takeMeHomeText: {
        en: 'Take me home',
        zh: '返回首页',
        ja: 'ホームに連れてって',
        ko: '홈으로 이동',
        ru: 'Вернуться на главную',
      },
    
      errorTitleText: {
        en: 'Something went wrong',
        zh: '页面出了点问题',
        ja: 'エラーが発生しました',
        ko: '문제가 발생했습니다',
        ru: 'Что-то пошло не так',
      },
      errorDescriptionText: {
        en: 'This page could not be loaded. Try reloading it or return to the home page.',
        zh: '页面未能正常加载,请尝试重新加载,或返回首页。',
        ja: 'ページを読み込めませんでした。再読み込みするか、ホームに戻ってください。',
        ko: '페이지를 불러올 수 없습니다. 새로고침하거나 홈으로 돌아가세요.',
        ru: 'Не удалось загрузить страницу. Попробуйте обновить её или вернуться на главную.',
      },
      reloadPageText: {
        en: 'Reload page',
        zh: '重新加载',
        ja: '再読み込み',
        ko: '새로고침',
        ru: 'Обновить страницу',
      },
      errorDetailsText: {
        en: 'Error details',
        zh: '错误详情',
        ja: 'エラーの詳細',
        ko: '오류 세부 정보',
        ru: 'Подробности ошибки',
      },
    
      promptCopyText: {
        en: 'Copy Prompt',
        zh: '复制 Prompt',
        ja: 'Prompt をコピー',
        ko: '프롬프트 복사',
        ru: 'Скопировать Prompt',
      },
      promptCopiedText: {
        en: 'Copied',
        zh: '已复制',
        ja: 'コピーしました',
        ko: '복사됨',
        ru: 'Скопировано',
      },
      promptExpandText: {
        en: 'Expand',
        zh: '展开',
        ja: '展開',
        ko: '펼치기',
        ru: 'Развернуть',
      },
      promptCollapseText: {
        en: 'Collapse',
        zh: '折叠',
        ja: '折りたたむ',
        ko: '접기',
        ru: 'Свернуть',
      },
    } as const satisfies Required<I18nText>;
    
    // cspell:enable
    

    logo

    • Type: string | { dark: string; light: string; width?: number; height?: number }
    • Default: ""

    Site logo. Rspress uses this path for the logo in the upper-left corner of the navbar. In the object form, optional width and height set the intrinsic dimensions (in pixels) for both images; use the source images' dimensions to reserve their aspect ratio and reduce layout shifts. For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      logo: '/logo.png',
    });

    Rspress resolves the logo from the public directory. You can also use a CDN URL.

    You can also set different logos for dark and light mode:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      logo: {
        dark: '/logo-dark.png',
        light: '/logo-light.png',
        width: 120,
        height: 32,
      },
    });

    logoHref

    • Type: string
    • Default: /${lang}/

    Custom link for the logo. By default, clicking the logo navigates to the homepage of the current language. For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      logo: '/logo.png',
      logoHref: 'https://example.com',
    });

    logoText

    • Type: string
    • Default: ""

    Site logo text. Rspress displays this text in the upper-left corner of the navbar. For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      logoText: 'rspress',
    });

    outDir

    • Type: string
    • Default: doc_build

    Custom output directory for built sites. For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      outDir: 'doc_build',
    });

    themeDir

    • Type: string
    • Default: theme

    Specifies the custom theme directory. By default, Rspress uses the theme directory under the current working directory as the custom theme directory. You can use themeDir to customize it. For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    import path from 'path';
    
    export default defineConfig({
      themeDir: path.join(__dirname, 'my-theme'),
    });

    This option supports both relative and absolute paths. Relative paths are resolved from the current working directory.

    For more details on custom themes, see Custom Theme.

    • Type: string | [string, Record<string, string>] | (route) => string | [string, Record<string, string>] | undefined
    • Can be appended per page via frontmatter

    Adds extra elements to the page's HTML <head> in production builds.

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      // ... other user config
      head: [
        '<meta name="author" content="John Doe">',
        // or
        ['meta', { name: 'author', content: 'John Doe' }],
        // [htmlTag, { attrName: attrValue, attrName2: attrValue2 }]
        // or
        route => {
          if (route.routePath.startsWith('/jane/'))
            return "<meta name='author' content='Jane Doe'>";
          if (route.routePath.startsWith('/john/'))
            return ['meta', { name: 'author', content: 'John Doe' }];
          // or even skip returning anything
          return undefined;
        },
      ],
    });

    globalStyles

    • Type: string
    • Default: undefined

    Adds global styles from a style file path. For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    import path from 'path';
    
    export default defineConfig({
      globalStyles: path.join(__dirname, 'styles/global.css'),
    });
    styles/global.css
    :root {
      --rp-c-brand: #f00;
    }

    sitemap

    • Type: boolean | SitemapOptions
    • Default: true

    Generate sitemap.xml in the output directory during production builds. This feature is built into Rspress and does not require a plugin. It also works when ssg is false. Existing sitemap files copied from the public directory are preserved. Generated URLs follow route.cleanUrls.

    Configure siteOrigin so the sitemap contains absolute URLs. Rspress combines siteOrigin, base, and each page's route path:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      siteOrigin: 'https://example.com',
      base: '/docs/',
      // sitemap is enabled by default.
    });

    Set sitemap: false to disable generation, or pass an options object to customize it:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      siteOrigin: 'https://example.com',
      sitemap: {
        defaultChangeFreq: 'weekly',
        defaultPriority: '0.7',
      },
    });

    The options have the following type, exported as SitemapOptions from @rspress/core:

    type ChangeFreq =
      'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
    
    type Priority =
      | '0.0'
      | '0.1'
      | '0.2'
      | '0.3'
      | '0.4'
      | '0.5'
      | '0.6'
      | '0.7'
      | '0.8'
      | '0.9'
      | '1.0';
    
    // https://www.sitemaps.org/protocol.html
    interface Sitemap {
      loc: string;
      lastmod?: string;
      changefreq?: ChangeFreq;
      priority?: Priority;
    }
    
    interface CustomMaps {
      [routePath: string]: Sitemap;
    }
    
    export interface SitemapOptions {
      siteUrl?: string;
      customMaps?: CustomMaps;
      defaultPriority?: Priority;
      defaultChangeFreq?: ChangeFreq;
    }

    sitemap.siteUrl

    • Type: string
    • Default: siteOrigin + base, or base when siteOrigin is not configured

    Override the deployment URL used in sitemap entries. Use an absolute URL that includes the base path, such as https://example.com/docs/. This value takes precedence over siteOrigin and base. Only HTTP(S) URLs without query strings or fragments are accepted.

    If neither sitemap.siteUrl nor siteOrigin is configured, entries use base + routePath and remain relative paths. Configure either value to generate absolute sitemap URLs.

    sitemap.customMaps

    • Type: Record<string, Sitemap>
    • Default: {}

    Override sitemap values for individual pages. Keys are route paths without base, and values override the generated loc, lastmod, changefreq, and priority. By default, lastmod is the source file's modification time. This option customizes existing pages; it does not add routes.

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      siteOrigin: 'https://example.com',
      base: '/docs/',
      sitemap: {
        customMaps: {
          '/guide': {
            loc: 'https://example.com/docs/guide',
            lastmod: '2026-01-01',
            changefreq: 'weekly',
            priority: '0.8',
          },
        },
      },
    });

    sitemap.defaultChangeFreq

    • Type: ChangeFreq
    • Default: 'monthly'

    The default changefreq value for each page. Available values are 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', and 'never'. Use customMaps to override it for a specific page.

    sitemap.defaultPriority

    • Type: Priority
    • Default: '0.5'

    The default priority value for each page, from '0.0' to '1.0' in increments of 0.1. The root route / uses '1.0'. Use customMaps to override it for a specific page.

    mediumZoom

    • Type: boolean | { selector?: string }
    • Default: true

    Controls whether image zoom is enabled. It is enabled by default; set mediumZoom to false to disable it.

    Image zoom is implemented with the medium-zoom library.

    Example usage:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      // Turn off image zoom
      mediumZoom: false,
      // Configure the CSS selector for images that can be zoomed. The default is '.rspress-doc img'
      mediumZoom: {
        selector: '.rspress-doc img',
      },
    });
    • Type:
    type SearchOptions = {
      searchHooks?: string;
      versioned?: boolean;
      codeBlocks?: boolean;
    };
    Tip

    To exclude an individual page from the search index, set search: false in its frontmatter.

    searchHooks

    • Type: string
    • Default: undefined

    Use searchHooks to add runtime hooks for search. For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    import path from 'path';
    
    export default defineConfig({
      search: {
        searchHooks: path.join(__dirname, 'searchHooks.ts'),
      },
    });

    For specific hook logic, you can read Customize Search Functions.

    versioned

    • Type: boolean
    • Default: true

    When using multiVersion, a separate search index is created for each version by default, so that search results only include pages from the version the user is currently viewing. Set versioned to false to disable this behavior and include all versions in search results.

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      search: {
        versioned: false,
      },
    });

    codeBlocks

    • Type: boolean
    • Default: true

    Whether to include code block content in the search index, which allows users to search code blocks.

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      search: {
        codeBlocks: false,
      },
    });

    globalUIComponents

    • Type: (string | [string, object])[]
    • Default: []

    You can register global UI components through the globalUIComponents parameter, for example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    import path from 'path';
    
    export default defineConfig({
      globalUIComponents: [path.join(__dirname, 'components', 'MyComponent.tsx')],
    });

    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';
    
    export default defineConfig({
      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.

    multiVersion

    • Type: { default: string; versions: string[] }

    Enable multi-version support with multiVersion. For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      multiVersion: {
        default: 'v1',
        versions: ['v1', 'v2'],
      },
    });

    The default parameter is the default version, and the versions parameter is the version list.

    route

    • Type: Object

    Custom route config.

    route.include

    • Type: string[]
    • Default: []

    Adds extra files to the route table. By default, only files in the docs root are included. For example:

    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      route: {
        include: ['other-dir/**/*.{md,mdx}'],
      },
    });

    Note: Strings in the array support glob patterns. The glob expression should be relative to the docs root and include the relevant file extensions.

    Note

    For more flexible page routes and file/content mapping, we recommend using the addPages hook in a custom Rspress plugin.

    route.exclude

    • Type: string[]
    • Default: []

    Exclude some files from the route. For example:

    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      route: {
        exclude: ['custom.tsx', 'component/**/*'],
      },
    });

    Note: Strings in the array support glob patterns. The glob expression should be relative to the docs root.

    route.excludeConvention

    • Type: string[]
    • Default: ['**/_[^_]*']

    A routing convention that makes it easier to keep components in the docs directory. By default, files starting with _ are excluded.

    If you really need some routes starting with _, you can adjust this rule, for example, set it to exclude only files starting with _fragment-:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      route: {
        excludeConvention: ['**/_fragment-*'],
      },
    });

    route.extensions

    • Type: string[]
    • Default: ['.js', '.jsx', '.ts', '.tsx', '.md', '.mdx']

    File extensions to include in the route table. By default, Rspress includes all 'js', 'jsx', 'ts', 'tsx', 'md', and 'mdx' files. To customize the extensions, use this option:

    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      route: {
        extensions: ['.md', '.mdx'],
      },
    });

    route.cleanUrls

    • Type: Boolean
    • Default: true (false before v2.1.0)

    Generates URLs without file extensions. Set cleanUrls to false to keep the .html suffix.

    Server Support Required

    Enabling this may require additional configuration on your hosting platform. For it to work, your server must be able to serve /foo.html when visiting /foo without a redirect.

    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      route: {
        cleanUrls: false,
      },
    });

    route.cleanUrlsRedirect

    • Type: Boolean
    • Default: true

    When enabled, Rspress normalizes non-canonical browser URLs during client startup, using the actual matched route as the source of truth. The target format follows route.cleanUrls.

    route.cleanUrls controls the preferred URL format used by generated links, while route.cleanUrlsRedirect only normalizes the browser address bar.

    Client-side fallback

    This option runs after the requested page HTML and client runtime have loaded. It uses history.replaceState and does not return an HTTP 301/308 response, so it cannot fully replace a server-side or CDN canonical redirect, especially for SEO. The hosting platform must still serve the correct Rspress page for the requested URL variant. Prefer a server-side redirect when available.

    With cleanUrls: true

    Regular page routes omit the trailing slash, while directory index routes retain it.

    Incoming URLMatched routeBrowser URL update
    /file/fileNo update
    /file.html/filereplaceState to /file
    /file//filereplaceState to /file
    /file/index/filereplaceState to /file
    /file/index.html/filereplaceState to /file
    /folder/folder/replaceState to /folder/
    /folder.html/folder/replaceState to /folder/
    /folder//folder/No update
    /folder/index/folder/replaceState to /folder/
    /folder/index.html/folder/replaceState to /folder/

    With cleanUrls: false

    Regular page routes use .html, while directory index routes use /index.html.

    Incoming URLMatched routeBrowser URL update
    /file/filereplaceState to /file.html
    /file.html/fileNo update
    /file//filereplaceState to /file.html
    /file/index/filereplaceState to /file.html
    /file/index.html/filereplaceState to /file.html
    /folder/folder/replaceState to /folder/index.html
    /folder.html/folder/replaceState to /folder/index.html
    /folder//folder/replaceState to /folder/index.html
    /folder/index/folder/replaceState to /folder/index.html
    /folder/index.html/folder/No update

    For example, both /zh/guide/start/introduction.html and /zh/guide/start/introduction/index.html match /zh/guide/start/introduction; the final URL follows the configured cleanUrls format without losing the locale prefix.

    The canonical URL formats align with Cloudflare's HTML handling. However, Cloudflare performs server-side HTTP redirects, while this option only updates the URL in the browser.

    Set cleanUrlsRedirect to false to disable browser URL normalization:

    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      route: {
        cleanUrlsRedirect: false,
      },
    });

    route.localeRedirect

    • Type: 'auto' | 'never' | 'only-default-lang'
    • Default: 'auto'

    Controls how first-time visitors are redirected to the closest configured locale based on window.navigator.language:

    • auto: Redirect from any locale to the closest configured locale.
    • never: Disable automatic locale redirects.
    • only-default-lang: Redirect only when the visitor opens the default locale.
    Prefer server-side redirects

    This option performs the redirect in the browser. For production sites, prefer handling locale negotiation and redirects on the server or at the CDN edge when possible. This redirects visitors before HTML is delivered and does not depend on client-side JavaScript.

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      route: {
        localeRedirect: 'never',
      },
    });

    route.useTransitions

    • Type: Boolean
    • Default: true

    Enable concurrent, optimized routing for internal links rendered by Rspress' default Link component. This covers links in markdown and MDX content, as well as default theme navigation links such as sidebar items.

    By default, this option is enabled. Internal page transitions are wrapped inside React's startTransition unless you explicitly set useTransitions to false. This prevents the heavy rendering of new page content from blocking user input, keeping the page responsive and interactive during navigation.

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      route: {
        useTransitions: false,
      },
    });
    • Type: Boolean
    • Default: true

    By default, Rspress' Link component prefetches resources for the matching route when users hover over internal links, and it applies the same behavior on touch devices. This is a performance optimization. Set this option to false to disable it.

    Tip

    In development, link prefetching is designed to work together with dev.lazyCompilation, which Rspress enables by default. Lazy compilation improves startup speed by compiling pages only when they are visited, while link prefetching starts compiling the target route on hover to reduce the wait when the target route is opened for the first time.

    Example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      route: {
        prefetchLink: false,
      },
    });

    ssg

    • Type: boolean | { experimentalWorker?: boolean; experimentalLoose?: boolean; }
    • Default: true

    Controls whether page content is rendered into HTML at build time. Rspress enables SSG by default.

    Set ssg: false to generate HTML shells for client-side rendering.

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      ssg: false,
    });
    Tip

    Both SSG and SSG-MD require source code to compile under SSR. Code that is incompatible with SSR will cause the build to fail. You can try:

    1. Make your code SSR-compatible. See Common issues and solutions in the SSG guide.

    2. If your code does not support SSR, set both ssg: false and llms: false:

      rspress.config.ts
      import { defineConfig } from '@rspress/core';
      
      export default defineConfig({
        ssg: false,
        llms: false,
      });

    experimentalWorker

    • Type: boolean
    • Default: false

    When enabled, Rspress uses workers to accelerate SSG and reduce memory usage. This is suitable for large documentation sites and is based on tinypool.

    experimentalExcludeRoutePaths

    • Type: (string | RegExp)[]
    • Default: []

    Excludes selected pages from SSG so they use CSR HTML directly. This can help large documentation sites bypass SSG errors on a small number of pages, but it is not recommended as a default choice.

    This option only affects SSG; it does not exclude pages from SSG-MD. If excluded pages are incompatible with SSR, make them SSR-compatible or set llms: false to disable SSG-MD.

    replaceRules

    • Type: { search: string | RegExp; replace: string; }[]
    • Default: []

    You can set text replacement rules for the entire site through replaceRules. The rules will apply to everything including _meta.json files, frontmatter configurations, and document content and titles.

    rspress.config.ts
    export default {
      replaceRules: [
        {
          search: /foo/g,
          replace: 'bar',
        },
      ],
    };

    languageParity

    • Type: Object

    Scans md and mdx files in the docs root to detect missing language versions and protect language parity.

    languageParity.enabled

    • Type: boolean
    • Default: false

    Whether to enable language parity checks.

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      languageParity: {
        enabled: true,
      },
    });

    languageParity.include

    • Type: string[]
    • Default: []

    Specifies which folders to check. By default, all files in the docs root are checked. Paths should be relative to each language directory. For example:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      languageParity: {
        // `posts/foods` and `articles` folders under the zh/en language directories
        include: ['posts/foods', 'articles'],
      },
    });

    languageParity.exclude

    • Type: string[]
    • Default: []

    Excludes certain folders and files from the checks.

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    
    export default defineConfig({
      languageParity: {
        exclude: ['excluded-directory', 'articles/secret.md'],
      },
    });