--- url: https://rspress.rs/guide/start/introduction.md --- > 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. # Introduction Rspress is a React-based static site generator built on [Rsbuild](https://rsbuild.rs/). It ships with a default documentation theme so you can quickly build a documentation site, customize the theme for blogs or product homepages, and use official plugins for component library docs. ## Why Rspress Rspress is designed around the following core features: - **Build Performance**. Fast startup keeps the authoring experience smooth. - **AI-native**. Technical documentation not only serves human readers but can also be better understood and utilized by AI through SSG-MD. - **Theme and Customization**. A brand-new default theme with multiple customization layers, including CSS variables, BEM class names, re-export overrides, and eject. - **MDX Support**. MDX lets you reuse document fragments and render custom React components in docs. - **Documentation DX**. Continuous improvements for authoring with navigation metadata, code blocks, and dead link checks. - **Documentation Site Essentials**. Internationalization, multi-version docs, full-text search, component library docs, and more. - **Extensibility**. A built-in plugin system for extending Rspress through plugin APIs. These are also core requirements for static site development. The following sections cover them in detail. ### Build performance As projects grow, long startup times become a major drag on development. The longer a project lives, the more noticeable this cost becomes. We started from a simple question: can an SSG framework break through the performance limits of the existing JavaScript toolchain and deliver near-instant startup for most projects? Rspress was built to answer that question. Rspress achieves strong performance through multiple optimization strategies: - **`lazyCompilation`**. `lazyCompilation` compiles on-demand in dev mode. Pages are only compiled when you visit them, significantly improving development startup speed and even achieving millisecond-level cold starts. - **Route Preload**. When hovering over links, Rspress preloads target route resources ahead of time, pairing with `lazyCompilation` for a near-lossless dev experience. - **Persistent Cache**. For production builds, persistent cache is enabled by default, reusing previous compilation results during warm starts to improve build speed by 30%-60%. - **Rspack Bundler**. Rspress uses Rspack, the Rust-based bundler from the same team. Rspack includes optimizations such as multi-threaded parallel compilation and incremental compilation, making it 5 to 10 times faster than traditional JavaScript bundlers in many scenarios. Rspress also applies additional build optimizations internally. Combined with the Rust-powered front-end toolchain, these optimizations raise the performance ceiling for SSG frameworks. ### AI-native With the rise of large language models, technical documentation needs to serve not only human readers but also be better understood and utilized by AI. Rspress provides **SSG-MD** capability, which renders pages as Markdown files instead of HTML files and generates index files compliant with the [llms.txt](https://llmstxt.org/) specification. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ llms: true, }); ``` Once enabled, the build output will include `llms.txt` (an index file showing page titles and descriptions in navigation and sidebar order), `llms-full.txt` (a complete file containing Markdown content from all pages), and `.md` files corresponding to each route. For custom components, you can also use `import.meta.env.SSG_MD` to output AI-friendly plain text in SSG-MD mode, balancing interactive UX with higher-quality static information. Just as SSG generates static HTML to improve SEO, SSG-MD improves GEO (Generative Engine Optimization) and provides higher-quality static information for large language models. For detailed usage, see the [SSG-MD documentation](https://rspress.rs/guide/basic/ssg-md.md). Beyond build performance and AI-native capabilities, Rspress also provides a default theme, automatic layout generation, MDX, Shiki code highlighting, internationalization, multi-version docs, full-text search, and a plugin system. The following sections cover these capabilities in more detail. ### Default theme and customization Rspress provides a well-designed default theme with a strong reading experience and a high degree of customizability. #### Theme customization ```css /* Easily override component styles */ .rp-nav__title { height: 32px; } .rp-nav-menu__item--active { color: purple; } ``` The default theme exposes CSS variables for theme colors, code blocks, homepage components, and more. All built-in components follow the [BEM naming convention](https://getbem.com/), making styles easier to override with standard CSS selectors. If CSS is not enough, you can override built-in components through ESM re-exports in `theme/index.tsx`. #### `rspress eject` Command When CSS variables cannot meet your customization needs, you can use the `rspress eject` command to copy the source code of built-in components to your project's theme directory for complete customization. ```bash # Export nav component to theme directory npx rspress eject Nav ``` #### Navbar and sidebar tags Rspress provides a [Tag component](https://rspress.rs/ui/layout-components/tag.md). You can define `tag` in frontmatter and display those annotations in headings, the navbar, the sidebar, and the outline. ### Automatic layout generation Most documentation sites need these layout modules in addition to the main content: - Navbar for global navigation. - Sidebar for the page tree under the current nav item. - Outline for the heading structure of the current page. For the document outline, Rspress automatically extracts headings from the current page and displays them on the right side by default. For the navbar and sidebar, Rspress supports two configuration methods: - **Declarative config**. Configure the corresponding data by declaring `_meta.json` in the directory: ```json title="_meta.json" ["introduction", "install", "start"] ``` See [Autogenerated navigation](https://rspress.rs/guide/basic/auto-nav-sidebar.md) for details. - **Programmatic config**. Specify [nav](https://rspress.rs/api/config/config-theme.md#nav) and [sidebar](https://rspress.rs/api/config/config-theme.md#sidebar) directly in the Rspress config. We recommend declarative config for most sites because it: 1. Keeps the config file concise. 2. Makes the relationship between the file tree and sidebar tree more intuitive. 3. Lets you add or remove sidebar entries in the current directory instead of jumping back to `rspress.config.ts`. Programmatic config is useful when the navigation needs to be generated dynamically. For example, the official Rspress [TypeDoc plugin](https://rspress.rs/plugin/official-plugins/typedoc.md) converts TypeDoc JSON data into `nav` and `sidebar` config. ### MDX support MDX is a powerful content development format. You can not only write Markdown files as usual, but also use React components in the content of Markdown: ![](https://lf3-static.bytednsdoc.com/obj/eden-cn/uhbfnupenuhf/rspress/mdx-intro.png) In addition, Rspress also supports some specific syntax, such as: - Custom container syntax. - Frontmatter metadata definition. - Code line highlighting syntax. See [Use MDX](https://rspress.rs/guide/use-mdx/components.md) for details. ### Code highlighting with [Shiki](https://shiki.style/) Rspress uses [Shiki](https://shiki.style/) by default for code highlighting. Compared to runtime highlighting solutions, Shiki performs highlighting at compile time, achieving accurate syntax highlighting consistent with VS Code based on TextMate grammar, without adding runtime overhead or bundle size. You can customize code block color schemes through CSS variables, and interactively switch and preview different Shiki themes on the [CSS Variables](https://rspress.rs/ui/vars.md) page. Shiki also allows extensions through custom [transformers](https://shiki.style/guide/transformers) to enrich writing, such as [twoslash](https://twoslash.netlify.app/). ### Documentation DX Rspress also brings a more complete authoring experience: - Dead link checking is enabled by default and catches invalid links during builds. - File code blocks support `file="./path/to/file"` so examples can live in standalone source files. - The `preview` plugin now uses meta-based configuration and works better with file code blocks. - `preview` and `playground` can now be enabled together for component docs and interactive examples. For concrete `preview` and `playground` examples, see the [Component documentation](#component-documentation) section below. ### SSG Rspress is an SSG framework. During a production build, it generates static HTML for each page and writes the result to the output directory. You can deploy the generated output to any static hosting service, such as GitHub Pages, Netlify, or Vercel. Rspress also provides configuration for customizing the HTML generated by SSG. For details, see [Static Site Generation](https://rspress.rs/guide/basic/ssg.md). ### Internationalization (I18n) Internationalization is common for documentation sites. Rspress keeps i18n straightforward by modeling it around these tasks: - Define the i18n data source. - Configure the site for each language. - Organize docs for different languages. - Use i18n text in custom components. Rspress includes built-in translations for Chinese, English, Japanese, Korean, and more languages, with more to come. The system tree-shakes language text based on your configuration and usage, bundling only what you need. You can also extend or override translations through [`i18nSource`](https://rspress.rs/api/config/config-basic.md#i18nsource). You can follow the [I18n Tutorial](https://rspress.rs/guide/basic/i18n.md) to implement internationalization for your site step by step. ### Multi-version Some sites need to maintain docs for multiple product versions. Rspress has built-in multi-version support: enable it with a small config block, then organize versioned directories naturally without extra concepts. ```ts // config file import { defineConfig } from '@rspress/core'; export default defineConfig({ multiVersion: { default: 'v1', versions: ['v1', 'v2'], }, }); ``` ```tree // Directory structure docs ├── v1 │ ├── README.md │ └── guide │ └── README.md └── v2 ├── README.md └── guide ``` ### Full text search Rspress provides full-text search out of the box, with no configuration required. It is based on the open-source FlexSearch engine: ![](https://lf3-static.bytednsdoc.com/obj/eden-cn/uhbfnupenuhf/rspress/rspress-search.png) ### Custom theme Rspress supports two ways to customize themes: 1. Extend from the default theme. In each component of the default theme, many slots are provided for you to add custom layout content, for example: ```tsx // theme/index.tsx import { Layout as BasicLayout } from '@rspress/core/theme-original'; const Layout = () => Custom Block

} />; export { Layout }; export * from '@rspress/core/theme-original'; ``` 2. Fully customized theme. If you want to build a custom theme from scratch, customize the `Layout` content and use Rspress runtime APIs such as `usePageData` to access compile-time data, routing information, and more. For details about custom themes, see [Custom Theme](https://rspress.rs/guide/basic/custom-theme.md). ### Plugin system The plugin system is a core part of Rspress and lets you extend site build behavior. For details, see [Plugin Introduction](https://rspress.rs/plugin/system/introduction.md). ### Component documentation Rspress provides component preview and live editing through [@rspress/plugin-preview](https://rspress.rs/plugin/official-plugins/preview.md) and [@rspress/plugin-playground](https://rspress.rs/plugin/official-plugins/playground.md), which works well for component library docs and interactive examples. #### Component library demo preview Use the ` ```tsx preview ` syntax in mdx files: ````mdx ```tsx preview import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Current count: {count}

); } export default App; ``` ```` It renders as follows: ```tsx preview import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Current count: {count}

); } export default App; ``` If you prefer to keep demo code in external files, you can combine it with file code blocks. See [@rspress/plugin-preview](https://rspress.rs/plugin/official-plugins/preview.md) for details. #### Component library real-time playground Use the ` ```tsx playground ` syntax in mdx files: ````mdx ```tsx playground import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Current count: {count}

); } export default App; ``` ```` It renders as follows: ```tsx playground import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Current count: {count}

); } export default App; ``` For iframe preview mode, layout direction, and combining it with `preview`, see [@rspress/plugin-playground](https://rspress.rs/plugin/official-plugins/playground.md). ## Differences from other SSG frameworks ### Differences from Docusaurus [Docusaurus](https://docusaurus.io/ "Docusaurus") is an open-source SSG framework by Meta. Like Rspress, it uses React as the rendering framework and supports MDX. However, the main differences between Rspress and Docusaurus are: 1. Rspress provides better build performance through lazyCompilation and persistent cache, achieving millisecond-level cold starts. For details, see [Build Performance](#build-performance). 2. Rspress has simpler configuration and a lower learning curve. It avoids unnecessary concepts and reduces cognitive load where possible, with built-in search and intuitive multi-version docs. 3. Rspress provides a higher-level abstraction over the bundler. Low-level bundlers such as webpack and Rspack expose complex configuration. Docusaurus exposes the underlying bundler config directly, while Rspress offers simpler, user-friendly options. For example, you can add tags to `` through `builderConfig.html.tags` without registering a bundler plugin such as `html-webpack-plugin`. ### Differences from Nextra [Nextra](https://nextra.vercel.app/ "Nextra") is an open-source SSG framework by Vercel. Like Rspress, it also uses React as the rendering framework and supports MDX. The main differences between Rspress and Nextra are: 1. Rspress has better build performance. See "Differences from Docusaurus" for details. 2. Rspress is lighter overall. Nextra depends on Next.js, and its SSG pipeline is based on Next.js. Its output is therefore not pure HTML; it also includes Next.js runtime code. This increases output size and usually requires deployment as an application with `next start` rather than as a pure static site. Rspress is not tied to an application framework, so its output is lighter and can be deployed as a pure static site. ### Differences from VitePress [VitePress](https://vitepress.dev/ "VitePress") is a static site generator based on Vite. It is characterized by using Vue as the rendering framework and has excellent performance. The main differences between Rspress and VitePress are: 1. Rspress uses React as the rendering framework, while VitePress uses Vue. 2. Rspress uses MDX for content development, while VitePress uses Markdown and supports Vue components in Markdown, which also leads to differences in the implementation of the underlying compilation toolchain. 3. For build performance, both Rspress and VitePress can start quickly in development. In production, VitePress bundles with Rollup and faces similar performance limits to other JavaScript-based toolchains. Rspress is faster in this phase. ## Try Rspress Go to [Quick start](https://rspress.rs/guide/start/getting-started.md) to learn how to use Rspress to quickly build a documentation site. --- url: https://rspress.rs/guide/start/getting-started.md --- > 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. # Quick start For your Agent Start a Rspress project in one shot Copy this prompt and send it to your AI agent. It will scaffold a new Rspress site for you automatically. Copy Prompt Create a Rspress project by following the official quick start guide at https://rspress.rs/guide/start/getting-started.md. 1. Scaffold the project with `create rspress@latest`. 2. Install dependencies. 3. Start the dev server. ## Environment preparation Rspress supports using [Node.js](https://nodejs.org/), [Deno](https://deno.com/), or [Bun](https://bun.sh/) as the JavaScript runtime. Use one of the following installation guides to set up a runtime: - [Install Node.js](https://nodejs.org/en/download) - [Install Bun](https://bun.com/docs/installation) - [Install Deno](https://docs.deno.com/runtime/getting_started/installation/) :::tip Version requirements Rspress requires Node.js version 20.19+, 22.12+. ::: ## Online example You can try Rspress directly in [CodeSandbox](https://codesandbox.io/p/github/web-infra-dev/rspress-codesandbox-template/main). ## Create a Rspress project The recommended way to start a new Rspress project is to use the `create-rspress` scaffold: ```sh [npm] npm create rspress@latest ``` ```sh [yarn] yarn create rspress ``` ```sh [pnpm] pnpm create rspress@latest ``` ```sh [bun] bun create rspress@latest ``` ```sh [deno] deno init --npm rspress@latest ``` The scaffold will ask for the project name or path, whether to set up i18n, whether to create a `theme` folder for customization, and which optional tools or skills to add. By default, the scaffold initializes a Git repository in the generated project. Pass `--no-git` to skip Git initialization. After the project is created, follow the next steps printed in the terminal: ```bash cd rspress-project npm install npm run dev ``` The dev server will print the local URL after startup. Open it in your browser to view the generated documentation site. ### Templates Rspress provides the following built-in templates: | Template | Description | | ------------- | --------------------------------------------------------------------------- | | `basic` | Creates a minimal Rspress documentation site that uses the default theme. | | `basic-theme` | Creates a single-language site with a `theme` folder for customization. | | `i18n` | Creates a multilingual documentation site with English and Chinese content. | | `i18n-theme` | Creates a multilingual site with a `theme` folder for customization. | ### Optional tools During project creation, you can select optional tools for linting or formatting: | Tool | Purpose | | ---------- | -------------------------------------- | | `rslint` | Adds Rslint for linting. | | `eslint` | Adds ESLint for linting. | | `prettier` | Adds Prettier for formatting. | | `biome` | Adds Biome for linting and formatting. | ### Optional skills If you plan to maintain the documentation site with an AI agent, you can select optional Agent Skills during project creation. The CLI will generate a `.agents/skills` directory in your project and add the selected skills there. For most documentation sites, we recommend selecting: - [rspress-docs-generator](https://github.com/rstackjs/agent-skills#rspress-docs-generator): helps AI agents create and maintain Rspress documentation sites, especially when a monorepo keeps a dedicated Rspress project as its docs site. - [rspress-best-practices](https://github.com/rstackjs/agent-skills#rspress-best-practices): provides Rspress project structure, config, MDX, theme, and deployment guidance for AI agents. - [rspress-description-generator](https://github.com/rstackjs/agent-skills#rspress-description-generator): helps AI agents write and maintain page descriptions for SEO, search, and AI-readable outputs. If you choose the `basic-theme` or `i18n-theme` template, the following skill is selected by default: - [rspress-custom-theme](https://github.com/rstackjs/agent-skills#rspress-custom-theme): enables your AI agent to customize the Rspress theme, such as CSS variables, layout slots, and theme component overrides. These skills do not affect the runtime behavior of your Rspress site. They only provide local guidance for AI agents when editing or maintaining the project. If you do not use an AI agent, you can deselect them or press Enter to skip this option. For more information about Agent Skills and other AI-related capabilities, see [AI](https://rspress.rs/guide/start/ai.md). ### Current directory To create a project in the current directory, enter `.` as the project path when prompted: ```bash ◆ Create Rspress Project ◇ Project name or path │ . ``` If the current directory is not empty, the CLI will ask whether to continue and overwrite files. ### Non-interactive mode You can pass CLI options to create a project without interactive prompts: ```bash npx -y create-rspress@latest my-docs --template basic-theme --tools rslint,prettier ``` You can also scaffold the multilingual template: ```bash npx -y create-rspress@latest my-docs --template i18n ``` Or scaffold a multilingual site with a `theme` folder: ```bash npx -y create-rspress@latest my-docs --template i18n-theme ``` You can also add Agent Skills explicitly: ```bash npx -y create-rspress@latest my-docs --template basic-theme --skill rspress-docs-generator,rspress-best-practices,rspress-description-generator ``` All CLI flags supported by `create-rspress`: ```bash Usage: create-rspress [dir] [options] Options: -h, --help display help for command -d, --dir create project in specified directory -t, --template specify the template to use --no-git skip Git repository initialization --tools add additional tools, comma separated --skill add optional skills, comma separated --override override files in target directory --packageName specify the package name --template-version specify the npm template version Available templates: basic, basic-theme, i18n, i18n-theme Optional tools: eslint, rslint, biome, prettier Optional skills: rspress-docs-generator, rspress-best-practices, rspress-custom-theme, rspress-description-generator ``` ## Manual setup If you want to add Rspress to an existing project or create the minimal files yourself, start by creating a directory: ```bash mkdir rspress-app && cd rspress-app ``` Initialize a `package.json`: ```bash npm init -y ``` Install Rspress: ```sh [npm] npm install @rspress/core -D ``` ```sh [yarn] yarn add @rspress/core -D ``` ```sh [pnpm] pnpm add @rspress/core -D ``` ```sh [bun] bun add @rspress/core -D ``` ```sh [deno] deno add npm:@rspress/core -D ``` Create the first document: ```bash mkdir docs && echo '# Hello world' > docs/index.md ``` Add the following scripts to `package.json`: ```json { "scripts": { "dev": "rspress dev", "build": "rspress build", "preview": "rspress preview" } } ``` Create a configuration file: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ root: 'docs', }); ``` Create `tsconfig.json`: ```json { "compilerOptions": { "lib": ["DOM", "ES2023"], "jsx": "react-jsx", "target": "ES2023", "noEmit": true, "skipLibCheck": true, "useDefineForClassFields": true, /* modules */ "module": "ESNext", "moduleDetection": "force", "moduleResolution": "bundler", "verbatimModuleSyntax": true, "resolveJsonModule": true, "allowImportingTsExtensions": true, "noUncheckedSideEffectImports": true, "isolatedModules": true, /* type checking */ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true }, "include": ["docs", "theme", "rspress.config.ts"], "mdx": { "checkMdx": true } } ``` ## Start dev server Start the local development server with the following command: ```bash npm run dev ``` :::tip TIP For the dev command, you can specify the port number or host of the development server with the `--port` or `--host` parameter, such as `rspress dev --port 8080 --host 0.0.0.0`. ::: ## Build for production Build the production bundle with the following command: ```bash npm run build ``` By default, Rspress will output the production files to the `doc_build` directory. ## Preview locally Start the local preview server with the following command: ```bash npm run preview ``` The preview server serves the production output from `doc_build`. ## Next steps - Read [Basic features](https://rspress.rs/guide/basic/conventional-route.md) to learn routing, homepages, static assets, deployment, and other common documentation site features. - Read [Use MDX](https://rspress.rs/guide/use-mdx/components.md) to learn how to write MDX and use components in documentation. - Read [Configuration](https://rspress.rs/api/config/config-basic.md) to learn all supported Rspress config options. --- url: https://rspress.rs/guide/start/ai.md --- > 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. # AI Rspress provides the following capabilities to help AI understand its features, configuration, and best practices, so it can provide more accurate assistance during day-to-day development and troubleshooting: - [Agent Skills](#agent-skills) - [llms.txt](#llmstxt) - [Markdown docs](#markdown-docs) - [AGENTS.md](#agentsmd) ## Agent Skills Agent Skills are domain-specific knowledge packs that can be installed into coding agents, enabling more accurate, domain-specific suggestions and actions in supported scenarios. In the [rstackjs/agent-skills](https://github.com/rstackjs/agent-skills) repository, there are many skills for the Rstack ecosystem. The skills related to Rspress include: - [rspress-docs-generator](https://github.com/rstackjs/agent-skills#rspress-docs-generator): Recommended for creating and maintaining Rspress documentation sites, especially when a monorepo keeps a dedicated Rspress project as its documentation site. - [rspress-best-practices](https://github.com/rstackjs/agent-skills#rspress-best-practices): Rspress best practices for config, CLI workflow, content organization, frontmatter, MDX, themes, i18n, search, static assets, deployment, and debugging. - [rspress-v2-upgrade](https://github.com/rstackjs/agent-skills#rspress-v2-upgrade): Migrate Rspress projects from v1 to v2. - [rspress-custom-theme](https://github.com/rstackjs/agent-skills#rspress-custom-theme): Customize Rspress themes using CSS variables, Layout slots, component wrapping, or component ejection. - [rspress-description-generator](https://github.com/rstackjs/agent-skills#rspress-description-generator): Generate and maintain `description` frontmatter for Rspress documentation files. In Coding Agents that support skills, you can use the [skills](https://www.npmjs.com/package/skills) package to install a specific skill with the following command: ```sh [npx] npx skills add rstackjs/agent-skills --skill rspress-docs-generator ``` ```sh [yarn] yarn dlx skills add rstackjs/agent-skills --skill rspress-docs-generator ``` ```sh [pnpm] pnpm dlx skills add rstackjs/agent-skills --skill rspress-docs-generator ``` ```sh [bunx] bunx skills add rstackjs/agent-skills --skill rspress-docs-generator ``` ```sh [deno] deno run -A npm:skills add rstackjs/agent-skills --skill rspress-docs-generator ``` After installation, use natural language prompts to trigger the skill. For example: ``` Help me update the Rspress documentation project in this monorepo for the current feature branch ``` ## llms.txt [llms.txt](https://llmstxt.org/) is a standard that helps LLMs discover and use project documentation. Rspress follows this standard and publishes the following two files: - [llms.txt](https://rspress.rs/llms.txt): A structured index file containing the titles, links, and brief descriptions of all documentation pages. ``` https://rspress.rs/llms.txt ``` - [llms-full.txt](https://rspress.rs/llms-full.txt): A full-content file that concatenates the complete content of every documentation page into a single file. ``` https://rspress.rs/llms-full.txt ``` You can choose the file that best fits your use case: - `llms.txt` is smaller and consumes fewer tokens, making it suitable for AI to fetch specific pages on demand. - `llms-full.txt` contains the complete documentation content, so AI doesn't need to follow individual links — ideal when you need AI to have a comprehensive understanding of Rspress, though it consumes more tokens and is best used with AI tools that support large context windows. Rspress also has built-in [SSG-MD](https://rspress.rs/guide/basic/ssg-md.md) support, which can generate `llms.txt`-compliant files for your own documentation sites. Enable `llms: true` in the config to use it. ## Markdown docs Every Rspress documentation page has a corresponding `.md` plain-text version that can be provided directly to AI. On any doc page, you can click "Copy Markdown" or "Copy Markdown Link" under the title to get the Markdown content or link. ``` https://rspress.rs/guide/start/introduction.md ``` Providing the Markdown link or content allows AI to focus on a specific chapter, which is useful for targeted troubleshooting or looking up a particular topic. ## AGENTS.md You can create an `AGENTS.md` file in your Rspress project. This file follows the [AGENTS.md](https://agents.md/) specification and provides key project information to Agents. Example `AGENTS.md` content: ```markdown wrapCode # AGENTS.md You are an expert in JavaScript, Rspress, and documentation site development. You write maintainable, performant, and accessible code. ## Commands - `npm run dev` - Start the dev server - `npm run build` - Build the site for production - `npm run preview` - Preview the production build locally ## Docs - Rspress: https://rspress.rs/llms.txt - Rsbuild: https://rsbuild.rs/llms.txt - Rspack: https://rspack.rs/llms.txt ``` You can customize it for your project by adding details about the project structure, overall architecture, and other relevant information so agents can better understand your project. ::: tip If you are using Claude Code, you can create a `CLAUDE.md` file and reference the `AGENTS.md` file in it. ```markdown title="CLAUDE.md" @AGENTS.md ``` ::: --- url: https://rspress.rs/guide/basic/conventional-route.md --- > 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. # Conventional route ## What is it? Rspress uses file system routing: each page file path maps directly to a route path, making project routes easy to understand. For example, a file named `foo.md` in the `docs` directory is routed to `/foo`. ## Mapping rules Rspress automatically scans the root directory and all subdirectories, and maps file paths to route paths. For example, if you have the following file structure: ```tree docs ├── foo │ ├── bar.md │ └── index.md ├── zoo.md └── index.md ``` Then `bar.md` is routed to `/foo/bar`, and `/foo/index.md` is routed to `/foo/`. The specific mapping rules are as follows: | filepath | route path | `cleanUrl: false` path | | --------------- | ---------- | ---------------------- | | `index.md` | `/` | `/index.html` | | `/zoo.md` | `/zoo` | `/zoo.html` | | `/foo/index.md` | `/foo/` | `/foo/index.html` | | `/foo/bar.md` | `/foo/bar` | `/foo/bar.html` | :::warning Do not create files and folders with the same name, because they cause routing conflicts. For example, the following file structure is not allowed: ```tree docs ├── foo │ └── index.md └── foo.md ``` ::: ## TSX routing In conventional routing, `.tsx` files can also act as route components in addition to `.md(x)` files. By default, the component exported from a `.tsx` file is automatically registered as a route. For example: ```tsx title="foo.tsx" export default () => { return
foo
; }; ``` To customize the layout, export `frontmatter` and declare the layout type: ```tsx title="foo.tsx" export const frontmatter = { // Declare layout type // The custom layout here will not have a sidebar pageType: 'custom', }; ``` For the meaning of each `pageType`, see the [API documentation](https://rspress.rs/api/config/config-frontmatter.md#pagetype). ## Custom behavior If you want to customize the routing behavior, you can use the `route` field in the configuration file. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ route: { // These files will be registered as routes (supports glob pattern) include: ['other-dir/**/*'], // These files will not be registered as routes (supports glob pattern) exclude: ['components/**/*', 'fragments/**/*'], }, }); ``` ## Exclude files starting with `_` by default In the [docs directory](https://rspress.rs/api/config/config-basic.md#root), MDX fragments or React components must be excluded from routing with [route.exclude](https://rspress.rs/api/config/config-basic.md#routeexclude). For convenience, files starting with "\_" are excluded by default through [route.excludeConvention](https://rspress.rs/api/config/config-basic.md#routeexcludeconvention). You can also place components in adjacent directories outside the docs directory. For example: ```tree docs ├── _button.mdx └── index.mdx components └── button.tsx ``` **docs/index.mdx** ```mdx import ButtonFragment from './_button.mdx'; import Button from '../../components/button'; ; export default Button; ``` It is rendered as: #### button This is text from MDX This is a button from tsx ## Best practices We recommend placing documentation files in the `docs` directory to keep the project structure clear. Keep non-documentation content, such as custom components and utility functions, outside `docs` when possible. If they must live in `docs`, exclude them with `route.exclude`. :::tip If you place custom components or document fragments in the `docs` directory, use `route.exclude`; otherwise, those files are automatically registered as routes and may cause unexpected behavior. ::: Here is a best practice file structure that includes [MDX fragments and React components](https://rspress.rs/guide/use-mdx/components.md#fragments), [custom themes](https://rspress.rs/guide/basic/custom-theme.md), [conventional routing](https://rspress.rs/guide/basic/conventional-route.md), and [internationalization](https://rspress.rs/guide/basic/i18n.md): ```tree ├── docs │ ├── components # React components used in documentation │ │ └── Example.tsx │ ├── zh │ │ ├── fragments # zh document fragments │ │ │ └── example.mdx │ │ └── index.mdx │ └── en │ ├── fragments # en document fragments │ │ └── example.mdx │ └── index.mdx └── theme ├── components # React components for theme │ └── DocFooter.tsx └── index.tsx ``` ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ route: { exclude: ['*/components/**/*', '*/fragments/**/*'], // Files in these directories won't be registered as routes }, lang: 'en', locales: [ { lang: 'zh', label: '中文', }, { lang: 'en', label: 'English', }, ], }); ``` ```json title="tsconfig.json" { "compilerOptions": { "lib": ["DOM", "ESNext"], "jsx": "react-jsx", "moduleResolution": "bundler", "paths": { "i18n": ["./i18n.json"], "@theme": ["./theme/index.tsx"] } }, "include": ["docs", "theme", "rspress.config.ts"], "mdx": { "checkMdx": true } } ``` --- url: https://rspress.rs/guide/basic/auto-nav-sidebar.md --- > 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. # Autogenerated navigation In Rspress, you can either declare [nav](https://rspress.rs/api/config/config-theme.md#nav) and [sidebar](https://rspress.rs/api/config/config-theme.md#sidebar) in the config file or generate them automatically from `_nav.json` and `_meta.json`. We recommend the latter because it keeps the config file concise, supports HMR, and still exposes everything under `themeConfig`. :::tip Autogenerated navbar/sidebar only works when `rspress.config.ts` does not define `nav` or `sidebar`. ::: ## Basic usage Rspress generates the navbar from `_nav.json` and the sidebar from `_meta.json`. The navbar-level `_nav.json` lives in the docs root, while sidebar-level `_meta.json` files live in subdirectories under the docs root. For example: ```tree docs ├── _nav.json // navigation bar level └── guide ├── _meta.json // sidebar level ├── introduction.mdx └── advanced ├── _meta.json // sidebar level └── plugin-development.md ``` If your site uses i18n, place the navbar-level `_nav.json` in each language directory: ```tree docs ├── en │ ├── _nav.json // navigation bar level │ └── guide │ ├── _meta.json // sidebar level │ ├── introduction.mdx │ ├── install.mdx │ └── advanced │ ├── _meta.json // sidebar level │ └── plugin-development.md └── zh ├── _nav.json // navigation bar level └── guide ├── _meta.json // sidebar level ├── introduction.mdx ├── install.mdx └── advanced ├── _meta.json // sidebar level └── plugin-development.md ``` ## Global sidebar usage By default (only `_nav.json` exists at the root), Rspress generates a **separate sidebar for each subdirectory**. The sidebar switches automatically based on the currently active nav item. For example, clicking the "Guide" nav item shows the Guide sidebar, and clicking "API" shows the API sidebar: ```tree docs ├── _nav.json ├── guide │ ├── _meta.json // sidebar for /guide │ └── ... └── api ├── _meta.json // sidebar for /api └── ... ``` If you want all pages to **share a single global sidebar** instead of switching by nav, you can add a `_meta.json` at the root level of the docs directory (alongside `_nav.json`). This approach works better for documentation sites with **fewer nav items and a simpler structure**. Since the sidebar stays the same regardless of which nav item is active, it is a good fit when you want to organize the whole site under one unified sidebar: ```tree docs ├── _nav.json ├── _meta.json // root-level _meta.json → global sidebar ├── guide │ ├── _meta.json │ └── ... └── api ├── _meta.json └── ... ``` When a root-level `_meta.json` exists, Rspress will generate a single sidebar (keyed by `'/'`) for all pages, regardless of which nav item is active. The root `_meta.json` serves as the entry point for the entire sidebar tree, and you can typically organize subdirectories with section headers: ```json title="docs/_meta.json" [ { "type": "dir-section-header", "name": "guide", "label": "Guide" }, { "type": "dir-section-header", "name": "api", "label": "API" } ] ``` ## JSON schema type hint To improve editing for `_nav.json` and `_meta.json`, Rspress provides two schema files for IDE hints: `@rspress/core/meta-json-schema.json` and `@rspress/core/nav-json-schema.json`. For example, in VSCode, you can add the following configuration in `.vscode/settings.json`: ```json title=".vscode/settings.json" { //... "json.schemas": [ { "fileMatch": ["**/_meta.json"], "url": "./node_modules/@rspress/core/meta-json-schema.json" // or "url": "https://unpkg.com/@rspress/core@2.0.0/meta-json-schema.json" }, { "fileMatch": ["**/_nav.json"], "url": "./node_modules/@rspress/core/nav-json-schema.json" // or "url": "https://unpkg.com/@rspress/core@2.0.0/nav-json-schema.json" } ] // ... } ``` ## Navbar level config At the navbar level, `_nav.json` accepts an array with the same type as the default theme's nav config. For details, see [nav config](https://rspress.rs/api/config/config-theme.md#nav). For example: ```json title="docs/_nav.json" [ { "text": "Guide", "link": "/guide/introduction", "activeMatch": "^/guide/" } ] ``` ## Sidebar level config At the sidebar level, `_meta.json` accepts an array whose items use the following types: ```ts export type FileSideMeta = { type: 'file'; name: string; label?: string; icon?: string; tag?: string; overviewHeaders?: number[]; context?: string; }; export type DirSideMeta = { type: 'dir'; name: string; label?: string; collapsible?: boolean; collapsed?: boolean; icon?: string; tag?: string; overviewHeaders?: number[]; context?: string; }; export type DirSectionHeaderSideMeta = Omit & Omit & { type: 'dir-section-header' }; export type DividerSideMeta = { type: 'divider'; dashed?: boolean; }; export type SectionHeaderMeta = { type: 'section-header'; label: string; icon?: string; tag?: string; }; export type CustomLinkMeta = | { // file link type: 'custom-link'; label: string; icon?: string; tag?: string; overviewHeaders?: number[]; context?: string; link: string; } | { // dir link type: 'custom-link'; label: string; icon?: string; tag?: string; overviewHeaders?: number[]; context?: string; link?: string; collapsible?: boolean; collapsed?: boolean; items: _CustomLinkMetaWithoutTypeField[]; }; export type SideMetaItem = | FileSideMeta | DirSideMeta | DirSectionHeaderSideMeta | DividerSideMeta | SectionHeaderMeta | CustomLinkMeta | string; ``` ### file - When the item is a `string`, it represents a file. The string is the file name: ```json ["introduction"] ``` The file name may include a suffix or omit it. For example, `introduction` is resolved as `introduction.mdx`. - When the item is an object, it can describe a file, directory, or custom link. To describe a **file**, use the following type: ```ts export type FileSideMeta = { type: 'file'; name: string; label?: string; icon?: string; tag?: string; overviewHeaders?: number[]; context?: string; }; ``` Here, `name` is the file name with or without a suffix, and `label` is the file's display name in the sidebar. If `label` is omitted, Rspress uses the document's H1 title automatically. `overviewHeaders` controls which headings are shown on the file's overview page; it is optional and defaults to `[2]`. `context` adds a `data-context` attribute to the generated sidebar DOM node; it is optional and omitted by default. For example: ```json { "type": "file", "name": "introduction", "label": "Introduction" } ``` ### dir To describe a **directory**, use the following type: ```ts export type DirSideMeta = { type: 'dir'; name: string; label?: string; collapsible?: boolean; collapsed?: boolean; icon?: string; tag?: string; overviewHeaders?: number[]; context?: string; }; ``` Here, `name` is the directory name, `label` is the directory's display name in the sidebar, `collapsible` controls whether the directory can be collapsed, and `collapsed` controls whether it is collapsed by default. `overviewHeaders` controls which headings are shown on overview pages for files in this directory; it is optional and defaults to `[2]`. `context` adds a `data-context` attribute to the generated sidebar DOM node; it is optional and omitted by default. For example: ```json { "type": "dir", "name": "advanced", "label": "Advanced", "collapsible": true, "collapsed": false } ``` :::tip To display a document when users click a sidebar directory, create an `index.mdx` file inside that directory. For example: ```tree docs └── basic ├── guide │ ├── index.mdx │ ├── getting-started.mdx │ └── _meta.json └── _meta.json ``` ```json title="basic/_meta.json" [{ "type": "dir", "name": "guide" }] ``` ```json title="basic/guide/_meta.json" ["getting-started"] ``` This sidebar contains only the `getting-started` document. When users click the `Guide` directory, Rspress displays the content of `index.mdx`. ::: ### dir-section-header new When describing a **directory**, you can also use `dir-section-header`. It behaves like `"type": "dir"` but renders differently in the UI. It is often used at the first level, where the directory title appears as a [section header](#section-header) at the same level as files inside the directory. Type: ```ts export type DirSectionHeaderSideMeta = Omit & Omit & { type: 'dir-section-header' }; ``` ```json { "type": "dir-section-header", "name": "advanced", "label": "Advanced", "collapsible": true, "collapsed": false } ``` ### divider To describe a **divider**, use the following type: ```ts export type DividerSideMeta = { type: 'divider'; dashed?: boolean; }; ``` When `dashed` is `true`, the divider is dashed. Otherwise, it is solid. ### section-header To describe a **section header**, use the following type: ```ts export type SectionHeaderMeta = { type: 'section-header'; label: string; icon?: string; tag?: string; }; ``` Here, `label` is the section header's display name in the sidebar. For example: ```json { "type": "section-header", "label": "Section Header" } ``` Section headers make it easier to group documents and directories in the sidebar. You can combine them with `divider` to separate groups more clearly: ```json [ { "type": "section-header", "label": "Section 1" }, "introduction", { "type": "divider" }, { "type": "section-header", "label": "Section 2" }, "advanced" ] ``` ### custom-link To describe a **custom link**, use the following type: ```ts export type CustomLinkMeta = | { // file link type: 'custom-link'; label: string; icon?: string; tag?: string; overviewHeaders?: number[]; context?: string; link: string; } | { // dir link type: 'custom-link'; label: string; icon?: string; tag?: string; overviewHeaders?: number[]; context?: string; link?: string; collapsible?: boolean; collapsed?: boolean; items: _CustomLinkMetaWithoutTypeField[]; }; ``` Here, `link` is the link target and `label` is the display name in the sidebar. For example: ```json { "type": "custom-link", "link": "/my-link", "label": "My Link" } ``` `link` supports external links, for example: ```json { "type": "custom-link", "link": "https://github.com", "label": "GitHub" } ``` You can also use `items` to create nested custom links, for example: ```json { "type": "custom-link", "label": "My Link", "items": [ { "type": "custom-link", "label": "Sub Link 1", "link": "/sub-link-1" }, { "type": "custom-link", "label": "Sub Link 2", "link": "/sub-link-2" } ] } ``` ### Complete example Here is a complete example using the three types above: ```json [ "install", { "type": "file", "name": "introduction", "label": "Introduction" }, { "type": "dir", "name": "advanced", "label": "Advanced", "collapsible": true, "collapsed": false }, { "type": "custom-link", "link": "/my-link", "label": "My Link" } ] ``` ### No config usage In some directories, you can omit `_meta.json` and let Rspress generate the sidebar automatically. This works when the directory contains only documents, no subdirectories, and you do not need a custom document order. For example: ```tree docs ├── _meta.json └── guide ├── _meta.json └── basic ├── introduction.mdx ├── install.mdx └── plugin-development.md ``` In the `guide` directory, configure `_meta.json` as follows: ```json [ { "type": "dir", "name": "basic", "label": "Basic", "collapsible": true, "collapsed": false } ] ``` In the `basic` directory, you can omit `_meta.json`; Rspress then generates the sidebar automatically and sorts files alphabetically by file name. To customize the order, prefix file names with numbers: ```tree basic ├── 1-introduction.mdx ├── 2-install.mdx └── 3-plugin-development.md ``` ## Configure file items with frontmatter Most display fields for automatically generated file items can be declared in the page frontmatter: `title`, `icon`, `tag`, `overviewHeaders`, and `context`. Keep structural settings in `_meta.json`, including item order, `type`, `name`, directory groups, section headers, custom links, `collapsible`, and `collapsed`. For page-specific metadata, prefer frontmatter so the content and its sidebar presentation stay together. For example, `_meta.json` can define which files appear and in what order: ```json title="docs/guide/_meta.json" ["introduction"] ``` Then configure the file item's display metadata in the page frontmatter: ```md title="docs/guide/introduction.mdx" --- title: Introduction icon: /icon.png tag: new overviewHeaders: [2, 3] context: guide-introduction --- # Introduction ``` When a file item defines the same field in both places, frontmatter takes precedence for `icon`, `tag`, `overviewHeaders`, and `context`, while `label` in `_meta.json` takes precedence over the page title. For a directory group, `_meta.json` takes precedence over metadata from its index page. ## Sidebar icons and tags Use `icon` to add an icon before a sidebar title. The recommended and most common approach is to place the image in the `public` directory and reference it with an absolute path. For example, place a local image at `docs/public/icon.png`, then reference it in `_meta.json`: ```json title="docs/_meta.json" [ { "type": "file", "name": "introduction", "label": "Introduction", "icon": "/icon.png", "tag": "new" } ] ``` You can also provide an inline SVG string when you want to embed the icon directly in the configuration: ```json title="docs/_meta.json" [ { "type": "file", "name": "introduction", "icon": "" } ] ``` Emoji, external URLs, and data URLs are also supported. The existing `tag` config remains after the title. For details about `tag`, see [Tag Component](https://rspress.rs/ui/layout-components/tag.md). --- url: https://rspress.rs/guide/basic/static-assets.md --- > 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. # Static assets ## Introduction In Rspress, you may use the following static assets: - Images, videos and other static assets used in MDX files - Logo image in the upper-left corner of the site - Site favicon - Homepage logo image - Other static assets This page explains how to use each kind of static asset. :::tip Tip The `docs root` mentioned below refers to the directory specified by the `root` field in `rspress.config.ts`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ root: 'docs', }); ``` ::: ## Static assets used in MDX files You can import static assets in Markdown or MDX files. Rspress uses [Rsbuild - Static Assets](https://rsbuild.rs/guide/basic/static-assets) under the hood. ### Regular static assets For example, if the directory structure is as follows: ```tree docs ├── guide │ ├── index.mdx │ └── demo.png ``` If an image is in the same directory as the Markdown file, reference it like this: ```mdx ![](./demo.png) ``` You can also use the `img` tag directly in `.mdx` files: ```mdx ``` Both usages are transformed into: ```mdx title="index.mdx" import image from './demo.png'; ``` You can also import videos, audio files, and other static assets. Other usage patterns follow Rsbuild. ### public folder The `public` folder under the docs directory stores static assets. These assets are not processed during the build and can be referenced directly by URL. - When you start the dev server, these assets will be served under the [base](https://rspress.rs/api/config/config-basic.md#base) root path (default `/`). - When you run a production build, these assets will be copied to the [doc\_build directory](https://rspress.rs/api/config/config-basic.md#outdir). For example, you can place files like `robots.txt`, `manifest.json`, or `favicon.ico` in the public folder. Here's an example of placing static assets in the `public` folder. If the root directory is `docs` and the directory structure is as follows: ```tree docs ├── public │ └── demo.png ├── index.mdx ``` In the above `index.mdx` file, you can use an absolute path to reference `demo.png`: ```mdx ![](/demo.png) ``` When your site is configured with a `base` path and you use an absolute path in an `img` tag, use `normalizeImagePath` from `@rspress/core/runtime` to add the `base` path to `src`: ```tsx title="guide.mdx" import { normalizeImagePath } from '@rspress/core/runtime'; ; ``` ## Upper-left logo In Rspress, specify the upper-left logo image with the `logo` field. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ logo: 'https://avatars.githubusercontent.com/u/56892468?s=200&v=4', }); ``` The `logo` field supports both string and object configurations. When `logo` is a string, it supports: - Configured as an **external link**, like the above example. - Configured as an **absolute path**, such as `/rspress-logo.png`. In this case, Rspress finds `rspress-logo.png` in the `public` folder of your **docs root** and displays it. - Configured as a **relative path**, such as `./docs/public/rspress-logo.png`. In this case, Rspress resolves `rspress-logo.png` from the project root and displays it. If your site needs different logos for dark and light mode, use the object form: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ logo: { light: 'https://avatars.githubusercontent.com/u/56892468?s=200&v=4', dark: 'https://avatars.githubusercontent.com/u/56892468?s=200&v=4', }, }); ``` Here, `light` is the logo path for light mode, and `dark` is the logo path for dark mode. Both values support the same formats as the string form above. ## Favicon In Rspress, specify the site's favicon with the `icon` field. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ icon: 'https://avatars.githubusercontent.com/u/56892468?s=200&v=4', }); ``` The `icon` field supports a string or URL: - Configured as an **external link**, like the above example. - Configured as an **absolute path**, such as `/favicon.ico`. In this case, Rspress finds `favicon.ico` in the `public` folder of your **docs root** and displays it. - Configured as a **relative path**, such as `./docs/public/favicon.ico`. In this case, Rspress resolves `favicon.ico` from the project root and displays it. - Configured with the `file://` protocol or a `URL`, such as `file:///local_path/favicon.ico`. In this case, Rspress uses the local absolute path `/local_path/favicon.ico` directly. ## Homepage logo In the homepage [frontmatter configuration](https://rspress.rs/api/config/config-frontmatter.md#hero), specify the homepage logo image with `hero.image.src`. For example: ```mdx title="index.mdx" --- pageType: home hero: image: src: https://avatars.githubusercontent.com/u/56892468?s=200&v=4 alt: Rspress --- ``` Here, `src` is a string that supports: - Configured as an **external link**, like the above example. - Configured as an **absolute path**, such as `/rspress-logo.png`. In this case, Rspress finds `rspress-logo.png` in the `public` folder of your **docs root** and displays it. ## Other static assets In some scenarios, you may need to deploy specific static assets, such as Netlify's `_headers` file for custom HTTP response headers. In that case, place these assets directly in the `public` folder under the docs root, such as `docs/public`. During the build, Rspress automatically **copies all assets in the public folder to the output directory**, so they can be deployed with the site. --- url: https://rspress.rs/guide/basic/ssg.md --- > 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. # Static site generation (SSG) ## What is SSG SSG (Static Site Generation) refers to pre-rendering pages into HTML files during the **build phase**, rather than rendering them when users visit. **Advantages of SSG:** - **Faster First Contentful Paint**: Users don't need to wait for JavaScript to load and execute; they see complete content as soon as the browser loads the HTML - **SEO Friendly**: Search engine crawlers can directly access complete HTML content - **Easy to Deploy**: Output consists of static files and can be hosted on any static hosting service without a server Rspress enables SSG by default. When you run `rspress build`, each page is pre-rendered into an HTML file with complete content. The following sections explain how SSG works. ## Differences between dev and build Rspress employs different rendering strategies depending on the mode: it uses Client-Side Rendering (CSR) during development for a better experience, while defaulting to SSG during production builds for optimal performance. | Aspect | Dev Mode (Development) | Build Mode (Production) | | -------------- | -------------------------------- | -------------------------------------- | | Command | `rspress dev` | `rspress build` | | Rendering | Pure CSR (Client-Side Rendering) | SSG (default) or CSR | | Pre-rendering | None | Pre-renders all pages when SSG enabled | | Focus | Debugging, HMR | Performance, SEO | | Preview Method | Access dev server directly | `rspress preview` | ### Dev mode ```bash rspress dev ``` Dev mode uses **pure Client-Side Rendering (CSR)** without pre-rendering. This prioritizes iteration speed and Hot Module Replacement (HMR) capabilities. :::tip If your code works in dev mode but throws errors in build mode, it is usually because SSG renders in a Node.js environment and cannot access browser APIs such as `window` or `document`. See ["Common Issues and Solutions"](#common-issues-and-solutions) below. ::: ### Build mode ```bash rspress build ``` Build mode enables SSG by default. You can control this via the [`ssg` configuration](#configuration): - `ssg: true` (Default): Enable SSG. During the build, Rspress executes React component rendering in a Node.js environment, converting each page into an HTML file with complete content. - `ssg: false`: Disable SSG. Use pure CSR. The generated HTML contains only an empty container, waiting for client-side rendering. **After building:** - **Local Preview**: Use `rspress preview` to start a local static server for previewing the output ```bash rspress preview ``` - **Server Deployment**: Deploy the `doc_build` directory to static hosting services (GitHub Pages, Netlify, Vercel, etc.) ## SSG vs CSR output ### Output directory structure Whether using SSG or CSR mode, the output directory structure is the same: ```tree doc_build/ ├── static/ │ ├── js/ │ │ ├── main.[hash].js │ │ └── async/ │ └── css/ │ └── main.[hash].css ├── index.html ├── 404.html ├── guide/ │ └── getting-started.html └── api/ └── config.html ``` The `404.html` is automatically generated by Rspress to handle non-existent routes. This file plays an important role in SPA deployment, see ["Page shows 404 after refresh"](#refresh-404) for details. ### HTML content differences The core difference between the two modes lies in the HTML file content: **SSG Output HTML** (Pre-rendered complete content): ```html

Getting Started

Welcome to Rspress...

``` **CSR Output HTML** (only empty container, waiting for JS to render): ```html
``` ### Loading flow differences **SSG Loading Flow:** 1. Browser loads HTML → User **immediately sees complete content** 2. JavaScript finishes loading → React hydrates, binds event interactions 3. Subsequent navigation → SPA mode, client-side rendering **CSR Loading Flow:** 1. Browser loads HTML → User sees **blank page** 2. JavaScript finishes loading → React renders page content 3. Subsequent navigation → SPA mode, client-side rendering ## Common issues and solutions ### `window is not defined` / `document is not defined` **Cause**: SSG renders pages in a Node.js environment, where browser-specific global objects like `window` and `document` don't exist. **Solutions**: 1. **Use [`BrowserOnly`](https://rspress.rs/ui/runtime-components/browser-only.md) for browser-only rendering**: Wrap code that cannot run during SSG in a function. ```tsx import { BrowserOnly } from '@rspress/core/runtime'; function MyComponent(props) { return ( Loading...}> {async () => { const { LibComponent } = await import('some-lib-that-accesses-window'); return ; }} ); } ``` The children must be a function, not JSX. Otherwise, expressions like `window.location.href` are still evaluated while React builds the SSG render tree. 2. **Use `useEffect` for delayed execution**: Place browser API calls inside `useEffect` so they only run on the client. ```tsx import { useEffect, useState } from 'react'; function MyComponent() { const [width, setWidth] = useState(0); useEffect(() => { // Only runs on client setWidth(window.innerWidth); }, []); return
Window width: {width}
; } ``` 3. **Conditional check**: Check the environment before accessing browser APIs ```tsx if (typeof window !== 'undefined') { // Browser environment console.log(window.location.href); } ``` 4. **Dynamic import in `useEffect`**: For third-party libraries that depend on browser APIs, use dynamic imports in `useEffect` ```tsx import { useEffect, useState } from 'react'; function MyComponent() { const [Editor, setEditor] = useState(null); useEffect(() => { import('some-browser-only-library').then(mod => { setEditor(() => mod.default); }); }, []); if (!Editor) return
Loading...
; return ; } ``` ### Hydration mismatch **Cause**: The server-rendered HTML content doesn't match the client's first render. React checks for consistency during hydration, and mismatches will cause warnings or errors. **Common scenarios**: - Using `Date.now()` or random numbers - Rendering different content based on `window` object properties (like `window.innerWidth`) - Using data that only exists on the client (like localStorage) **Solution**: Ensure the first render output is consistent between server and client. For content that needs to change dynamically on the client, use `useEffect` to update after hydration completes. ```tsx import { useEffect, useState } from 'react'; function MyComponent() { // First render uses default value for server/client consistency const [theme, setTheme] = useState('light'); useEffect(() => { // Read localStorage after hydration completes const savedTheme = localStorage.getItem('theme'); if (savedTheme) { setTheme(savedTheme); } }, []); return
...
; } ``` ### Page shows 404 after refresh \{#refresh-404} **Symptom**: Navigating to other pages within the site works normally, but refreshing the page results in a 404 error. **Cause**: When you refresh the page or directly visit a URL, the request is sent to the server, but the server may not have a corresponding file for that path (especially on some static hosting services). **Solution**: Most static hosting services, such as GitHub Pages, Netlify, and Vercel, use `404.html` by default to handle unmatched routes and require no additional configuration. If your server does not do this automatically, configure it to redirect unmatched requests to `404.html`. The `404.html` generated by Rspress contains the complete application code, so it can handle routing on the client and display the correct page. If your hosting service supports Netlify-style redirects, you can use a `_redirects` file like this: ```txt title="docs/public/_redirects" /* /404.html 200 ``` ## Configuration Control whether SSG is enabled with the `ssg` configuration: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ ssg: true, // Default value, SSG enabled }); ``` If your site has special requirements, you can disable SSG: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ ssg: false, // Disable SSG, use CSR }); ``` :::warning Disable SSG carefully, because doing so removes the faster First Contentful Paint and SEO benefits. ::: ## Custom HTML content To inject custom HTML tags, such as meta tags, analytics code, scripts, or styles, see [Customizing Head Tags](https://rspress.rs/guide/advanced/custom-head.md). --- url: https://rspress.rs/guide/basic/ssg-md.md --- > 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. # llms.txt (SSG-MD) > Want to get started quickly? Jump to [Quick Start](#quick-start). ## What is SSG-MD? Rspress provides the experimental Static Site Generation to Markdown (SSG-MD) feature. Similar to [Static Site Generation (SSG)](https://rspress.rs/guide/basic/ssg.md), SSG-MD renders pages as Markdown files instead of HTML files and generates [`llms.txt`](#llms-txt) and `llms-full.txt`, making technical documentation easier for large language models to understand and use. The following table compares SSG and SSG-MD: | Comparison | SSG | SSG-MD | | ----------------------- | ------------------------------------------ | ------------------------------------ | | **Full Name** | Static Site Generation | Static Site Generation to Markdown | | **Optimization Target** | SEO (Search Engine Optimization) | GEO (Generative Engine Optimization) | | **Target Consumer** | Search engine crawler | LLM / vector retrieval system | | **Index File** | [`sitemap.xml`](https://www.sitemaps.org/) | [`llms.txt`](https://llmstxt.org/) | | **Full Content File** | - | `llms-full.txt` | | **Core Implementation** | `renderToString` | `renderToMarkdownString` | | **Access Method** | `/guide/start/introduction.html` | `/guide/start/introduction.md` | ## What is llms.txt? \{#llms-txt} [`llms.txt`](https://llmstxt.org/) is an emerging standard file format placed in a website's root directory to help large language models better understand and use website content. Because LLMs have limited context windows, they usually cannot process an entire website's HTML content. Converting complex HTML with navigation, ads, and JavaScript to plain text is also difficult and imprecise. `llms.txt` solves this by providing a structured Markdown index that includes page URLs and content descriptions, helping AI tools quickly locate and understand key information. In simple terms: - `sitemap.xml` → "Site map" for search engines - `llms.txt` → "Documentation index" for AI Output structure example: ```tree doc_build ├── llms.txt ├── llms-full.txt ├── guide │ └── start │ └── introduction.md └── ... ``` `llms.txt` content example: ```txt # Rspress > Rspress is a static site generator based on Rspack. ## Docs - [Introduction](/guide/start/introduction.md): Introduction to Rspress - [Quick Start](/guide/start/quick-start.md): Quick Start ``` ## Why SSG-MD? In React-based frontend frameworks, extracting static information from dynamically rendered content is often difficult. MDX has the same challenge: `.mdx` files contain Markdown content but can also embed React components, making docs more interactive. Rspress lets users enhance docs with MDX fragments, React components, Hooks, and TSX routes, but this dynamic content creates problems when converted to Markdown: - Feeding raw MDX to AI introduces code syntax noise and loses rendered React component content. - Converting HTML to Markdown often produces poor results, making information quality hard to guarantee. [Static Site Generation (SSG)](https://rspress.rs/guide/basic/ssg.md) generates static HTML for crawlers and improves [SEO](https://en.wikipedia.org/wiki/Search_engine_optimization). SSG-MD addresses a similar problem for AI tools: it improves [GEO](https://en.wikipedia.org/wiki/Generative_engine_optimization) and the quality of static information for large language models. Compared with HTML-to-Markdown conversion, rendering from React's virtual DOM gives SSG-MD a richer information source. ![SSG-MD rendering flow](https://assets.rspack.rs/rspress/assets/ssg-md-flow.jpg) ## How does SSG-MD work? 1. Rspress internally implements a `renderToMarkdownString` method similar to `renderToString` in `react-dom`, which renders React components to Markdown strings: ```tsx import { renderToMarkdownString } from 'react-render-to-markdown'; // HTML elements are converted to the corresponding Markdown syntax renderToMarkdownString(
foo bar
, ); // Output: '**foo**bar' // React components and Hooks are supported const Article = () => { return ( <>

Hello World

This is a paragraph.

); }; renderToMarkdownString(
); // Output: '# Hello World\n\nThis is a paragraph.\n' ``` In principle, this API works for any site built with React; see [react-render-to-markdown](https://www.npmjs.com/package/react-render-to-markdown) if you're interested. 2. Rspress uses a custom remark plugin `remarkSplitMdx` to preprocess MDX files before rendering. This plugin splits the MDX AST, separating pure Markdown content from JSX components: Markdown text is serialized as string literals, while JSX components and MDX expressions (e.g., `{variable}`) are preserved as React elements. This ensures that Markdown content passes through as-is without being processed by React rendering, while dynamic components are rendered by `renderToMarkdownString`. For example, the following MDX: ```mdx # Hello Some **bold** text. {window.title} ``` It is transformed into a component like this: ```tsx function _createMdxContent() { return ( <> {'# Hello\n\nSome **bold** text.\n'} {window.title} ); } ``` 3. Rspress provides the `import.meta.env.SSG_MD` environment variable so React components can distinguish SSG-MD rendering from browser rendering and customize their output: ```tsx export function Tab({ label }: { label: string }) { if (import.meta.env.SSG_MD) { return <>{`** Here is a Tab named ${label}**`}; } return
{label}
; } ``` 4. Rspress's internal component library is adapted for SSG-MD, so components render meaningful Markdown during the SSG-MD phase. For example: ```tsx ``` It is rendered as: ````md ```sh [npm] npm create rspress@latest ``` ```sh [yarn] yarn create rspress ``` ```sh [pnpm] pnpm create rspress@latest ``` ```sh [bun] bun create rspress@latest ``` ```sh [deno] deno init --npm rspress@latest ``` ```` ## Quick start Enable `llms` in `rspress.config.ts`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ llms: true, }); ``` After running `rspress build`, the output directory (default `doc_build`) will additionally contain the following files: ```tree doc_build ├── llms.txt # Index file with titles and descriptions in navigation order ├── llms-full.txt # Contains Markdown content of all pages ├── guide │ └── start │ └── introduction.md # Corresponding .md file for each page └── ... ``` Access pages by replacing the `.html` suffix with `.md`, e.g., `/guide/start/introduction.md`. Multilingual sites will output `{lang}/llms.txt` and `{lang}/llms-full.txt` for non-default languages. :::warning `llms` is experimental and may have stability or compatibility issues. If SSG-MD cannot be enabled because of SSR incompatibility, use [@rspress/plugin-llms](https://rspress.rs/plugin/official-plugins/llms.md). ::: :::info React 18 Support SSG-MD uses `react-render-to-markdown@19` by default, which only supports React 19. If you use React 18, install `react-render-to-markdown@18` in your `package.json`: ```json title="package.json" { "dependencies": { "react": "^18.3.1", "react-dom": "^18.3.1", "react-render-to-markdown": "^18.3.1" } } ``` After installation, Rspress automatically detects and uses the `react-render-to-markdown@18` version from your project. ::: ## Configuration ### UI display When `llms: true` is enabled, `LlmsCopyButton` and `LlmsViewOptions` components are automatically displayed below all H1 headers, allowing users to copy Markdown content or open it in AI tools like ChatGPT or Claude. You can also display them in the outline panel instead by setting `placement: 'outline'`. Customize or disable via `themeConfig.llmsUI`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ llms: true, themeConfig: { // Disable LLMS UI llmsUI: false, // Or customize options: // llmsUI: { // injectLlmsHint: false, // Disable the HTML/Markdown directive hint for LLMs // viewOptions: ['markdownLink', 'chatgpt', 'claude'], // placement: 'outline', // Display in outline panel instead of below H1 // }, }, }); ``` For more information, see [themeConfig.llmsUI](https://rspress.rs/api/config/config-theme.md#llmsui). ### Customize llms.txt Use `llms.llmsTxt` to compose the complete contents of each generated `llms.txt` file: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ llms: { llmsTxt: ({ title, description, sections }) => { const sectionContent = sections .map(section => { const pages = section.pages .map(page => `- [${page.title}](${page.link})`) .join('\n'); return `## ${section.title}\n\n${pages}`; }) .join('\n\n'); return `# ${title} > ${description} ${sectionContent}`; }, }, }); ``` The callback can return a string or a Promise. It runs once for every generated language and version combination, and receives: - `title` and `description`: The site metadata from `rspress.config.ts`. - `lang` and `version`: The language and version of the current `llms.txt` file. - `base` and `siteOrigin`: The URL configuration used to generate Markdown links. - `sections`: Pages grouped by navigation and ordered by the sidebar. Each page contains `title`, `description`, `frontmatter`, `routePath`, `link`, `lang`, and `version`. The `link` field is the final URL of the generated Markdown file. Pages that do not match a navigation item are placed in an `Others` section. The locale home page is omitted because the site title and description represent it. ### Custom MDX splitting When documents contain custom components, use `remarkSplitMdxOptions` to control which components to keep or convert to plain text when converting to Markdown: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ llms: { remarkSplitMdxOptions: { excludes: [[['Demo'], '@project/components']], }, }, }); ``` - `excludes`: Matched components are converted to plain text and have the highest priority. - `includes`: If set, only matched components are retained; all others are converted to plain text. - When both are configured, `excludes` is applied first, then the result is filtered by `includes`. --- url: https://rspress.rs/guide/basic/i18n.md --- > 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. # Internationalization To internationalize a Rspress documentation site, complete the following steps: 1. Define I18n text data. 2. Configure the language list, `locales` in `rspress.config.ts`. 3. Configure the default language, `lang` in `rspress.config.ts`. 4. Create docs for each language. 5. Configure sidebar and navbar. 6. Use `useI18n` in custom components. ## Define I18n text data Create an `i18n.json` file in the current workspace. The directory structure is: ```tree . ├── docs ├── i18n.json ├── package.json ├── tsconfig.json └── rspress.config.ts ``` Define the text required for internationalization in this JSON file. Its type is: ```ts export interface I18n { // key: text id [key: string]: { // key: language [key: string]: string; }; } ``` For example: ```json title="i18n.json" { "gettingStarted": { "en": "Getting Started", "zh": "开始" }, "features": { "en": "Features", "zh": "特性" }, "guide": { "en": "Guide", "zh": "指南" } } ``` This text data is used in both the **config file** and **custom components**, as explained below. ## Configure `locales` In `rspress.config.ts`, `locales` configures site-level information such as `lang`, `title`, and `description` for each language. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ // locales is an array of objects locales: [ { lang: 'en', // The label in the navbar language switcher label: 'English', title: 'Rspress', description: 'Static Site Generator', }, { lang: 'zh', label: '简体中文', title: 'Rspress', description: '静态网站生成器', }, ], }); ``` :::tip Note `themeConfig.locales` also contains all fields from `locales`, but it will be removed in the future. Use `locales` instead. ::: For other internationalized theme options, see [API type](https://rspress.rs/api/config/config-theme.md#locales). ## Configure `lang` default language After configuring `locales`, set the default site language with [lang](https://rspress.rs/api/config/config-basic.md#lang): ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ lang: 'en', }); ``` This is important because **Rspress removes the language prefix from routes in the default language**. For example, `/en/guide/getting-started` becomes `/guide/getting-started`. ## Create docs for each language After the configuration above, create the following structure in the docs root: ```tree ├── doc │ ├── en │ │ ├── _nav.json │ │ ├── api │ │ │ └── index.mdx │ │ ├── guide │ │ │ ├── _meta.json │ │ │ └── start │ │ │ ├── introduction.mdx │ │ │ └── quick-start.mdx │ │ └── index.md │ └── zh │ ├── _nav.json │ ├── api │ │ └── index.mdx │ ├── guide │ │ ├── _meta.json │ │ └── start │ │ ├── introduction.mdx │ │ └── quick-start.mdx │ └── index.md ├── i18n.json ├── package.json ├── rspress.config.ts └── tsconfig.json ``` Here, docs for different languages live in the `en` and `zh` directories under `docs`, making each language version easy to distinguish. ## Configure \_nav.json and \_meta.json Use `_nav.json` and `_meta.json` to configure the navbar and sidebar. For details, see [Autogenerated navigation](https://rspress.rs/guide/basic/auto-nav-sidebar.md). ### Navigation bar \_nav.json In the navbar-level `_nav.json`, `text` can be an i18n key. For example: ```json title="_nav.json" [ { "text": "guide", "link": "/guide/start/introduction" }, { "text": "api", "link": "/api/" } ] ``` Here, `text` is `guide`. Rspress translates this value to `指南` or `Guide` based on `i18n.json` and the current language. ### Sidebar \_meta.json In the sidebar-level `_meta.json`, `label` can be an i18n key. For example: ```json title="_meta.json" [ { "type": "dir", "name": "start", "label": "gettingStarted" } ] ``` Here, `label` is `gettingStarted`. Rspress translates this value to `开始` or `Getting Started` based on the current language. ## Use `useI18n` in custom components When writing MDX or developing a [custom theme](https://rspress.rs/guide/basic/custom-theme.md), custom components may also need localized text. Use `useI18n` to read it: Rspress provides the [`useI18n`](https://rspress.rs/ui/hooks/use-i18n.md) hook to get the internationalized text, the usage is as follows: ```tsx import { useI18n } from '@rspress/core/runtime'; const MyComponent = () => { const t = useI18n(); return
{t('gettingStarted')}
; }; ``` For better type hinting, you can configure `paths` in tsconfig.json: ```json { "compilerOptions": { "paths": { "i18n": ["./i18n.json"] } } } ``` Then use it like this in the component: ```tsx import { useI18n } from '@rspress/core/runtime'; const MyComponent = () => { const t = useI18n(); return
{t('gettingStarted')}
; }; ``` This way you get type hints for all text keys defined in `i18n.json`. --- url: https://rspress.rs/guide/basic/multi-version.md --- > 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. # Multi-version Rspress's default theme supports multi-version docs. This guide shows how to enable and organize them. ## `multiVersion` config Configure the version list and default version with `multiVersion`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ multiVersion: { default: 'v1', versions: ['v1', 'v2'], }, }); ``` Here, `default` is the default version, and `versions` is the version list. ## Add multi-version docs Based on the configured version list, add versioned docs under the `docs` directory: ```tree docs ├── v1 │ ├── index.mdx │ └── guide │ └── index.mdx └── v2 ├── index.mdx └── guide └── index.mdx ``` In Rspress conventional routing, the version path prefix is omitted for the default version. For example, `v1/index.mdx` is rendered as `/`, while `v2/index.mdx` is rendered as `/v2/`. :::tip Tip For document links, you do not need to manually add the version prefix. Rspress adds the corresponding prefix based on the current document version. For example, `/guide/` in `v2/index.mdx` is rendered as `/v2/guide/`. ::: ## Using with i18n You can use multi-version docs together with [internationalization](https://rspress.rs/guide/basic/i18n.md). When both are enabled, the directory structure uses **versions at the top level, then language subdirectories** within each version: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ lang: 'en', locales: [ { lang: 'en', label: 'English', }, { lang: 'zh', label: '简体中文', }, ], multiVersion: { default: 'v1', versions: ['v1', 'v2'], }, }); ``` Organize the docs directory as follows: ```tree docs ├── v1 │ ├── en │ │ ├── _nav.json │ │ ├── index.md │ │ └── guide │ │ └── index.md │ └── zh │ ├── _nav.json │ ├── index.md │ └── guide │ └── index.md └── v2 ├── en │ ├── _nav.json │ ├── index.md │ └── guide │ └── index.md └── zh ├── _nav.json ├── index.md └── guide └── index.md ``` The generated routes follow the pattern `/{version}/{lang}/`: | File path | Route | | ---------------- | --------------------------------------------------------------- | | `v1/en/index.md` | `/` (default version + default language, both prefixes omitted) | | `v1/zh/index.md` | `/zh/` | | `v2/en/index.md` | `/v2/` | | `v2/zh/index.md` | `/v2/zh/` | ## Get the current version in components In components, get the current version with [`useVersion`](https://rspress.rs/ui/hooks/use-version.md): ```tsx import { useVersion } from '@rspress/core/runtime'; export default () => { const version = useVersion(); return
Current version: {version}
; }; ``` ## Version-specific search By default, `search.versioned` is `true`, which means the search will only query the index corresponding to the currently selected version. If you want to search across all versions, you can set it to `false`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ multiVersion: { default: 'v1', versions: ['v1', 'v2'], }, search: { versioned: false, }, }); ``` --- url: https://rspress.rs/guide/basic/home-page.md --- > 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. # Homepage Rspress provides a homepage layout out of the box. Set `pageType: home` in frontmatter to quickly generate a usable site homepage. Define homepage content through frontmatter. See [Frontmatter Config](https://rspress.rs/api/config/config-frontmatter.md#hero) for the full types. Here is a simple example: ```yaml title="docs/index.mdx" --- pageType: home title: Rspress titleSuffix: 'Rsbuild-based Static Site Generator' hero: name: Rspress text: A documentation solution tagline: A modern documentation development technology stack actions: - theme: brand text: Introduction link: /en/guide/introduction - theme: alt text: Quick Start link: /en/guide/getting-started features: - title: 'MDX Support' details: MDX is a powerful way to write content. You can use React components in Markdown. icon: 📦 - title: 'Feature Rich' details: Out-of-the-box support for i18n, full-text search, and more. icon: 🎨 - title: 'Customizable' details: Customize the theme UI and build process. icon: 🚀 --- ``` ## Home components The Rspress homepage consists of these components, which you can customize through [Custom Theme - ESM Re-export](https://rspress.rs/guide/basic/custom-theme.md#reexport): - [HomeHero](https://rspress.rs/ui/layout-components/home-hero.md) - [HomeFeature](https://rspress.rs/ui/layout-components/home-feature.md) - [HomeFooter](https://rspress.rs/ui/layout-components/home-footer.md) - [HomeBackground](https://rspress.rs/ui/layout-components/home-background.md) :::tip You can also customize the entire homepage by overriding the [`HomeLayout`](https://rspress.rs/ui/layout-components/home-layout.md) component. If you do this, homepage-related configuration and these frontmatter fields will no longer take effect. ::: ## Configuration details For complete homepage frontmatter options, see [Frontmatter Config](https://rspress.rs/api/config/config-frontmatter.md#hero). --- url: https://rspress.rs/guide/basic/deploy.md --- > 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. # Deployment This page explains how to deploy a Rspress project after development is complete. Deployment usually involves: - Building and previewing the production output. - Configuring the static asset prefix. - Configuring the project base path. - Choosing a deployment platform. ## Build and preview Before deployment, build the project for production and preview it locally to make sure it works. In Rspress projects, use the following `scripts` commands: ```json { "scripts": { "build": "rspress build", "preview": "rspress preview" } } ``` :::tip Tip For preview, specify the port with `--port`, for example `rspress preview --port 8080`. ::: By default, the final output is written to the `doc_build` directory under the project root. Deploy the contents of this directory. ## Static resource prefix configuration Deployment output can be divided into two parts: HTML files and static assets. HTML files are the page files in the output directory and are deployed to the server. Static assets live in the `static` directory in the output directory. This directory contains the JavaScript, CSS, images, and other assets required by the site. If you want to serve these assets from a CDN instead of the same server as the HTML files, configure the static asset prefix so the HTML references the CDN URLs correctly. Use `builderConfig.output.assetPrefix`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ builderConfig: { output: { assetPrefix: 'https://cdn.com/', }, }, }); ``` Then Rspress automatically prefixes static asset references in HTML: ```html ``` ## Project base path configuration When deploying to a subpath, configure `base`. For example, if your site will be deployed to `https://foo.github.io/bar/`, set `base` to `"/bar/"`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ base: '/bar/', }); ``` For more details, see the [`base` config reference](https://rspress.rs/api/config/config-basic.md#base). ## Deployment platforms After completing the configuration above, deploy the output to a hosting platform. Common choices include Zephyr, GitHub Pages, Netlify, Vercel, Kinsta, and Zeabur. The following sections show several examples. ### Deploy with Zephyr Cloud [Zephyr Cloud](https://zephyr-cloud.io) is a zero-config deployment platform that integrates directly into your build process and provides global edge distribution. #### How to deploy Follow the steps in [zephyr-rspress-plugin](https://www.npmjs.com/package/zephyr-rspress-plugin). During the build process, your Rspress documentation site is deployed automatically and you receive a deployment URL. Zephyr Cloud handles asset optimization, global CDN distribution, and automatic rollback for documentation sites. ### Deploy via GitHub actions If your project is hosted on GitHub, you can deploy with GitHub Pages. GitHub Pages is a static hosting service from GitHub, so you can deploy without running your own server. #### 1. Create workflow file Create `.github/workflows/deploy.yml` in the project root with the following content: ```yml name: Deploy Rspress site to Pages on: push: branches: [main] workflow_dispatch: permissions: contents: read pages: write id-token: write concurrency: group: pages cancel-in-progress: false jobs: # Build job build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 # Not needed if lastUpdated is not enabled - uses: pnpm/action-setup@v3 # pnpm is optional but recommended, you can also use npm / yarn with: version: 8 - name: Setup Node uses: actions/setup-node@v4 with: node-version: 20 cache: pnpm - name: Setup Pages uses: actions/configure-pages@v5 - name: Install dependencies run: pnpm install - name: Build with Rspress run: | pnpm run build - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: path: doc_build # Deployment job deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} needs: build runs-on: ubuntu-latest name: Deploy steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 ``` #### 2. Configure GitHub Actions In the repository settings, open the `Pages` section and choose `GitHub Actions` as the deployment source. #### 3. Push code to main branch When you push code to the `main` branch, GitHub Actions runs the deployment workflow automatically. You can view progress in the `Actions` tab. After deployment completes, access your site at `https://.github.io//`. ### Deploy via Netlify Netlify is a web application deployment platform. You can deploy a Rspress site on Netlify without running your own server. #### Basic configuration To deploy on Netlify, import your GitHub repository and configure two fields: - `Build command`: The project build command, such as `npm run build`. - `Publish directory`: The output directory, usually `doc_build`. Then click `Deploy site` to deploy. #### Configure custom domain To bind a custom domain, configure it in Netlify's `Domain management` section. See the [Netlify official documentation](https://docs.netlify.com/domains-https/custom-domains/) for details. ### Deploy to Kinsta static site hosting You can deploy your Rspress site on [Kinsta](https://kinsta.com/static-site-hosting/). 1. Log in or create an account to view your [MyKinsta](https://my.kinsta.com/) dashboard. 2. Authorize Kinsta with your Git provider. 3. Select **Static Sites** from the left sidebar and press **Add sites**. 4. Select the repository and branch you want to deploy. 5. In build settings, Kinsta tries to fill in **Build command**, **Node version**, and **Publish directory** automatically. If it does not, use: - Build command: `npm run build` - Node version: `18.16.0` - Publish directory: `doc_build` 6. Click **Create site**. ### Deploy to Zeabur [Zeabur](https://zeabur.com) is a platform for deploying services quickly. It can deploy a Rspress site without additional configuration. #### How to deploy First, [create a Zeabur account](https://zeabur.com). Then follow the instructions to create a project and install the GitHub app so Zeabur can access your Rspress repository. Click `Deploy New Service` and import your Rspress repository. Deployment starts automatically, and Zeabur recognizes that the site is built with Rspress. Deployment usually finishes within a minute. You can also bind a free Zeabur subdomain or your own domain to the site. ## Troubleshooting ### Page shows 404 after refresh If your site navigates normally but shows a 404 after refresh, see ["Page shows 404 after refresh"](https://rspress.rs/guide/basic/ssg.md#refresh-404) in the SSG documentation. --- url: https://rspress.rs/guide/basic/custom-theme.md --- > 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. # Custom theme For your Agent If you are using a coding agent, install the [`rspress-custom-theme` Agent Skill](https://github.com/rstackjs/agent-skills#rspress-custom-theme) to help the agent generate a brand-new theme for you. For more information about AI-assisted development with Rspress, see the [AI page](https://rspress.rs/guide/start/ai.md). 1. For CSS, Rspress provides [CSS variables](#css-variables) and [BEM class names](#bem-classname) for customization. 2. For JS / React, Rspress provides a runtime interface based on ESM re-exports, so you can modify or replace built-in components for your own homepage, sidebar, search components, and more. On top of this, there are two modes: - [**wrap**](#wrap): **Wrap** and enhance Rspress built-in components with props or slots. - [**eject**](#eject): Directly **override** the entire component. You can use the [`rspress eject`](https://rspress.rs/api/commands.md#rspress-eject) command to copy the source code locally and modify it directly. The following sections introduce these approaches from lighter to deeper customization. ## CSS variables \{#css-variables} Rspress exposes commonly used CSS variables. Compared with rewriting built-in React components, overriding CSS variables is simpler and easier to maintain. View these CSS variables on the [UI - CSS Variables](https://rspress.rs/ui/vars.md) page, then override them with: ```tree ├── docs │ └── index.mdx ├── theme │ ├── index.tsx │ └── index.css <-- Copy CSS variable code here to override styles └── rspress.config.ts ``` ```tsx title="theme/index.tsx" import './index.css'; export * from '@rspress/core/theme-original'; ``` Another approach is to use the [globalStyles](https://rspress.rs/api/config/config-basic.md#globalstyles) config in `rspress.config.ts`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import path from 'path'; export default defineConfig({ globalStyles: path.join(__dirname, 'styles/index.css'), // Points to your CSS file }); ``` ## BEM class names \{#bem-classname} All built-in Rspress components use the BEM naming convention. You can use these class names to override styles, similar to [CSS Variables](#css-variables). ```css .rp-[component-name]__[element-name]--[modifier-name] { /* styles */ } ``` For example: ```css .rp-nav { } .rp-link { } .rp-tabs { } .rp-codeblock { } .rp-codeblock__title { } .rp-codeblock__description { } .rp-nav-menu__item, .rp-nav-menu__item--active { } ``` ## Override built-in components using ESM re-exports \{#reexport} By default, create a `theme` directory under the project root, then create an `index.ts` or `index.tsx` file inside it to export theme components. ```tree ├── docs ├── theme │ └── index.tsx └── rspress.config.ts ``` You can write the `theme/index.tsx` file using built-in components from `@rspress/core/theme-original`: ```tsx title="theme/index.tsx" import { Layout as BasicLayout } from '@rspress/core/theme-original'; const Layout = () => some content} />; export { Layout }; //[!code highlight] export * from '@rspress/core/theme-original'; //[!code highlight] ``` When you override built-in components with **ESM re-exports**, Rspress internal references to those components use your re-exported version first. :::note About @rspress/core/theme-original `@rspress/core/theme-original` avoids circular references. Use it only when customizing themes. ```tree ├── docs │ └── index.mdx <-- use "@rspress/core/theme" ├── theme │ └── index.tsx <-- use "@rspress/core/theme-original" └── rspress.config.ts ``` 1. In the `docs` directory, use `@rspress/core/theme`, which points to your `theme/index.tsx`. 2. In the `theme` directory, use `@rspress/core/theme-original`, which always points to Rspress built-in theme components. ::: ### Wrap: Pass props/slots \{#wrap} Wrapping means adding props to re-exported components. Here is an example that inserts content before the navbar title: **theme/index.tsx** ```tsx import { Layout as BasicLayout } from '@rspress/core/theme-original'; import { useI18n } from '@rspress/core'; const Layout = () => { const t = useI18n(); return {t('some content')}} />; }; export { Layout }; export * from '@rspress/core/theme-original'; ``` **i18n.json** ```json { "some content": { "zh": "一些内容", "en": "some content" } } ``` :::tip The [`Layout`](https://rspress.rs/ui/layout-components/layout.md) component is designed with a series of slot props specifically for wrapping. You can use these props to extend the default theme layout: ::: ### Eject: Directly override the entire component \{#eject} Ejecting means fully replacing a built-in Rspress component with your own version. Rspress provides the [`rspress eject [component]`](https://rspress.rs/api/commands.md#rspress-eject) command to copy built-in component source code locally so you can modify it directly: 1. Run the CLI. Rspress ejects the specified component source code to the local `theme/components` directory without ejecting its dependencies. 2. Update `theme/index.tsx` re-export: ```tsx title="theme/index.tsx" // Assuming you ejected the DocFooter component export { DocFooter } from './components/DocFooter'; export * from '@rspress/core/theme-original'; ``` 3. Modify `theme/components/DocFooter.tsx` as needed to meet your requirements. Rspress components are split into fine-grained pieces to make ejecting practical. See which components can be ejected in [Layout Components](https://rspress.rs/ui/layout-components/index.md). :::warning Do you really need eject? Ejecting increases maintenance cost. When Rspress is updated, ejected components do not receive updates automatically, so you need to compare and merge changes manually. Check whether wrapping meets your needs first. Use eject only when wrapping is not enough. ::: --- url: https://rspress.rs/guide/use-mdx/components.md --- > 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. # MDX and React components Rspress supports [MDX](https://mdxjs.com/), a content authoring format that seamlessly combines Markdown with JSX. MDX lets you use React components directly in your documentation, pairing Markdown's concise syntax with the React ecosystem. It is ideal for building interactive, component-based technical documentation. ## What is MDX MDX combines Markdown and JSX syntax, so you can write Markdown content and use React components in the same file. We recommend using `.mdx` for all documentation files. This lets you write content like regular Markdown while importing and using the [built-in components](https://rspress.rs/ui/components/index.md) provided by Rspress. ```mdx title="docs/index.mdx" # Hello, world! import { PackageManagerTabs } from '@rspress/core/theme'; ``` ## MDX fragments \{#fragments} In MDX, every `.mdx` file is compiled into a React component, which means it can be imported like any component and can freely render React components. For example: **docs/index.mdx** ```mdx import MdxFragment from './_mdx-fragment.mdx'; import TsxComponent from './_tsx-component'; Testing the use of MDX fragments and React components. ``` **docs/_mdx-fragment.mdx** ```mdx file="./_mdx-fragment.mdx" This is **mdx fragment**. ``` **docs/_tsx-component.tsx** ```tsx file="./_tsx-component.tsx" import { useState } from 'react'; export default () => { const [count, setCount] = useState(0); return (

This is a component from tsx{' '}

); }; ``` It renders as: Testing the use of MDX fragments and React components. This is **mdx fragment**. This is a component from tsx 0 In `.mdx` files, you can use the [built-in components](https://rspress.rs/ui/components/index.md) provided by Rspress or install React component libraries to enrich your documentation. ## Routing convention In the [docs directory](https://rspress.rs/api/config/config-basic.md#root), MDX fragments or React components must be excluded from routing with [route.exclude](https://rspress.rs/api/config/config-basic.md#routeexclude). For convenience, files starting with "\_" are excluded by default through [route.excludeConvention](https://rspress.rs/api/config/config-basic.md#routeexcludeconvention). You can also place components in adjacent directories outside the docs directory. For example: ```tree docs ├── _button.mdx └── index.mdx components └── button.tsx ``` **docs/index.mdx** ```mdx import ButtonFragment from './_button.mdx'; import Button from '../../components/button'; ; export default Button; ``` It is rendered as: #### button This is text from MDX This is a button from tsx ## Escape Hatch: writing document content in tsx ```tsx file="./_escape-hatch.tsx" title="_escape-hatch.tsx" import { getCustomMDXComponent } from '@rspress/core/theme'; export default () => { const { p: P, code: Code } = getCustomMDXComponent(); return (

This is content in tsx, but the styles are the same as in the documentation, such as @rspress/core. However, this text with className="rp-not-doc" @rspress/core will not take effect

); }; ``` It renders as: This is content in tsx, but the styles are the same as in the documentation, such as `@rspress/core`. However, this text with className="rp-not-doc"`@rspress/core` will not take effect :::warning TSX and HTML syntax can make it difficult to extract static information, such as local search indexes. We recommend using `.mdx` files for document content and `.tsx` files for interactive dynamic content. ::: ## React version requirements | Dependency | Allowed Range | Default Version | Notes | | ------------------ | ---------------------- | --------------- | ----------------------------------------- | | `react` | `^18.0.0 \|\| ^19.0.0` | 19 | React 17 is no longer supported | | `react-dom` | `^18.0.0 \|\| ^19.0.0` | 19 | Keep consistent with react version | | `react-router-dom` | `^6.0.0 \|\| ^7.0.0` | 7 | Uses project version if already installed | :::tip If `react`, `react-dom`, or `react-router-dom` is already installed in your project, Rspress will prioritize using the version installed in your project rather than the built-in default version. ::: --- url: https://rspress.rs/guide/use-mdx/frontmatter.md --- > 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. # Frontmatter You can add frontmatter at the beginning of a Markdown file. It is a [YAML](https://yaml.org/) block wrapped with three dashes `---` and used to define metadata. For example, use [title](https://rspress.rs/api/config/config-frontmatter.md#title) to specify the page title. By default, Rspress uses the page's H1 heading as the HTML document title. To use a different title, set it in frontmatter: ```mdx --- title: My Homepage --- This is my **homepage content**. ``` You can also use [description](https://rspress.rs/api/config/config-frontmatter.md#description) to specify a custom page description. By default, Rspress extracts the first contentful paragraph below the `h1` heading as the description (see [How description is determined](https://rspress.rs/guide/advanced/custom-head.md#how-description-is-determined)). If the extracted result does not meet your needs, you can override it: ```mdx --- description: A brief introduction to my homepage for SEO and social sharing. --- ``` For example, you can use [head](https://rspress.rs/api/config/config-frontmatter.md#head) to specify custom meta tags for [Open Graph](https://ogp.me/). ```yaml --- head: - - meta - property: og:url content: https://example.com/foo/ - - meta - property: og:image content: https://example.com/bar.jpg # - - [htmlTag] # - [attributeName]: [attributeValue] # [attributeName]: [attributeValue] --- ``` :::tip See [Frontmatter config](https://rspress.rs/api/config/config-frontmatter.md) for available frontmatter options, and [useFrontmatter](https://rspress.rs/ui/hooks/use-frontmatter.md) for accessing frontmatter in code. ::: --- url: https://rspress.rs/guide/use-mdx/code-blocks.md --- > 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. # Code blocks Rspress uses [Shiki](https://shiki.style) for syntax highlighting at compile time, which means better runtime performance. When using code blocks in multiple languages, the corresponding language is automatically detected at compile time, and the runtime bundle size does not increase. For supported programming languages, refer to the [Shiki supported languages list](https://shiki.style/languages). ## Basic usage You can use the \`\`\` syntax to create code blocks. For example: ````mdx ```js console.log('Hello World'); ``` ```` It renders as: ```js console.log('Hello World'); ``` ## Code block title You can use the `title="..."` attribute to add a title to a code block. ````mdx ```jsx title="src/components/HelloCodeBlockTitle.tsx" const HelloCodeBlockTitle = props => { return

Hello CodeBlock Title

; }; ``` ```` It renders as: ```jsx title="src/components/HelloCodeBlockTitle.tsx" const HelloCodeBlockTitle = props => { return

Hello CodeBlock Title

; }; ``` ## File code block \{#file-code-block} You can use the `file="./path/to/file"` attribute without writing any code block content to reference the text from an external file. ### Relative paths Use relative paths starting with `./` or `../` to reference files relative to the current MDX file: **foo.mdx** ````mdx ```tsx file="./_tsx-component.tsx" ``` ```` **_tsx-component.tsx** ```tsx file="./_tsx-component.tsx" import { useState } from 'react'; export default () => { const [count, setCount] = useState(0); return (

This is a component from tsx{' '}

); }; ``` It renders as: ```tsx file="./_tsx-component.tsx" import { useState } from 'react'; export default () => { const [count, setCount] = useState(0); return (

This is a component from tsx{' '}

); }; ``` ### Absolute paths with `/` prefix Use the `/` prefix to reference files using absolute paths relative to the docs directory. This is useful when you need to reference shared code files from different locations in your documentation: ````mdx ```tsx file="/components/Button.tsx" ``` ```` For example, if your docs directory is `/project/docs`, then `/components/Button.tsx` will resolve to `/project/docs/components/Button.tsx`. ### Absolute paths with `/` prefix Use the `/` prefix to reference files using absolute paths relative to the project root directory. This is useful when you need to reference shared code files from different locations in your documentation: ````mdx ```tsx file="/src/components/Button.tsx" ``` ```` For example, if your project root is `/project`, then `/src/components/Button.tsx` will resolve to `/project/src/components/Button.tsx`. :::tip When using external file code blocks, it's common to use them together with [route conventions](https://rspress.rs/guide/use-mdx/components.md#routing-convention). Name files starting with `_`. ::: ## Notation line highlight You can use [Shiki transformers](#shiki-transformers) with the `transformerNotationHighlight` and `// [!code highlight]` comments to highlight code lines. **Code** ````mdx ```ts console.log('Highlighted'); // [\!code highlight] console.log('Not highlighted'); // [\!code highlight:2] console.log('Highlighted'); console.log('Highlighted'); ``` ```` **rspress.config.ts** ```ts import { defineConfig } from '@rspress/core'; import { transformerNotationHighlight } from '@shikijs/transformers'; export default defineConfig({ markdown: { shiki: { transformers: [transformerNotationHighlight()], }, }, }); ``` It renders as: ```ts title="highlight.ts" console.log('Highlighted'); // [!code highlight] console.log('Not highlighted'); // [!code highlight:2] console.log('Highlighted'); console.log('Highlighted'); ``` ## Meta line highlight :::warning When using meta info for line highlighting, be aware that formatting tools may change line numbers. For maintainability, [Notation Line Highlight](#notation-line-highlight) is recommended. ::: You can use `@rspress/core/shiki-transformers` with `transformerCompatibleMetaHighlight` and meta info comments to highlight code lines. **Code** ````mdx ```ts {1,3-4} console.log('Highlighted'); console.log('Not highlighted'); console.log('Highlighted'); console.log('Highlighted'); ``` ```` **rspress.config.ts** ```ts import { defineConfig } from '@rspress/core'; import { transformerCompatibleMetaHighlight } from '@rspress/core/shiki-transformers'; export default defineConfig({ markdown: { shiki: { transformers: [transformerCompatibleMetaHighlight()], }, }, }); ``` It renders as: ```ts {1,3-4} console.log('Highlighted'); console.log('Not highlighted'); console.log('Highlighted'); console.log('Highlighted'); ``` ## Show code line numbers You can show line numbers for individual code blocks using the `lineNumbers` meta attribute: ````mdx ```ts lineNumbers function hello() { console.log('Line numbers enabled for this block'); } ``` ```` It renders as: ```ts lineNumbers function hello() { console.log('Line numbers enabled for this block'); } ``` You can also enable line numbers globally by setting the [`showLineNumbers`](https://rspress.rs/api/config/config-build.md#markdownshowlinenumbers) option in the config file: ```ts title="rspress.config.ts" export default { // ... markdown: { showLineNumbers: true, }, }; ``` When `showLineNumbers` is enabled globally, all code blocks will show line numbers by default. You can disable line numbers for a specific code block by using `lineNumbers=false`: ````mdx ```ts lineNumbers=false function hello() { console.log('Line numbers disabled for this block'); } ``` ```` ## Wrap code You can enable code wrapping for individual code blocks using the `wrapCode` meta attribute: ````mdx ```ts wrapCode const longLine = 'This is a very long line of code that will wrap when the wrapCode meta attribute is present'; ``` ```` It renders as: ```ts wrapCode const longLine = 'This is a very long line of code that will wrap when the wrapCode meta attribute is present'; ``` You can also enable code wrapping globally by setting the [`defaultWrapCode`](https://rspress.rs/api/config/config-build.md#markdowndefaultwrapcode) option in the config file: ```ts title="rspress.config.ts" export default { // ... markdown: { defaultWrapCode: true, }, }; ``` When `defaultWrapCode` is enabled globally, all code blocks will wrap long lines by default. You can disable code wrapping for a specific code block by using `wrapCode=false`: ````mdx ```ts wrapCode=false const longLine = 'This code block will not wrap even if defaultWrapCode is enabled globally'; ``` ```` ## Code block height You can control the height behavior of code blocks using the `height` and `fold` meta attributes. There are three cases: - **`fold`**: Collapsible code block with an expand button. Height defaults to 300px. - **`height=X`**: Fixed height with vertical scrollbar. If combined with `fold`, the code block will be collapsible at the specified height instead. - **No meta**: Fully expanded by default. You can change this globally via [`markdown.defaultCodeOverflow`](https://rspress.rs/api/config/config-build.md#markdowndefaultcodeoverflow). ### Fold Use the `fold` attribute to enable expand/collapse functionality. You can also customize the collapsed height via the `height` attribute (in pixels, default 300): ````mdx ```tsx fold height="350" // Put longer code content here to trigger expand/collapse ``` ```` It renders as: ```jsx title="fold-demo.tsx" fold height="350" import { useState } from 'react'; export default () => { const [count, setCount] = useState(0); return (
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
Line 9
Line 10
Line 11
Line 12
Line 13
Line 14
Line 15
Line 16
Line 17
Line 18
Line 19
Line 20
{count}
); }; ``` :::tip The expand/collapse button will not be shown when the actual content height is less than `height`. ::: ### Scroll Use the `height` attribute alone (without `fold`) to set a fixed height with a vertical scrollbar: ````mdx ```tsx height="200" // Put longer code content here to trigger scrolling ``` ```` It renders as: ```tsx title="scroll-demo.tsx" height="200" const lines = Array.from({ length: 20 }, (_, index) => `Line ${index + 1}`); export default function ScrollDemo() { return (
{lines.map(line => (
{line}
))}
); } ``` ## Combining meta attributes You can combine multiple meta attributes together: ````mdx ```ts lineNumbers wrapCode title="example.ts" const longLine = 'This code block has line numbers, code wrapping, and a title'; ``` ```` It renders as: ```ts lineNumbers wrapCode title="example.ts" const longLine = 'This code block has line numbers, code wrapping, and a title'; ``` ## Diff code block ````mdx ```diff function test() { - console.log('deleted'); + console.log('added'); console.log('unchanged'); } ``` ```` It renders as: ```diff function test() { - console.log('deleted'); + console.log('added'); console.log('unchanged'); } ``` ## Shiki transformers Rspress uses [Shiki](https://shiki.style) for compile-time code highlighting, providing flexible code block capabilities. You can add custom [shiki transformers](https://shiki.style/guide/transformers.html) via [`markdown.shiki.transformers`](https://rspress.rs/api/config/config-build.md#markdownshiki) for richer code block effects. In addition to the [transformerNotationHighlight](#notation-line-highlight) mentioned above, Rspress defaults to supporting the following transformers from [@shikijs/transformers](https://shiki.style/packages/transformers). ### transformerNotationDiff **Syntax** ````mdx ```ts console.log('deleted'); // [\!code --] console.log('added'); // [\!code ++] console.log('unchanged'); ``` ```` **rspress.config.ts** ```ts import { defineConfig } from '@rspress/core'; import { transformerNotationDiff } from '@shikijs/transformers'; export default defineConfig({ markdown: { shiki: { transformers: [transformerNotationDiff()], }, }, }); ``` It renders as: ```ts console.log('deleted'); // [!code --] console.log('added'); // [!code ++] console.log('unchanged'); ``` ### transformerNotationErrorLevel **Syntax** ````mdx ```ts console.log('No errors or warnings'); console.error('Error'); // [\!code error] console.warn('Warning'); // [\!code warning] ``` ```` **rspress.config.ts** ```ts import { defineConfig } from '@rspress/core'; import { transformerNotationErrorLevel } from '@shikijs/transformers'; export default defineConfig({ markdown: { shiki: { transformers: [transformerNotationErrorLevel()], }, }, }); ``` It renders as: ```ts console.log('No errors or warnings'); console.error('Error'); // [!code error] console.warn('Warning'); // [!code warning] ``` ### transformerNotationFocus **Syntax** ````mdx ```ts console.log('Not focused'); console.log('Focused'); // [\!code focus] console.log('Not focused'); ``` ```` **rspress.config.ts** ```ts import { defineConfig } from '@rspress/core'; import { transformerNotationFocus } from '@shikijs/transformers'; export default defineConfig({ markdown: { shiki: { transformers: [transformerNotationFocus()], }, }, }); ``` It renders as: ```ts console.log('Not focused'); console.log('Focused'); // [!code focus] console.log('Not focused'); ``` ## Twoslash > [Twoslash](https://twoslash.netlify.app/guide/) is a markup format for TypeScript code, suitable for creating self-contained code samples and letting the TypeScript compiler automatically supplement type information and hints. It is widely used on the official TypeScript website. Rspress provides the `@rspress/plugin-twoslash` plugin, which enables Twoslash features in Rspress. See [@rspress/plugin-twoslash documentation](https://rspress.rs/plugin/official-plugins/twoslash.md) for details. ```ts twoslash // @noErrorValidation const str: string = 1; ``` ## Runtime syntax highlighting When you need to render code blocks dynamically at runtime, such as in interactive docs or fetching code remotely, Rspress provides the `CodeBlockRuntime` component. Here is an example: ```mdx title="foo.mdx" import { CodeBlockRuntime } from '@rspress/core/theme'; import { transformerNotationHighlight } from '@shikijs/transformers'; ``` ```ts title=highlight.ts console.log('Highlighted'); // [!code highlight] // [!code highlight:1] console.log('Highlighted'); console.log('Not highlighted'); ``` :::warning Use `CodeBlockRuntime` only when necessary. It increases runtime bundle size and cannot benefit from compile-time highlighting. ::: --- url: https://rspress.rs/guide/use-mdx/link.md --- > 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. # Links ## Link format Rspress supports two formats of links: **file path format** and **URL format**. They render exactly the same results, differing only in code style. **Syntax** ```mdx [File path format - ../start/getting-started.mdx](../start/getting-started.mdx) [URL format - /guide/start/getting-started](/guide/start/getting-started) ``` **Rendered result** [File path format - ../start/getting-started.mdx](https://rspress.rs/guide/start/getting-started.md) [URL format - /guide/start/getting-started](https://rspress.rs/guide/start/getting-started.md) :::tip Within the same Rspress project, use one link format consistently to keep the code style predictable. ::: ## File path format The file path format uses **absolute file paths** or **relative file paths** to reference specific `.md` or `.mdx` files. Here are examples from this website: **Syntax** ```mdx [Relative path - ../start/getting-started.mdx](../start/getting-started.mdx) [Absolute path - /guide/start/getting-started.mdx](/guide/start/getting-started.mdx) [Absolute path with language - /zh/guide/start/getting-started.mdx](/zh/guide/start/getting-started.mdx) [Absolute path to another language page - /en/guide/start/getting-started.mdx](/en/guide/start/getting-started.mdx) ``` **Rendered result** [Relative path - ../start/getting-started.mdx](https://rspress.rs/guide/start/getting-started.md) [Absolute path - /guide/start/getting-started.mdx](https://rspress.rs/guide/start/getting-started.md) [Absolute path with language - /zh/guide/start/getting-started.mdx](https://rspress.rs/zh/guide/start/getting-started.md) [Absolute path to another language page - /en/guide/start/getting-started.mdx](https://rspress.rs/guide/start/getting-started.md) :::tip When using absolute paths, the root path is the [`docs`](https://rspress.rs/api/config/config-basic.md#root) directory. If the project uses [internationalization](https://rspress.rs/guide/basic/i18n.md) or [multi-version](https://rspress.rs/guide/basic/multi-version.md), the [`markdown.link.autoPrefix`](https://rspress.rs/api/config/config-build.md#markdownlinkautoprefix) configuration will automatically add prefixes, so you can omit the language directory in links. For example: [Absolute path - /guide/start/getting-started.mdx](https://rspress.rs/guide/start/getting-started.md) [Absolute path with language - /zh/guide/start/getting-started.mdx](https://rspress.rs/zh/guide/start/getting-started.md) Both will point to the same page. ::: We recommend using relative file paths because they provide the following advantages: 1. IDE support: suggestions, jumping to the corresponding file, automatic link updates when files move, and more. 2. Support in the GitHub UI and other Markdown editors. 3. Unlike URL format, file path links are not affected by the [`cleanUrls`](https://rspress.rs/api/config/config-basic.md#routecleanurls) configuration. ## URL format The URL format uses route URLs to reference specific pages. Here are examples from this website: **Syntax** ```mdx [Relative path - ../start/getting-started](../start/getting-started) [Absolute path - /guide/start/getting-started](/guide/start/getting-started) [Absolute path - /guide/start/getting-started.html](/guide/start/getting-started.html) [Absolute path with language - /zh/guide/start/getting-started.html](/zh/guide/start/getting-started.html) [Absolute path to another language page - /en/guide/start/getting-started.html](/en/guide/start/getting-started.html) ``` **Rendered result** [Relative path - ../start/getting-started](https://rspress.rs/guide/start/getting-started.md) [Relative path - ../start/getting-started.html](https://rspress.rs/guide/start/getting-started.md) [Absolute path - /guide/start/getting-started](https://rspress.rs/guide/start/getting-started.md) [Absolute path - /guide/start/getting-started.html](https://rspress.rs/guide/start/getting-started.md) [Absolute path with language - /zh/guide/start/getting-started.html](https://rspress.rs/zh/guide/start/getting-started.md) [Absolute path to another language page - /en/guide/start/getting-started.html](https://rspress.rs/guide/start/getting-started.md) :::tip When using absolute paths, the root path is the [`docs`](https://rspress.rs/api/config/config-basic.md#root) directory. If the project uses [internationalization](https://rspress.rs/guide/basic/i18n.md) or [multi-version](https://rspress.rs/guide/basic/multi-version.md), the [`markdown.link.autoPrefix`](https://rspress.rs/api/config/config-build.md#markdownlinkautoprefix) configuration will automatically add prefixes, so you can omit the language directory in links. For example: [Absolute path - /guide/start/getting-started](https://rspress.rs/guide/start/getting-started.md) [Absolute path with language - /zh/guide/start/getting-started](https://rspress.rs/zh/guide/start/getting-started.md) Both will point to the same page. ::: The difference between URL format and file path format is that Rspress automatically adds the `.html` suffix according to the [`cleanUrls`](https://rspress.rs/api/config/config-basic.md#routecleanurls) configuration. You do not need to manage the suffix manually; links with or without `.html` render consistently. ## External links External links that are not in this docsite will automatically add `target="_blank" rel="noreferrer"`: - [Rspack Documentation](https://rspack.rs/) - [Rsbuild Documentation](https://rsbuild.rs/) ## Assets links Links to static resources in the documentation site are preserved as written: - Static assets in public folder - [/og-image.png](/og-image.png) - Generated by @rspress/plugin-llms - [/llms-full.txt](/llms-full.txt) :::tip You need to exclude these links from [dead link checking](#dead-links-checking). ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { link: { checkDeadLinks: { excludes: ['/og-image.png', '/llms-full.txt'], }, }, }, }); ``` ::: ## Link definition syntax Rspress also supports markdown's alternative `definition` syntax for links, which can simplify link writing when there are many links. **Syntax** ```mdx Rspress supports [relative file paths] and [absolute file paths]. [relative file paths]: ../start/getting-started.mdx [absolute file paths]: /guide/start/getting-started.mdx ``` **Rendered result** Rspress supports [relative file paths] and [absolute file paths]. [relative file paths]: https://rspress.rs/guide/start/getting-started.md [absolute file paths]: https://rspress.rs/guide/start/getting-started.md ## Anchor links Rspress supports adding anchor navigation in links, using the `#` symbol to specify jumping to a specific position on the page. **Syntax** ```mdx [Jump to #File Path Format](#file-path-format) [Jump to Getting Started#Create a Rspress project](../start/getting-started.mdx#create-a-rspress-project) ``` **Rendered result** [Jump to #file-path-format](#file-path-format) [Jump to Getting Started#Create a Rspress project](https://rspress.rs/guide/start/getting-started.md#create-a-rspress-project) ### Customizing anchor id By default, Rspress will automatically generate ids based on the content of each title. This id will also serve as the content of the anchor. You can use the following syntax to customize the id of the header: ```md ## Hello world \{#custom-id} ``` Where `custom-id` is your custom id. ## Dead links checking During the maintenance of documentation sites, broken links often occur. Rspress provides a dead link checking feature to specifically address this troublesome maintenance issue. Configure through [markdown.link.checkDeadLinks](https://rspress.rs/api/config/config-build.md#markdownlinkcheckdeadlinks) to automatically check for invalid links. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { link: { checkDeadLinks: true, }, }, }); ``` ## Dead anchors checking Rspress can also check whether internal link anchors exist in the target page. It checks same-page anchors, relative links, and absolute links, but skips external URL anchors. :::info Anchor checking is currently disabled by default. It will be enabled by default in a future version. ::: Configure through [markdown.link.checkAnchors](https://rspress.rs/api/config/config-build.md#markdownlinkcheckanchors) to automatically check for invalid anchors. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { link: { checkAnchors: true, }, }, }); ``` ## Dead images checking Similar to dead link checking, Rspress can also check for broken image references in your documentation. This catches images that reference non-existent local files, including both relative paths and absolute paths that reference the `public` directory. Configure through [markdown.image.checkDeadImages](https://rspress.rs/api/config/config-build.md#markdownimagecheckdeadimages) to automatically check for invalid images. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { image: { checkDeadImages: true, }, }, }); ``` --- url: https://rspress.rs/guide/use-mdx/container.md --- > 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. # Container Containers are a great way to mark important information and provide hints to users. :::tip Rspress provides two styles of syntax, [`:::` syntax](#three-colon-syntax) and [GitHub Markdown Alerts syntax](#github-markdown-alerts-syntax). ::: ## `:::` Syntax \{#three-colon-syntax} You can use the `:::` syntax to create custom containers and support custom titles. For example: **Rendered Result** :::note This is a `note` callout ::: :::tip This is a `tip` callout ::: :::important This is an `important` callout ::: :::info This is an `info` callout ::: :::warning This is a `warning` callout ::: :::danger This is a `danger` callout ::: :::details This is a `details` callout ::: :::tip Custom Title This is a callout with a custom title ::: :::tip\{title="Custom Title"} This is a callout with a custom title ::: **Syntax** ```markdown :::note This is a `note` callout ::: :::tip This is a `tip` callout ::: :::important This is an `important` callout ::: :::info This is an `info` callout ::: :::warning This is a `warning` callout ::: :::danger This is a `danger` callout ::: :::details This is a `details` callout ::: :::tip Custom Title This is a callout with a custom title ::: :::tip{title="Custom Title"} This is a callout with a custom title ::: ``` :::warning Notes - Container types must be lowercase. Use `:::tip`, `:::warning`, `:::caution`, etc. Capitalized types like `:::Tip` or `:::Warning` will not be recognized. - When using the `:::` syntax in `.mdx` files and customizing headings with curly braces syntax, remember to escape the braces. We therefore recommend using the syntax `:::tip Custom Title` directly. ```mdx :::tip\{title="Custom Title"} This is a `block` of `Custom Title` ::: ``` ::: ## GitHub Markdown alerts syntax \{#github-markdown-alerts-syntax} You can use [GitHub Markdown Alerts Syntax](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) to create custom containers. **Rendered Result** > \[!NOTE] > This is a `block` of type `note` > \[!TIP] > This is a `block` of type `tip` > \[!IMPORTANT] > This is a `block` of type `important` > \[!INFO] > This is a `block` of type `info` > \[!WARNING] > This is a `block` of type `warning` > \[!DANGER] > This is a `block` of type `danger` > \[!DETAILS] > This is a `block` of type `details` **Syntax** ```markdown > [!NOTE] > This is a `block` of type `note` > [!TIP] > This is a `block` of type `tip` > [!IMPORTANT] > This is a `block` of type `important` > [!INFO] > This is a `block` of type `info` > [!WARNING] > This is a `block` of type `warning` > [!DANGER] > This is a `block` of type `danger` > [!DETAILS] > This is a `block` of type `details` ``` --- url: https://rspress.rs/guide/advanced/overview-page.md --- > 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. # Overview page The Overview page displays an overview of all articles in a directory, automatically extracting information from the sidebar to generate grouped content. ## Usage Configure `overview: true` in the directory's `index.md` to enable it: ```md title="api/index.md" --- overview: true title: API Overview --- This is the API overview page. ``` The Overview page automatically reads the current directory's [sidebar configuration](https://rspress.rs/guide/basic/auto-nav-sidebar.md) and extracts article titles to generate grouped cards. ## Example Given the following directory structure and `_meta.json` configuration: ```tree docs └── api ├── _meta.json ├── index.md <-- overview: true ├── config │ ├── _meta.json │ ├── basic.mdx │ └── theme.mdx └── runtime ├── _meta.json ├── hooks.mdx └── context.mdx ``` ```mdx title="api/index.md" --- overview: true title: API Overview --- This is the API overview page. ``` ```json title="api/_meta.json" [ { "type": "file", "name": "index", "label": "API Overview" }, { "type": "dir", "name": "config", "label": "Config" }, { "type": "dir", "name": "runtime", "label": "Runtime" } ] ``` The generated Overview page looks like: # Overview page ## Config ### [basic](/#) - [title](/##title) - [description](/##description) ### [theme](/#) - [darkMode](/##dark-mode) - [footer](/##footer) ## Runtime ### [hooks](/#) - [usePage](/##use-page) - [useSite](/##use-site) ### [context](/#) - [DataContext](/##data-context) - [ThemeContext](/##theme-context) ## Configuration ### overviewHeaders Controls the heading levels displayed in the Overview page, defaults to `[2]` (only h2 headings). Can be configured in `_meta.json`: ```json title="_meta.json" [ { "type": "file", "name": "component", "overviewHeaders": [2, 3] } ] ``` Or in the article's frontmatter: ```md title="component.mdx" --- overviewHeaders: [2, 3] --- ``` ### Nested overview pages Subdirectories can also have their own Overview pages by configuring `overview: true` in the subdirectory's `index.md`: ```tree docs └── api ├── index.md <-- overview: true └── theme ├── index.md <-- overview: true (nested Overview page) ├── component.mdx └── utils.mdx ``` ## Customization If you need to fully customize the Overview page content, there are two approaches: ### Approach 1: customize styles via custom theme Use a [custom theme](https://rspress.rs/guide/basic/custom-theme.md) to modify the styles of the [OverviewGroup](https://rspress.rs/ui/layout-components/overview-group.md) component, while continuing to use the built-in Overview page functionality: ```mdx title="index.mdx" --- overview: true --- ``` ### Approach 2: fully custom page content Use the [OverviewGroup](https://rspress.rs/ui/layout-components/overview-group.md) component with `pageType: doc-wide` to adjust the page layout and define content yourself: ```mdx title="index.mdx" --- pageType: doc-wide --- # My custom overview page import { OverviewGroup } from '@rspress/core/theme'; ``` --- url: https://rspress.rs/guide/advanced/extend-build.md --- > 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. # Build extension ## Rsbuild Rspress builds docs with [Rsbuild](https://github.com/web-infra-dev/rsbuild). ### Configure Rsbuild Rsbuild provides a rich set of build options. Customize them through [builderConfig](https://rspress.rs/api/config/config-build.md#builderconfig). For example, change the output directory to `doc_dist`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ builderConfig: { output: { distPath: { root: 'doc_dist', }, }, }, }); ``` Rspress also provides [builderConfig.plugins](https://rspress.rs/api/config/config-build.md#builderconfigplugins) for registering Rsbuild plugins. Use Rsbuild's plugin ecosystem to extend build behavior. For example, add Google Analytics with [rsbuild-plugin-google-analytics](https://github.com/rstackjs/rsbuild-plugin-google-analytics): ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import { pluginGoogleAnalytics } from 'rsbuild-plugin-google-analytics'; export default defineConfig({ builderConfig: { plugins: [ pluginGoogleAnalytics({ // replace this with your Google tag ID id: 'G-xxxxxxxxxx', }), ], }, }); ``` :::tip Learn more in the [Rsbuild - Config](https://rsbuild.rs/config/) documentation. ::: ### Configure Rspack You can configure Rspack through the [tools.rspack](https://rsbuild.rs/config/tools/rspack) option provided by Rsbuild: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ builderConfig: { tools: { rspack(options) { // modify the rspack configuration }, }, }, }); ``` ## MDX compilation Rspress compiles MDX with [unified](https://github.com/unifiedjs/unified). Add related compilation plugins through the `markdown` configuration. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { remarkPlugins: [ [ require('remark-autolink-headings'), { behavior: 'wrap', }, ], ], rehypePlugins: [require('rehype-slug')], }, }); ``` --- url: https://rspress.rs/guide/advanced/custom-head.md --- > 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. # Customizing head tags / SEO Adding head tags (such as meta tags) to web pages is crucial for SEO optimization and social media sharing. For example, [Open Graph](https://ogp.me/) is a web metadata protocol that controls how pages appear when shared on social media platforms. Currently, Rspress automatically injects the following head tags: | Tag | Description | | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | | `` | Identifies the site generator and version | | `` | Page description, see [How description is determined](#how-description-is-determined) below | | `` | Open Graph type, fixed as `website` | | `` | Open Graph title, uses current page title (if available) | | `` | Open Graph description, same as above | | `` | Alternate language versions of the current page on multilingual sites | | `` | Performance optimization that preloads the current page's async route chunk | ## How description is determined By default, Rspress extracts the first contentful paragraph below the `h1` heading as the page description (see [`markdown.extractDescription`](https://rspress.rs/api/config/config-build.md#markdownextractdescription)). If the extracted result does not meet your needs, you can specify the `description` field in [frontmatter](https://rspress.rs/api/config/config-frontmatter.md#description) to override it: ```md title="example.mdx" --- description: Custom description for this page. --- ``` :::tip You can use the [rspress-description-generator](https://github.com/rstackjs/agent-skills#rspress-description-generator) agent skill to automatically generate descriptions for all pages. See [Agent Skills](https://rspress.rs/guide/start/ai.md#agent-skills) for more details. ::: If you want to add head tags, you can use the following methods: ## Global head configuration In `rspress.config.ts`, you can set HTML metadata (head tags) for all pages. See [Basic Config - head](https://rspress.rs/api/config/config-basic.md#head) for details. ## Frontmatter configuration You can modify the [title](https://rspress.rs/api/config/config-frontmatter.md#title) and [description](https://rspress.rs/api/config/config-frontmatter.md#description) fields in frontmatter to change the title and description of individual pages. ```md title="example.mdx" --- title: Custom Page Title description: Custom page description for meta description and Open Graph. --- ``` You can also use [frontmatter - head](https://rspress.rs/api/config/config-frontmatter.md#head) to customize page metadata tags for SEO optimization. For example, if you want to add `` to the `` tag, you can use frontmatter like this: ```md title="example.mdx" --- head: - - meta - property: og:title content: This is title - - meta - property: og:description content: This is description --- ``` You can use the same `head` frontmatter field to add a `` tag: ```md title="example.mdx" --- head: - - meta - name: keywords content: Rspress, React, static site generator --- ``` ## Head component If you need more complex head customization, you can use the [Head component](https://rspress.rs/ui/runtime-components/head.md) provided by Rspress to dynamically set head tags in pages or layout components. ## useHead hook If you are already inside a React component and prefer object-based declarations, use [`useHead`](https://rspress.rs/ui/hooks/use-head.md): ```tsx import { useHead } from '@rspress/core/runtime'; export function PageMeta() { useHead({ title: 'Custom Page Title', meta: [ { name: 'description', content: 'Custom page description for SEO and social sharing.', }, ], }); return null; } ``` Compared with `Head`, `useHead` is usually more convenient when the final tags depend on props, state, or reusable helper functions. ## Rsbuild html.tags configuration Through `builderConfig.html.tags`, you can inject custom content into HTML, such as adding analytics code, scripts, or styles: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ builderConfig: { html: { tags: [ { tag: 'script', attrs: { src: 'https://cdn.example.com/analytics.js', }, }, ], }, }, }); ``` For more configuration details, see the [Rsbuild html.tags documentation](https://rsbuild.rs/config/html/tags). :::tip Difference from Rspress head configuration - **Rspress head configuration**: Can access route-related information and dynamically set head tags for different pages. - **Rsbuild html.tags**: A static build-time configuration suitable for globally injecting the same tags, such as analytics code. If you need to dynamically adjust head content based on page routes, use [Global head configuration](#global-head-configuration), the [Head component](#head-component), or the [useHead hook](#usehead-hook). ::: --- url: https://rspress.rs/guide/advanced/custom-search.md --- > 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. # Customize search functions You may need to customize search behavior for scenarios such as: - Processing search keywords, such as removing sensitive words. - Filtering the default full-text search results. - Reporting the search keywords. - Customizing the search data source, such as searching from the database. - Rendering custom search data sources. Rspress provides interfaces for extending the default theme's search components so you can customize search behavior. ## Understanding `searchHooks` Use the `search.searchHooks` option in the Rspress config to register search component hooks: ```js import { defineConfig } from '@rspress/core'; import path from 'path'; export default defineConfig({ search: { searchHooks: path.join(__dirname, './search.tsx'), }, }); ``` The value of `search.searchHooks` is a file path. This file exports hook logic such as `onSearch`, allowing you to customize search at runtime. We call this file a **`searchHooks` module**. ## Hook functions in searchHooks The `searchHooks` module supports `beforeSearch`, `onSearch`, `afterRender`, and `render`. :::tip In the `searchHooks` module, export only the hook functions you need. ::: ### beforeSearch The `beforeSearch` hook runs before search starts. Use it to process or report search keywords. > This hook supports asynchronous operations. Example: ```ts import type { BeforeSearch } from '@rspress/core/theme'; const beforeSearch: BeforeSearch = (query: string) => { // Do something before search console.log('beforeSearch'); // Return the processed query return query.replace(' ', ''); }; export { beforeSearch }; ``` ### onSearch The `onSearch` hook runs after the default full-text search finishes. Use it to filter or report search results, or to add a custom search data source. > This hook supports asynchronous operations. Example: ```ts import type { OnSearch } from '@rspress/core/theme'; import { RenderType } from '@rspress/core/theme'; const onSearch: OnSearch = async (query, defaultSearchResult) => { // Request data based on query console.log(query); // The results of the default search source, which is an array console.log(defaultSearchResult); // const customResult = await searchQuery(query); // Operate on the default search results directly. defaultSearchResult.pop(); // The return value is an array. Each item is a search source result that is added to the final search result. return [ { group: 'Custom', result: { list: [ { title: 'Search Result 1', path: '/search1', }, { title: 'Search Result 2', path: '/search2', }, ], }, renderType: RenderType.Custom, }, ]; }; export { onSearch }; ``` The `onSearch` hook returns an array of search source results. Each item has the following structure: ```ts { group: string; // The search result group name displayed in the UI. result: unknown; renderType: RenderType; // The type of the search result, which can be `RenderType.Default` or `RenderType.Custom`. `RenderType.custom` by default. } ``` `result` is the search result and can have any structure you need. `renderType` controls how the result is rendered. When it is `RenderType.Default`, Rspress uses the default rendering logic. When it is `RenderType.Custom`, Rspress uses the `render` function. ### afterSearch The `afterSearch` hook runs after search results are rendered. Use it to access the final search keywords and results. > This hook supports asynchronous operations. Example: ```ts import type { AfterSearch } from '@rspress/core/theme'; const afterSearch: AfterSearch = async (query, searchResult) => { // Search keyword console.log(query); // Search result console.log(searchResult); }; export { afterSearch }; ``` ### render The `render` function will render the custom search source data in your `onSearch` hook. Therefore, it generally needs to be used together with `onSearch`. Here's how to use it: ```tsx import type { RenderSearchFunction } from '@rspress/core/theme'; // The above OnSearch hook implementation is skipped interface ResultData { list: { title: string; path: string; }[]; } // The render function for each search source const render: RenderSearchFunction = item => { return (
{item.list.map(i => ( ))}
); }; export { onSearch, render }; ``` The result is as follows: ![Custom Search Source Rendering](https://lf3-static.bytednsdoc.com/obj/eden-cn/uhbfnupenuhf/rspress/custom-search-preview.png) --- url: https://rspress.rs/guide/migration/rspress-1-x.md --- > 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. # Migrating from Rspress 1.x This document will help you migrate from Rspress 1.x to Rspress V2. We recommend using the "Copy as Markdown" feature to pass this document to an LLM for automated migration assistance. ## Quick migration checklist - [ ] **Node.js** ^20.19.0 || >=22.12.0 - [ ] **Dependencies**: `rspress` → `@rspress/core`, remove `@rspress/shared` - [ ] **Import paths**: `rspress/runtime` → `@rspress/core/runtime`, `rspress/theme` → `@rspress/core/theme` - [ ] **Custom themes**: Change default exports to named exports, use `@rspress/core/theme-original` - [ ] **Top-level navigation**: `_meta.json` → `_nav.json` (top-level only) - [ ] **Code highlighting**: Prism → Shiki, line highlight syntax `{1,3-4}` requires transformer config - [ ] **builderPlugins**: Move to `builderConfig.plugins` - [ ] **Sass/Less**: Manually install `@rsbuild/plugin-sass` or `@rsbuild/plugin-less` - [ ] **External code blocks**: `` → ` ```tsx file="..." ` - [ ] **markdown.mdxRs**: Remove the `markdown.mdxRs` option (no longer supported) - [ ] **themeConfig.locales**: Remove `outlineTitle` and other text configs, use `i18nSource` instead ## \[Important] Node.js and upstream dependency requirements ### Node.js Version Rspress V2 no longer supports Node.js 16 and 18. Please upgrade to **Node.js ^20.19.0 || >=22.12.0**. Node.js 22 LTS is recommended. ### Upstream dependency versions | Dependency | Allowed Range | Default | Notes | | ------------------ | ---------------------- | ------- | ----------------------------------------------- | | `react` | `^18.0.0 \|\| ^19.0.0` | 19 | React 17 is no longer supported | | `react-dom` | `^18.0.0 \|\| ^19.0.0` | 19 | Keeps in sync with react version | | `react-router-dom` | `^6.0.0 \|\| ^7.0.0` | 7 | Uses project version if already installed | | `unified` | `^11.0.0` | 11 | Custom remark/rehype plugins must be compatible | :::tip If `react`, `react-dom`, or `react-router-dom` is already installed in your project, Rspress will use the project's version instead of the built-in default version. ::: ## \[Important] Package name and import path changes Rspress V2 consolidates multiple packages into `@rspress/core`. The original `rspress` package is no longer used. - before: ```json title="package.json" { "dependencies": { "rspress": "^1.x", "@rspress/shared": "^1.x" } } ``` - after: ```json title="package.json" { "dependencies": { "@rspress/core": "^2.0.0" } } ``` If you developed an Rspress plugin, change the plugin's peerDependencies from `rspress` to `@rspress/core`: ```json title="package.json" { "peerDependencies": { "@rspress/core": "^2.0.0" } } ``` ### Import path changes | Old Path | New Path | | ---------------------------- | ----------------------------------------------------- | | `rspress` / `rspress/config` | `@rspress/core` | | `rspress/runtime` | `@rspress/core/runtime` | | `rspress/theme` | Use `@rspress/core/theme` in docs directory | | `@rspress/theme-default` | Use `@rspress/core/theme-original` in theme directory | We recommend using a global find-and-replace to update import paths. Example: - before: ```ts import { usePageData, useDark } from 'rspress/runtime'; import type { RspressPlugin } from 'rspress'; ``` - after: ```ts import { usePageData, useDark } from '@rspress/core/runtime'; import type { RspressPlugin } from '@rspress/core'; ``` ### Removed standalone packages The following packages are now built into `@rspress/core`. If you are upgrading from 1.x, use the import path changes table above to update your import paths: - `rspress` - Renamed to `@rspress/core` - `@rspress/runtime` - Runtime is built-in - `@rspress/theme-default` - Default theme is built-in - `@rspress/plugin-shiki` - Shiki code highlighting is now default - `@rspress/plugin-auto-nav-sidebar` - Navigation sidebar is built-in - `@rspress/plugin-container-syntax` - Container syntax is built-in - `@rspress/plugin-last-updated` - Last updated time is built-in - `@rspress/plugin-medium-zoom` - Image zoom is built-in ## \[Important] Custom theme ESM export changes Custom themes no longer use default exports. Use named exports instead. - before: ```tsx title="theme/index.tsx" import Theme from 'rspress/theme'; const Layout = () => content} />; export default { ...Theme, Layout }; export * from 'rspress/theme'; ``` - after: ```tsx title="theme/index.tsx" import { Layout as BasicLayout } from '@rspress/core/theme-original'; const Layout = () => content} />; export { Layout }; export * from '@rspress/core/theme-original'; ``` ### Theme import paths | Context | Import Path | Description | | ---------------- | --------------------------------- | --------------------------------------------------------- | | `theme` folder | `@rspress/core/theme-original` | Use when customizing theme, get original theme components | | `docs` directory | `@rspress/core/theme` or `@theme` | Use theme components in docs, supports theme override | Using theme components in MDX files within the `docs` directory: ```tsx title="docs/guide/index.mdx" import { PackageManagerTabs } from '@rspress/core/theme'; // Or use alias import { PackageManagerTabs } from '@theme'; ``` If using the `@theme` alias, add path mapping in `tsconfig.json` for type hints: ```json title="tsconfig.json" { "compilerOptions": { "paths": { "@theme": ["./theme/index.tsx"] } } } ``` :::tip If you encounter errors about missing exports from `@theme` or `@rspress/core/theme`, it's likely because you didn't use `@rspress/core/theme-original` when overriding the theme in the theme folder, causing a circular reference: ```txt × ESModulesLinkingError: export 'SvgWrapper' (imported as 'SvgWrapper') was not found in '@theme' (possible exports: HomeLayout, Layout, Search, Tag, getCustomMDXComponent) × ESModulesLinkingError: export 'Banner' (imported as 'Banner') was not found in '@rspress/core/theme' (possible exports: HomeLayout, Layout, Search, Tag, getCustomMDXComponent) ``` Make sure to use `@rspress/core/theme-original` in the `theme` folder and correctly export all components. ::: ## \[Important] Shiki code highlighting replaces prism Rspress V2 uses Shiki v3 for code highlighting by default. Prism has been removed. For the list of languages supported by Shiki, see [Shiki Languages](https://shiki.style/languages). For more Shiki usage, see the [Code Blocks documentation](https://rspress.rs/guide/use-mdx/code-blocks.md). ### Configuration migration - before: Configure language aliases via highlightLanguages: ```ts title="rspress.config.ts" import { defineConfig } from 'rspress/config'; export default defineConfig({ markdown: { highlightLanguages: [['ejs', 'javascript']], }, }); ``` - after: Configure `langAlias` and other Shiki options via [markdown.shiki](https://rspress.rs/api/config/config-build.md#markdownshiki): ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { shiki: { langAlias: { ejs: 'javascript', }, }, }, }); ``` ### Line highlighting syntax changes V2 no longer includes the `{1,3-4}` meta line highlighting syntax by default. Choose from the following options based on your needs: - **[Notation Line Highlight](https://rspress.rs/guide/use-mdx/code-blocks.md#notation-line-highlight)**: Uses `// [!code highlight]` comment syntax, requires `transformerNotationHighlight` configuration - **[Meta Line Highlight](https://rspress.rs/guide/use-mdx/code-blocks.md#meta-line-highlight)**: Compatible with legacy `{1,3-4}` syntax, requires `transformerCompatibleMetaHighlight` configuration To maintain compatibility with V1's meta line highlighting syntax, add the following configuration: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import { transformerCompatibleMetaHighlight } from '@rspress/core/shiki-transformers'; export default defineConfig({ markdown: { shiki: { transformers: [transformerCompatibleMetaHighlight()], }, }, }); ``` ## \[Important] Top-level Navigation file renamed Rspress V2 separates nav and sidebar configuration. The top-level `_meta.json` needs to be renamed to `_nav.json`, while inner files remain unchanged. - before: ``` docs/ ├── en/ │ ├── _meta.json # Top-level navigation │ └── guide/ │ └── _meta.json # Inner sidebar ``` - after: ``` docs/ ├── en/ │ ├── _nav.json # Top-level navigation (renamed) │ └── guide/ │ └── _meta.json # Inner sidebar (unchanged) ``` ## \[Important] SSG strict mode by default SSG is now in strict mode by default. On failure, the build exits immediately instead of falling back to CSR. The `ssg.strict` configuration has been removed. To skip SSG, set `ssg: false`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ ssg: false, }); ``` ## \[Important] Features enabled by default The following features are enabled by default in V2: | Feature | Description | | ------------------------------ | -------------------------------------------------- | | `markdown.link.checkDeadLinks` | Dead link checking, fix broken links based on logs | | `search.codeBlocks` | Search results include code blocks | | `dev.lazyCompilation` | Lazy compilation for faster dev startup | | `performance.buildCache` | Persistent cache for faster builds | :::tip If you encounter dead link errors, try to fix the broken links rather than disabling the `markdown.link.checkDeadLinks` feature. ::: To disable lazy compilation: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ builderConfig: { dev: { lazyCompilation: false, }, }, }); ``` ## base configuration reimplemented The `base` configuration is now implemented using react-router's `basename`. Key changes: - `useLocation().pathname` no longer includes the `base` prefix - Use `Link` / `useNavigate` for navigation instead of directly manipulating `window.location` ## `cleanUrls: true` Links are shortened When `cleanUrls: true`, generated links no longer include the `/index` suffix. - before: `/guide/index` - after: `/guide/` ## builderPlugins configuration removed `builderPlugins` has been removed. Please migrate to `builderConfig.plugins`. - before: ```ts title="rspress.config.ts" import { defineConfig } from 'rspress/config'; export default defineConfig({ builderPlugins: [pluginFoo()], }); ``` - after: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ builderConfig: { plugins: [pluginFoo()], }, }); ``` ## `markdown.mdxRs` option removed The `markdown.mdxRs` option has been removed in V2. Rspress no longer uses the Rust-based MDX parser (`@rspress/mdx-rs`). Please remove the `markdown.mdxRs` option from your configuration. Leaving this option in your configuration will cause TypeScript type checking errors, but it does not affect runtime behavior. - before: ```ts title="rspress.config.ts" import { defineConfig } from 'rspress/config'; export default defineConfig({ markdown: { mdxRs: false, remarkPlugins: [plugin1, plugin2], }, }); ``` - after: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { // mdxRs option removed, no replacement needed remarkPlugins: [plugin1, plugin2], }, }); ``` ## Sass/Less Requires manual installation Built-in Sass/Less plugins have been removed. Install them manually if needed: ```bash # Sass npm add @rsbuild/plugin-sass -D # Less npm add @rsbuild/plugin-less -D ``` Then register in configuration: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import { pluginSass } from '@rsbuild/plugin-sass'; export default defineConfig({ builderConfig: { plugins: [pluginSass()], }, }); ``` ## External code block syntax changed External code block syntax has changed: - before: ```tsx ``` - after: ````md ```tsx file="./example.tsx" ``` ```` ## Relative link resolution changed Relative links no longer require the `./` prefix. The following two syntaxes are now equivalent: ```md [subfolder](subfolder) [subfolder](./subfolder) ``` ## MDX file route exclusion Files starting with underscore `_` are automatically excluded from routing, suitable for MDX fragments and React components. ``` docs/ ├── guide/ │ ├── _components.tsx # Will not generate route │ └── index.mdx ``` ## Theme style changes ### Tailwind class name prefix Built-in theme class names now have a Tailwind prefix to avoid conflicts. If you rely on classes like `dark:hidden`, configure Tailwind/UnoCSS in your project. ### Native HTML tag styling Native HTML tags now have document styling by default. To isolate styling, add the `.rp-not-doc` class: ```html
``` ### Built-in Multilingual text The default theme now includes built-in multilingual translation text with tree-shaking support based on your project's configured languages. Key changes: - If your documentation only includes `en` and `zh`, only those languages will be bundled - For languages not supported by Rspress, it automatically falls back to `en` - In most cases, you don't need to manually configure i18n text The following `themeConfig.locales` text configurations have been removed. Please delete related configurations: - `outlineTitle` - `lastUpdatedText` - `editLink.text` - `prevPageText` - `nextPageText` - `sourceCodeText` - `searchPlaceholderText` - `searchNoResultsText` - `searchSuggestedQueryText` - `overview.filterNameText` - `overview.filterPlaceholderText` - `overview.filterNoResultText` - before: ```ts title="rspress.config.ts" import { defineConfig } from 'rspress/config'; export default defineConfig({ themeConfig: { locales: [ { lang: 'en', label: 'English', outlineTitle: 'ON THIS PAGE', }, { lang: 'zh', label: '中文', outlineTitle: '目录', }, ], }, }); ``` - after: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ locales: [ { lang: 'en', label: 'English', }, { lang: 'zh', label: '中文', }, ], // Only use i18nSource when you want to modify built-in text i18nSource: { outlineTitle: { zh: '大纲', en: 'On This Page', }, }, }); ``` ## plugin-preview `@rspress/plugin-preview` V2 no longer includes `@rsbuild/plugin-less` and `@rsbuild/plugin-sass` as built-in dependencies. If you need Less or Sass support in previews, install the corresponding plugin and configure it via `iframeOptions.builderConfig`: ```sh [npm] npm add @rsbuild/plugin-less -D ``` ```sh [yarn] yarn add @rsbuild/plugin-less -D ``` ```sh [pnpm] pnpm add @rsbuild/plugin-less -D ``` ```sh [bun] bun add @rsbuild/plugin-less -D ``` ```sh [deno] deno add npm:@rsbuild/plugin-less -D ``` ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import { pluginPreview } from '@rspress/plugin-preview'; import { pluginLess } from '@rsbuild/plugin-less'; export default defineConfig({ plugins: [ pluginPreview({ iframeOptions: { builderConfig: { plugins: [pluginLess()], }, }, }), ], }); ``` For more migration details, see [plugin-preview migration guide](https://rspress.rs/plugin/official-plugins/preview.md#migrating-from-v1). ## Resources - [GitHub Discussion: Rspress v2 Breaking Changes](https://github.com/web-infra-dev/rspress/discussions/1891) --- url: https://rspress.rs/plugin/system/introduction.md --- > 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. # Introduction The plugin system is a core part of Rspress. It lets you extend Rspress during the site build process. First, let's look at the overall Rspress architecture. The overall architecture of Rspress is shown in the figure below: ![Rspress Architecture](https://assets.rspack.rs/rspress/assets/rspress-architecture.png) Rspress has two main parts: **Node Side** and **Browser Runtime**. The plugin system lets you extend both parts. Specifically, plugins can: - Extend [**Markdown/MDX compilation**](https://rspress.rs/plugin/system/plugin-api.md#markdown) by adding [`remark`](https://github.com/remarkjs/remark) or [`rehype`](https://github.com/rehypejs/rehype) plugins. - [**Add custom pages**](https://rspress.rs/plugin/system/plugin-api.md#addpages) on top of Rspress's conventional routing, such as a `/blog` route that renders a custom blog list. - [**Customize build tool behavior**](https://rspress.rs/plugin/system/plugin-api.md#builderconfig) by modifying the underlying [Rsbuild](https://rsbuild.rs) config or adding Rspack/Rsbuild plugins. - [**Extend page metadata**](https://rspress.rs/plugin/system/plugin-api.md#extendpagedata). Rspress calculates metadata such as `title` and `description` for each page. Plugins can extend that logic, and theme code can read the result with [usePageData](https://rspress.rs/ui/hooks/use-page-data.md). - Run [**custom logic**](https://rspress.rs/plugin/system/plugin-api.md#beforebuildafterbuild) before and after builds, such as closing event listeners after a build ends. - [**Add global components**](https://rspress.rs/plugin/system/plugin-api.md#globaluicomponents). Since Rspress renders with React, plugins can add global React components such as a BackToTop component or global side-effect component. --- url: https://rspress.rs/plugin/system/write-a-plugin.md --- > 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. # Write a plugin This example injects a global component to show how to define and use plugins. ### 1. Define a plugin ```tsx title="plugin.ts" import type { RspressPlugin } from '@rspress/core'; export function pluginExample(slug: string): RspressPlugin { // Component path. You need to implement the component yourself. const componentPath = path.join(__dirname, 'Example.tsx'); return { name: 'plugin-example', // Path to global components globalUIComponents: [componentPath], // Global variable definitions for build phase builderConfig: { source: { define: { 'process.env.SLUG': JSON.stringify(slug), }, }, }, }; } ``` ```tsx title="Example.tsx" import React from 'react'; const Example = () => { console.log(process.env.SLUG); return
Example
; }; export default Example; ``` A plugin is usually a function that receives optional plugin parameters and returns an object containing the plugin name and other config. In the example above, we define a plugin named `plugin-example`. It defines a global environment variable, `process.env.SLUG`, during the build phase and injects the global component `Example.tsx` into the page. ### 2. Use a plugin Register plugins via `plugins` in `rspress.config.ts`: ```tsx title="rspress.config.ts" import { pluginExample } from './plugin'; export default { plugins: [pluginExample('test')], }; ``` The `Example` component is then injected into the page, and the component can access `process.env.SLUG`. --- url: https://rspress.rs/plugin/system/plugin-api.md --- > 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
This is a global layout component
; } ``` 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` 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` 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` ```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
{page.a}
; } ``` ### addPages - **Type**: `(config: UserConfig) => AdditionalPage[] | Promise` 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` 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 | Promise>;` 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
{myData.a}
; } ``` :::tip TIP This hook is executed after the `routeGenerated` hook. ::: ### i18nSource - **Type**: `(source: Record>) => Record> | Promise>>` 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
{t('customKey')}
; } ``` --- url: https://rspress.rs/plugin/official-plugins/overview.md --- > 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. # Overview ## Official plugins Official plugins include: - [@rspress/plugin-algolia](https://rspress.rs/plugin/official-plugins/algolia.md): Replace Rspress built-in search with [Algolia](https://www.algolia.com/) based on [DocSearch](https://docsearch.algolia.com). - [@rspress/plugin-api-docgen](https://rspress.rs/plugin/official-plugins/api-docgen.md): Integrate [react-docgen-typescript](https://github.com/styleguidist/react-docgen-typescript) and [documentation](https://github.com/documentationjs/documentation) to generate API reference content automatically. - [@rspress/plugin-client-redirects](https://rspress.rs/plugin/official-plugins/client-redirects.md): Add client-side redirects. - [@rspress/plugin-llms](https://rspress.rs/plugin/official-plugins/llms.md): Generate [llms.txt](https://llmstxt.org/) related files for your Rspress site so large language models can better understand your documentation. - [@rspress/plugin-playground](https://rspress.rs/plugin/official-plugins/playground.md): Provide a real-time playground for Markdown/MDX code blocks. - [@rspress/plugin-preview](https://rspress.rs/plugin/official-plugins/preview.md): Preview Markdown/MDX code blocks. - [@rspress/plugin-rss](https://rspress.rs/plugin/official-plugins/rss.md): Generate RSS files for a documentation site with [feed](https://github.com/jpmonette/feed). - [@rspress/plugin-sitemap](https://rspress.rs/plugin/official-plugins/sitemap.md): Generate a [sitemap](https://developers.google.com/search/docs/crawling-indexing/sitemaps/overview) automatically for SEO and search engine crawling. - [@rspress/plugin-twoslash](https://rspress.rs/plugin/official-plugins/twoslash.md): Integrate [Twoslash](https://github.com/twoslashes/twoslash) to automatically generate rich code blocks with type information. - [@rspress/plugin-typedoc](https://rspress.rs/plugin/official-plugins/typedoc.md): Integrate [TypeDoc](https://github.com/TypeStrong/typedoc) to generate API documentation for TypeScript modules automatically. --- url: https://rspress.rs/plugin/official-plugins/llms.md --- > 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. # @rspress/plugin-llms [Source Code](https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-llms) Generate [llms.txt](https://llmstxt.org/) related files for your Rspress site so large language models can better understand your documentation. :::warning `@rspress/plugin-llms` uses remark to process MDX source files, so it does not support rendering dynamic content such as React Hooks or custom components. This plugin is intended only as a fallback when SSG and SSG-MD cannot be enabled because the code is incompatible with SSR. Prefer the [SSG-MD](https://rspress.rs/guide/basic/ssg-md.md) feature when possible. ::: ## Installation ```sh [npm] npm add @rspress/plugin-llms -D ``` ```sh [yarn] yarn add @rspress/plugin-llms -D ``` ```sh [pnpm] pnpm add @rspress/plugin-llms -D ``` ```sh [bun] bun add @rspress/plugin-llms -D ``` ```sh [deno] deno add npm:@rspress/plugin-llms -D ``` ## Usage ### 1. Install the plugin Add the following configuration: ```ts // rspress.config.ts import { defineConfig } from '@rspress/core'; import { pluginLlms } from '@rspress/plugin-llms'; export default defineConfig({ plugins: [pluginLlms()], }); ``` Then run `rspress build`. During output generation, the plugin also generates `llms.txt`, `llms-full.txt`, and corresponding Markdown files for each route in the output directory, based on the navbar and sidebar. ### 2. UI display To help readers use your documentation with large language models, add a copy Markdown button at the top of the page, similar to this website. #### Using themeConfig (Recommended) The simplest way is to enable `llmsUI` in `themeConfig`. This will automatically add `LlmsCopyButton` and `LlmsViewOptions` components below all H1 headers (or in the outline panel) without requiring custom theme code: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import { pluginLlms } from '@rspress/plugin-llms'; export default defineConfig({ plugins: [pluginLlms()], themeConfig: { llmsUI: true, // Or with custom options: // llmsUI: { // injectLlmsHint: false, // Disable the HTML/Markdown directive hint for LLMs // viewOptions: ['markdownLink', 'chatgpt', 'claude'], // placement: 'outline', // Display in outline panel instead of below H1 // }, }, }); ``` #### Using custom theme If you need more control, you can use [custom theme](https://rspress.rs/guide/basic/custom-theme.md) to add a copy Markdown button. Add a copy button to all pages: ```tsx title="theme/index.tsx" import { getCustomMDXComponent as basicGetCustomMDXComponent } from '@rspress/core/theme-original'; import { LlmsContainer, LlmsCopyButton, LlmsViewOptions, } from '@rspress/plugin-llms/runtime'; function getCustomMDXComponent() { const { h1: H1, ...mdxComponents } = basicGetCustomMDXComponent(); const MyH1 = ({ ...props }) => { return ( <>

{/* [!code highlight:5] */} {/* Add LlmsViewOptions as needed */} ); }; return { ...mdxComponents, h1: MyH1, }; } export { getCustomMDXComponent }; export * from '@rspress/core/theme-original'; ``` Add a copy button to specific pages: ```mdx title="docs/hello-world.mdx" # Hello world {/* Add LlmsViewOptions as needed */} This is a sample document. ``` ## Configuration This plugin accepts an options object with the following type: - **Type**: ```ts interface LlmsTxt { name: string; onTitleGenerate?: (context: { title: string | undefined; description: string | undefined; }) => string; onLineGenerate?: (page: PageIndexInfo) => string; onAfterLlmsTxtGenerate?: (llmsTxtContent: string) => string; } interface MdFiles { mdxToMd?: boolean; remarkPlugins?: PluggableList; } interface LlmsFullTxt { name: string; } export interface Options { llmsTxt?: false | LlmsTxt; mdFiles?: false | MdFiles; llmsFullTxt?: false | LlmsFullTxt; include?: (context: { page: PageIndexInfo }) => boolean; exclude?: (context: { page: PageIndexInfo }) => boolean; } ``` - **Default**: When [internationalization](https://rspress.rs/guide/basic/i18n.md) is not enabled, the default value is: ```ts { llmsTxt: { name: 'llms.txt' }, llmsFullTxt: { name: 'llms-full.txt' }, mdFiles: true } ``` When [internationalization](https://rspress.rs/guide/basic/i18n.md) is enabled, it will use [multiple configurations](#group), with the default value being: ```ts [ { llmsTxt: { name: 'llms.txt' }, llmsFullTxt: { name: 'llms-full.txt' }, mdFiles: true, include: ({ page }) => page.lang === config.lang, }, // Automatically generate other languages based on locales configuration { llmsTxt: { name: `${lang}/llms.txt` }, llmsFullTxt: { name: `${lang}/llms-full.txt` }, mdFiles: true, include: ({ page }) => page.lang === lang, }, // ... ]; ``` ### llmsTxt - **Type**: `false | LlmsTxt` ```ts import type { PageIndexInfo } from '@rspress/core'; export interface LlmsTxt { name: string; onTitleGenerate?: (context: { title: string | undefined; description: string | undefined; }) => string; onLineGenerate?: (page: PageIndexInfo) => string; onAfterLlmsTxtGenerate?: (llmsTxtContent: string) => string; } ``` - **Default**: `{ name: 'llms.txt' }` Controls whether to generate the `llms.txt` file, or customizes it through hooks. The default format of an llms.txt file is as follows: ```markdown # {title} > {description} ## {nav1.title} - [{page.title}]({ page.routePath }): {page.frontmatter.description} ## {nav2.title} - [{page.title}]({ page.routePath }): {page.frontmatter.description} ``` You can modify specific parts through hooks: - `onTitleGenerate`: Customize the generated title and description sections. - `onLineGenerate`: Customize each line of the Markdown file. - `onAfterLlmsTxtGenerate`: Modify the final contents of the `llms.txt` file. For example: ```ts pluginLlms({ llmsTxt: { onTitleGenerate: ({ title, description }) => { return `# ${title} - llms.txt > ${description} Rspress is a static site generator based on Rsbuild and it can generate llms.txt with @rspress/plugin-llms. `; }, }, }); ``` The generated result is: ```markdown # Rspress - llms.txt > Rsbuild based static site generator Rspress is a static site generator based on Rsbuild and it can generate llms.txt with @rspress/plugin-llms. ## guide - [foo](/foo.md) ``` ### mdFiles - **Type**: `false | MdFiles` ```ts export interface MdFiles { mdxToMd?: boolean; remarkPlugins?: PluggableList; } ``` - **Default**: `{ mdxToMd: false, remarkPlugins: [] }` Controls whether to generate a Markdown file for the corresponding route. When set to `false`, the Markdown file for that route is not generated. #### mdxToMd - **Type**: `boolean` - **Default**: `false` Controls whether to convert MDX content to Markdown. If enabled, MDX files are converted to Markdown files through a set of default strategies, but some information may be lost. #### remarkPlugins - **Type**: `PluggableList` - **Default**: `[]` You can pass in custom remark plugins to modify the Markdown content. ### llmsFullTxt - **Type**: `false | LlmsFullTxt` ```ts export interface LlmsFullTxt { name: string; } ``` - **Default**: `{ name: 'llms-full.txt' }` Controls whether to generate `llms-full.txt`. When set to `false`, `llms-full.txt` is not generated. ### include - **Type**: `(context: { page: PageIndexInfo }) => boolean` Controls which pages are included during generation. This is usually used to simplify `llms.txt`. - Example: Generate `llms.txt` and other related files for pages whose language is English only: ```ts pluginLlms({ llmsTxt: { name: 'llms.txt', }, llmsFullTxt: { name: 'llms-full.txt', }, include: ({ page }) => { return page.lang === 'en'; }, }); ``` ### exclude - **Type**: `(context: { page: PageIndexInfo }) => boolean` Controls which pages are excluded. This runs after `include`. - Example: Exclude a single page under the `/foo` route: ```ts pluginLlms({ llmsTxt: { name: 'llms.txt', }, llmsFullTxt: { name: 'llms-full.txt', }, exclude: ({ page }) => { return page.routePath === '/foo'; }, }); ``` ## UI component props ### LlmsCopyButtonProps - **Type**: `LlmsCopyButtonProps` ```ts interface LlmsCopyButtonProps extends React.ButtonHTMLAttributes {} ``` ### LlmsViewOptionsProps - **Type**: `LlmsViewOptionsProps` ```ts type LlmsViewOptionsItem = | { title: string; icon?: React.ReactNode; onClick?: () => void; } | { title: string; href: string; icon?: React.ReactNode; } | 'markdownLink' | 'chatgpt' | 'claude'; interface LlmsViewOptionsProps extends React.ButtonHTMLAttributes { options?: LlmsViewOptionsItem[]; } ``` #### options - **Type**: `LlmsViewOptionsItem[]` ```ts type LlmsViewOptionsItem = | { title: string; icon?: React.ReactNode; onClick?: () => void; } | { title: string; href: string; icon?: React.ReactNode; } | 'markdownLink' | 'chatgpt' | 'claude'; ``` - **Default**: `['markdownLink', 'chatgpt', 'claude']` Customizes the options in the dropdown menu. By default, it supports "Copy Markdown Link", [ChatGPT](https://chatgpt.com/), and [Claude](https://claude.ai). ## Generate multiple groups of `llms.txt` at the same time \{#group} In some cases, such as i18n sites, you may need to generate multiple `llms.txt` groups. Pass an array to do this. - Example: ```ts // rspress.config.ts import { defineConfig } from '@rspress/core'; defineConfig({ lang: 'en', plugins: [ pluginLlms([ { llmsTxt: { name: 'llms.txt', }, llmsFullTxt: { name: 'llms-full.txt', }, include: ({ page }) => page.lang === 'en', }, { llmsTxt: { name: 'zh/llms.txt', }, llmsFullTxt: { name: 'zh/llms-full.txt', }, include: ({ page }) => page.lang === 'zh', }, ]), ], }); ``` --- url: https://rspress.rs/plugin/official-plugins/sitemap.md --- > 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. # @rspress/plugin-sitemap [Source Code](https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-sitemap) Automatically generate a [sitemap](https://developers.google.com/search/docs/crawling-indexing/sitemaps/overview) for SEO so search engines can crawl your site more easily. ## Installation ```sh [npm] npm add @rspress/plugin-sitemap -D ``` ```sh [yarn] yarn add @rspress/plugin-sitemap -D ``` ```sh [pnpm] pnpm add @rspress/plugin-sitemap -D ``` ```sh [bun] bun add @rspress/plugin-sitemap -D ``` ```sh [deno] deno add npm:@rspress/plugin-sitemap -D ``` ## Usage Add the following configuration in `rspress.config.ts`: ```ts // rspress.config.ts import path from 'path'; import { defineConfig } from '@rspress/core'; import { pluginSitemap } from '@rspress/plugin-sitemap'; export default defineConfig({ plugins: [ pluginSitemap({ siteUrl: 'https://example.com', // Replace with your site URL }), ], }); ``` ## Configuration This plugin accepts an options object with the following type: ```ts 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 PluginSitemapOptions { siteUrl?: string; customMaps?: CustomMaps; defaultPriority?: Priority; defaultChangeFreq?: ChangeFreq; } ``` ### siteUrl - **Type**: `string` - **Default**: [`siteOrigin`](https://rspress.rs/api/config/config-basic.md#siteorigin) + [`base`](https://rspress.rs/api/config/config-basic.md#base), or `base` when `siteOrigin` is not configured The site URL for deployment access, for example `https://example.com`. Sitemap `` entries should be absolute URLs with protocol and domain, such as `https://example.com/base/`. When `base` is configured, plugin-level `siteUrl` must include the `base` path. If [`siteOrigin`](https://rspress.rs/api/config/config-basic.md#siteorigin) and [`base`](https://rspress.rs/api/config/config-basic.md#base) are configured in Rspress, you can omit the plugin-level `siteUrl`. The full URL concatenation order is `siteOrigin + base + routePath`. If neither plugin-level `siteUrl` nor `siteOrigin` is configured, the plugin falls back to `base`, which keeps existing relative path behavior but does not generate absolute sitemap URLs. ```ts // rspress.config.ts import path from 'path'; import { defineConfig } from '@rspress/core'; import { pluginSitemap } from '@rspress/plugin-sitemap'; export default defineConfig({ siteOrigin: 'https://example.com', base: '/base/', plugins: [ // siteUrl defaults to 'https://example.com/base/' pluginSitemap(), ], }); ``` ### customMaps - **Type**: ```ts interface Sitemap { loc: string; lastmod?: string; changefreq?: ChangeFreq; priority?: Priority; } interface CustomMaps { [routePath: string]: Sitemap; } ``` - **Default**: `{}` Sets custom sitemap values for specific important pages. ### defaultChangeFreq - **Type**: `ChangeFreq` - **Default**: `'monthly'` - **Options**: `"always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never"` > changefreq: How frequently the page is likely to change. This value provides general information to search engines and may not correlate exactly to how often they crawl the page. Sets the default [changefreq](https://www.sitemaps.org/protocol.html) value for each page in the generated sitemap file. ### defaultPriority - **Type**: `Priority` - **Default**: `'0.5'` - **Options**: `"0.0" | "0.1" | "0.2" | "0.3" | "0.4" | "0.5" | "0.6" | "0.7" | "0.8" | "0.9" | "1.0"` > priority: The priority of this URL relative to other URLs on your site. Sets the default [priority](https://www.sitemaps.org/protocol.html) value for each page in the generated sitemap file. --- url: https://rspress.rs/plugin/official-plugins/client-redirects.md --- > 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. # @rspress/plugin-client-redirects [Source Code](https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-client-redirects) Used for client redirects. :::warning Before using this plugin, make sure your deployment environment has the fallback page correctly configured. See the [SSG refresh-404 guide](https://rspress.rs/guide/basic/ssg.md#refresh-404) for details. Note: Client-side redirects differ from server-side redirects — the page will load first and then redirect (causing a brief flash), and SSR is not supported. If your deployment platform supports server-side redirects (301/302), prefer using that approach for better SEO and user experience. ::: ## Installation ```sh [npm] npm add @rspress/plugin-client-redirects -D ``` ```sh [yarn] yarn add @rspress/plugin-client-redirects -D ``` ```sh [pnpm] pnpm add @rspress/plugin-client-redirects -D ``` ```sh [bun] bun add @rspress/plugin-client-redirects -D ``` ```sh [deno] deno add npm:@rspress/plugin-client-redirects -D ``` ## Usage Write the following configuration in the configuration file: ```ts title="rspress.config.ts" import { pluginClientRedirects } from '@rspress/plugin-client-redirects'; import { defineConfig } from '@rspress/core'; export default defineConfig({ plugins: [ pluginClientRedirects({ redirects: [ { from: '/docs/old1', to: '/docs/new1', }, ], }), ], }); ``` ## Configuration This plugin supports passing in an object configuration. The properties of this object configuration are as follows: ```ts type RedirectRule = { from: string | string[]; to: string; }; type RedirectsOptions = { redirects?: RedirectRule[]; }; ``` `from` represents the matching path, `to` represents the path to be redirected, and using regular expression strings is supported. :::note One `to` supports matching multiple `from`: they will redirect to a single path. One `from` cannot correspond to multiple `to`: there needs to be a unique and clear redirection path. ::: ## Example ```ts import path from 'node:path'; import { defineConfig } from '@rspress/core'; import { pluginClientRedirects } from '@rspress/plugin-client-redirects'; export default defineConfig({ root: path.join(__dirname, 'doc'), plugins: [ pluginClientRedirects({ redirects: [ // /docs/old1 -> /docs/new1 { from: '/docs/old1', to: '/docs/new1', }, // redirect from multiple old paths to the new path { from: ['/docs/2022', '/docs/2023'], to: '/docs/2024', }, // redirect using regular expressions { from: '^/docs/old2', to: '/docs/new2', }, { from: '/docs/old3$', to: '/docs/new3', }, // redirect to an external URL { from: '/docs/old4', to: 'https://example.com', }, ], }), ], }); ``` --- url: https://rspress.rs/plugin/official-plugins/typedoc.md --- > 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. # @rspress/plugin-typedoc [Source Code](https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-typedoc) Rspress plugin for integrating [TypeDoc](https://github.com/TypeStrong/typedoc) and automatically generating API documentation for TypeScript modules. ## Installation ```sh [npm] npm add @rspress/plugin-typedoc -D ``` ```sh [yarn] yarn add @rspress/plugin-typedoc -D ``` ```sh [pnpm] pnpm add @rspress/plugin-typedoc -D ``` ```sh [bun] bun add @rspress/plugin-typedoc -D ``` ```sh [deno] deno add npm:@rspress/plugin-typedoc -D ``` ## Usage ```ts import { defineConfig } from '@rspress/core'; import { pluginTypeDoc } from '@rspress/plugin-typedoc'; import path from 'path'; export default defineConfig({ plugins: [ pluginTypeDoc({ entryPoints: [ path.join(__dirname, 'src', 'foo.ts'), path.join(__dirname, 'src', 'bar.ts'), ], }), ], }); ``` ```ts title="src/foo.ts" /** * This is an add function. */ export function add( /** * This is param1. */ param1: string, /** * This is param2. */ param2: number, ) { return 1; } ``` ```ts title="src/bar.ts" /** * This is a multi function. */ export function multi( /** * This is param1. */ param1?: string, /** * This is param2. */ param2?: number, ) { return 1; } ``` When you start or build the project, the plugin automatically generates an `api` directory in your docs root. The directory structure is: ```tree api ├── _meta.json ├── index.md ├── functions │ ├── bar.multi.md │ └── foo.add.md ├── interfaces │ ├── foo.RunTestsOptions.md │ └── foo.TestMessage.md └── modules ├── bar.md └── foo.md ``` The plugin calls TypeDoc internally to generate API documentation for your modules, including module lists, interface details, and function details such as parameters, return values, and descriptions. Note that the `.md` documentation files are regenerated every time you start the project to reflect the latest module content. Therefore, we recommend adding the `.md` files in the `api` directory to `.gitignore`, for example `docs/api/**/*.md`. If you customize the output directory with the `outDir` parameter below, you should also add the corresponding `.md` files to `.gitignore`. The `_meta.json` file is only automatically generated on the first run and will not be overwritten afterwards. This means you can manually edit it to customize the sidebar structure (e.g., add dividers, adjust order, etc.) and commit it to git. Do not modify the generated `.md` documents in the `api` directory, because they are overwritten each time the project starts to reflect module content changes. ## Options ### entryPoints - **Type**: `string[]` - **Default**: `[]` Specifies the absolute paths of the TypeScript modules for which documentation should be generated. ### outDir - **Type**: `string` - **Default**: `api` Customizes the documentation output directory. Provide a relative path, such as `api/custom`. ### setup - **Type**: `(app: Application) => Promise | Promise | void` - **Default**: `() => {}` A function for setting up the TypeDoc application. Use it to customize TypeDoc configuration before documentation is generated. --- url: https://rspress.rs/plugin/official-plugins/api-docgen.md --- > 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. # @rspress/plugin-api-docgen [Source Code](https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-api-docgen) This plugin generates API reference content automatically, powered by [react-docgen-typescript](https://github.com/styleguidist/react-docgen-typescript) and [documentation](https://github.com/documentationjs/documentation). ## Install ```sh [npm] npm add @rspress/plugin-api-docgen -D ``` ```sh [yarn] yarn add @rspress/plugin-api-docgen -D ``` ```sh [pnpm] pnpm add @rspress/plugin-api-docgen -D ``` ```sh [bun] bun add @rspress/plugin-api-docgen -D ``` ```sh [deno] deno add npm:@rspress/plugin-api-docgen -D ``` ## Usage First, add the following configuration: ```ts // rspress.config.ts import path from 'path'; import { defineConfig } from '@rspress/core'; import { pluginApiDocgen } from '@rspress/plugin-api-docgen'; export default defineConfig({ plugins: [ pluginApiDocgen({ entries: { button: './src/index.ts', }, apiParseTool: 'react-docgen-typescript', }), ], }); ``` Then use the `API` component to inject API documentation into an MDX file: ```mdx ## API This is API Table ``` ## Config The plugin accepts an object with the following type: ```ts interface Options { entries?: Record; apiParseTool?: 'react-docgen-typescript' | 'documentation'; appDir?: string; parseToolOptions?: ParseToolOptions; } ``` ### appDir `appDir` configures the base directory for parsing. The default is `process.cwd()`. ### entries `entries` configures the files to parse. - The key is an identifier used as the `moduleName` attribute of the `API` component. - The value is the relative path to the file being parsed. ### apiParseTool `apiParseTool` selects the parser. The default is `react-docgen-typescript`: - `react-docgen-typescript` is used for component library scenarios. It parses props to generate tables. ```tsx export type ButtonProps = { /** * Whether to disable the button */ disabled?: boolean; /** * Type of Button * @default 'default' */ size?: 'mini' | 'small' | 'default' | 'large'; }; export const Button = (props?: ButtonProps) => {}; ``` In this standard form, `ButtonProps` is extracted into a table and `Button` is used as the table title. If you use a default export, the file name is used as the table title. Note that exports declared elsewhere are not available. ```tsx const A = () => {}; export { A }; // wrong export default A; // wrong export const B = () => {}; // right export default () => {}; // right ``` The generated content is as follows: ```mdx ### ButtonTest | Props | Description | Type | Default | | :------: | :---------------------------: | :-----------------------------------------: | :---------: | | disabled | Whether to disable the button | `boolean` | `-` | | size | Type of Button | `"mini" \| "small" \| "default" \| "large"` | `'default'` | ``` :::warning If props use React types, add those types in `tsconfig.json`; otherwise, types under the React namespace cannot be resolved. ```json { "compilerOptions": { "types": ["react"] } } ``` The best approach is to import the type directly: ```tsx import { FC } from 'react'; ``` ::: - `documentation` is used in utility library scenarios to parse JSDoc annotations. Here is a `greet` function with JSDoc annotations. ```ts /** * Greet function that returns a greeting message. * @param {string} name - The name of the person to greet. * @param {string} [greeting='Hello'] - The greeting to use. * @returns {string} The greeting message. */ function greet(name: string, greeting = 'Hello') { return `${greeting}, ${name}!`; } ``` The generated content is as follows: ```md ## greet Greet function that returns a greeting message. ### Parameters - `name` **[string][1]** The name of the person to greet. - `greeting` **[string][1]** The greeting to use. (optional, default `'Hello'`) Returns **[string][1]** The greeting message. [1]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String ``` ### parseToolOptions `parseToolOptions` passes options to the selected parser. Its type is: ```ts type ParseToolOptions = { 'react-docgen-typescript'?: ParserOptions & { tsconfigPath?: Record; compilerOptions?: Record; }; documentation?: DocumentationArgs; }; ``` See [ParserOptions](https://github.com/styleguidist/react-docgen-typescript/blob/b7ea0a235efb7c78a1158ca12d864de2bc2ee30e/src/parser.ts#L84-L95) and [DocumentationArgs](https://github.com/documentationjs/documentation/blob/master/docs/NODE_API.md#parameters-1) for available options. When the parser is `react-docgen-typescript`, `withDefaultConfig` creates the parser instance by default. If `tsconfigPath` or `compilerOptions` is configured, they can be set separately for each `entry`; `withCompilerOptions` and `withCustomConfig` are used to create the parser instance respectively. See [Custom Parsers](https://github.com/styleguidist/react-docgen-typescript/blob/b7ea0a235efb7c78a1158ca12d864de2bc2ee30e/README.md#usage) for details. --- url: https://rspress.rs/plugin/official-plugins/preview.md --- > 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. # @rspress/plugin-preview [Source Code](https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-preview) Preview components from code blocks in MDX files. This is useful for component library documentation. ## Installation ```sh [npm] npm add @rspress/plugin-preview -D ``` ```sh [yarn] yarn add @rspress/plugin-preview -D ``` ```sh [pnpm] pnpm add @rspress/plugin-preview -D ``` ```sh [bun] bun add @rspress/plugin-preview -D ``` ```sh [deno] deno add npm:@rspress/plugin-preview -D ``` ## Usage ### 1. Install the plugin First, add the following configuration: ```ts title="rspress.config.ts" twoslash import { defineConfig } from '@rspress/core'; import { pluginPreview } from '@rspress/plugin-preview'; export default defineConfig({ plugins: [pluginPreview()], }); ``` ### 2. Use in mdx files Use the ` ```tsx preview ` syntax in MDX files: ````mdx title="example.mdx" ```tsx preview import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Current count: {count}

); } export default App; ``` ```` It renders as follows: ```tsx preview import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Current count: {count}

); } export default App; ``` :::tip 1. Currently only works in `.mdx` files. 2. Export the component as the default export, and Rspress will render it automatically. ::: ### 3. Write component code in other files (optional) Instead of writing component code directly in an MDX code block, you can use it with [File Code Block](https://rspress.rs/guide/use-mdx/code-blocks.md#file-code-block) and keep example code in separate files. ````mdx title="example.mdx" ```tsx file="./_demo.tsx" preview ``` ```` ```tsx title="_demo.tsx" file="./_demo.tsx" import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Current count: {count}

); } export default App; ``` It renders as follows: ```tsx file="./_demo.tsx" preview import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Current count: {count}

); } export default App; ``` ## Using iframe preview mode \{#preview-mode} This plugin supports multiple preview modes. You can switch between them by adjusting the `preview="..."` meta information. For example, you can use ` ```tsx preview="iframe-follow" ` to switch to [iframe-follow](#previewiframe-follow) mode. ` ```tsx preview` is equivalent to ` ```tsx preview="{defaultPreviewMode}"`, which is determined by the [defaultPreviewMode](#defaultpreviewmode) configuration. :::tip Iframe preview mode has separate compilation and runtime environments. 1. Separate compilation environment: example code in the code block is compiled as an entry by a separate Rsbuild instance, allowing Sass/Less variables and other setup to be injected. 2. Separate runtime environment: style conflicts with the documentation site are avoided, and the component library can load its own `base.css`. ::: ### `preview="internal"` `"internal"` is the default preview mode, where the component is rendered directly within the document. Syntax: ````mdx title="example.mdx" ```tsx file="./_demo.tsx" preview ``` ```` or ````mdx title="example.mdx" ```tsx file="./_demo.tsx" preview="internal" ``` ```` Rendering result: ```tsx file="./_demo.tsx" preview="internal" import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Current count: {count}

); } export default App; ``` ### `preview="iframe-follow"` This mode displays an iframe preview area on the right side of the code block that follows the content flow. Syntax: ````mdx title="example.mdx" ```tsx file="./_demo.tsx" preview="iframe-follow" ``` ```` Rendering result: ```tsx file="./_demo.tsx" preview="iframe-follow" import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Current count: {count}

); } export default App; ``` ### `preview="iframe-fixed"` This mode displays a fixed iframe preview area on the right side of the page, ideal for mobile component library documentation. Syntax: ````mdx title="example.mdx" ```tsx file="./_demo.tsx" preview="iframe-fixed" ``` ```` Rendering result: ![](https://lf3-static.bytednsdoc.com/obj/eden-cn/uhbfnupenuhf/rspress/demo-preview-mobile-fixed.png) :::tip preEntry Tips You can inject global scripts or styles into the iframe preview environment using `iframeOptions.builderConfig.source.preEntry`. Here are some common use cases: - **Mobile touch event emulation**: Emulate mobile touch events on PC by importing [@vant/touch-emulator](https://www.npmjs.com/package/@vant/touch-emulator). - **Dark mode handling**: Inject a `MutationObserver` to watch for `html.dark` class changes, then sync to `body.dark` or perform other dark mode processing. - **Using Tailwind CSS**: Since the iframe preview environment is a separate Rsbuild instance, if your previewed components depend on Tailwind CSS v4, configure `@rsbuild/plugin-tailwindcss` in `iframeOptions.builderConfig.plugins` and inject your Tailwind CSS entry via `preEntry`. ```ts title="rspress.config.ts" import { pluginTailwindcss } from '@rsbuild/plugin-tailwindcss'; pluginPreview({ iframeOptions: { builderConfig: { plugins: [pluginTailwindcss()], source: { preEntry: [ '@vant/touch-emulator', './src/dark-mode-observer.js', './tailwind.css', ], }, }, }, }); ``` ::: ## Options This plugin accepts a configuration object with the following type definition: ```ts interface PreviewOptions { defaultRenderMode?: 'pure' | 'preview'; defaultPreviewMode?: 'internal' | 'iframe-fixed' | 'iframe-follow'; iframeOptions?: IframeOptions; previewLanguages?: string[]; previewCodeTransform?: (codeInfo: { language: string; code: string; }) => string; } interface IframeOptions { devPort?: number; builderConfig?: RsbuildConfig; customEntry?: (meta: CustomEntry) => string;; } ``` ### defaultRenderMode - **Type:** `'pure' | 'preview'` - **Default:** `'pure'` Configures the default rendering behavior for code blocks that don't explicitly declare `pure` or `preview`. :::warning It is not recommended to modify the default value, as it may affect the combined usage with `@rspress/plugin-playground`. ::: - ` ```tsx pure`: Render as a regular code block - ` ```tsx `: Render based on `defaultRenderMode` configuration - ` ```tsx preview`: Render as a code block with preview component ### defaultPreviewMode - **Type:** `'internal' | 'iframe-follow' | 'iframe-fixed'` - **Default:** `'internal'` Configures the default [preview mode](#preview-mode) for ` ```tsx preview`. - ` ```tsx preview`: Render based on `defaultPreviewMode` configuration - ` ```tsx preview="internal"`: Render using internal mode - ` ```tsx preview="iframe-follow"`: Render using follow iframe mode - ` ```tsx preview="iframe-fixed"`: Render using fixed iframe mode ### iframeOptions This plugin starts a separate Rsbuild instance for the iframe mode's dev server and build process, completely isolated from the Rspress documentation compilation. #### iframeOptions.devPort - **Type:** `number` - **Default:** `7890` Configures the dev server port for iframe preview. If the specified port is already occupied, the plugin will automatically try the next port, up to 20 attempts. #### iframeOptions.builderConfig Configures Rsbuild build options for the iframe, such as adding global styles or scripts. For example, to add Less or Sass support in previews, install and configure the corresponding Rsbuild plugin: ```sh [npm] npm add @rsbuild/plugin-less -D ``` ```sh [yarn] yarn add @rsbuild/plugin-less -D ``` ```sh [pnpm] pnpm add @rsbuild/plugin-less -D ``` ```sh [bun] bun add @rsbuild/plugin-less -D ``` ```sh [deno] deno add npm:@rsbuild/plugin-less -D ``` ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import { pluginPreview } from '@rspress/plugin-preview'; import { pluginLess } from '@rsbuild/plugin-less'; export default defineConfig({ plugins: [ pluginPreview({ iframeOptions: { builderConfig: { plugins: [pluginLess()], }, }, }), ], }); ``` #### iframeOptions.customEntry Configures a custom entry to support other frameworks like Vue. :::warning Note Only available in `preview="iframe-follow"` mode. ::: Here is an example for the Vue framework: ```ts import { defineConfig } from '@rspress/core'; import { pluginPreview } from '@rspress/plugin-preview'; import { pluginVue } from '@rsbuild/plugin-vue'; export default defineConfig({ // ... plugins: [ pluginPreview({ previewMode: 'iframe', previewLanguages: ['vue'], iframeOptions: { position: 'follow', customEntry: ({ demoPath }) => { return ` import { createApp } from 'vue'; import App from ${JSON.stringify(demoPath)}; createApp(App).mount('#root'); `; }, builderConfig: { plugins: [pluginVue()], }, }, }), ], }); ``` ### previewLanguages - **Type:** `string[]` - **Default:** `['jsx', 'tsx']` Configures the code languages that support preview. To support other formats like JSON or YAML, use this in conjunction with `previewCodeTransform`. ### previewCodeTransform - **Type:** `(codeInfo: { language: string; code: string }) => string` - **Default:** `({ code }) => code` Performs custom transformation on code before preview. The following example shows how to transform JSON Schema into a renderable React component: ```json { "type": "div", "children": "Render from JSON" } ``` You can configure it as follows: ```ts pluginPreview({ previewLanguages: ['jsx', 'tsx', 'json'], previewCodeTransform(codeInfo) { if (codeInfo.language === 'json') { return ` import React from 'react'; const json = ${codeInfo.code}; export default function() { return React.createElement(json.type, null, json.children); } `; } else { return codeInfo.code; } }, }); ``` ## Migrating from V1 When migrating from Rspress V1, the plugin functionality remains unchanged. Only the MDX source code syntax has the following adjustments: - `` should be migrated to [File Code Block](https://rspress.rs/guide/use-mdx/code-blocks.md#file-code-block) ` ```tsx file="./foo.tsx"` - The `defaultPreviewMode` option replaces `iframeOptions.position` and `previewMode` - The default value of `defaultRenderMode` changed from `'preview'` to `'pure'` - `@rsbuild/plugin-less` and `@rsbuild/plugin-sass` are no longer built-in. If you need Less or Sass support in previews, install the corresponding plugin and configure it via `iframeOptions.builderConfig`: ```sh [npm] npm add @rsbuild/plugin-less -D ``` ```sh [yarn] yarn add @rsbuild/plugin-less -D ``` ```sh [pnpm] pnpm add @rsbuild/plugin-less -D ``` ```sh [bun] bun add @rsbuild/plugin-less -D ``` ```sh [deno] deno add npm:@rsbuild/plugin-less -D ``` ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import { pluginPreview } from '@rspress/plugin-preview'; import { pluginLess } from '@rsbuild/plugin-less'; export default defineConfig({ plugins: [ pluginPreview({ iframeOptions: { builderConfig: { plugins: [pluginLess()], }, }, }), ], }); ``` :::tip Migration Examples **Example 1**: Before: Required declarations in both config file and MDX file. ```ts pluginPreview({ previewMode: 'iframe', iframeOptions: { position: 'fixed' }, }); ``` ````mdx ```tsx preview ``` ```` After: Only declare in the MDX file. ````mdx ```tsx preview="iframe-fixed" ``` ```` **Example 2**: Before: Using `iframe` or `previewMode="iframe"` attribute. ````mdx ```tsx iframe ``` {/* or */} ```` After: Use the unified `preview="..."` attribute. ````mdx ```tsx preview="iframe-follow" ``` ```tsx file="./_demo.tsx" preview="iframe-follow" ``` ```` ::: --- url: https://rspress.rs/plugin/official-plugins/playground.md --- > 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. # @rspress/plugin-playground [Source Code](https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-playground) Provides a live editable playground for previewing components in MDX code blocks. :::tip Use this plugin alongside [@rspress/plugin-preview](https://rspress.rs/plugin/official-plugins/preview.md). Unlike `plugin-preview`, `plugin-playground` compiles code in the browser, so it has more limitations. For example, it cannot import modules from local files. Use `plugin-playground` as a supplement to `plugin-preview` when live code editing is required. ::: ## Installation ```sh [npm] npm add @rspress/plugin-playground -D ``` ```sh [yarn] yarn add @rspress/plugin-playground -D ``` ```sh [pnpm] pnpm add @rspress/plugin-playground -D ``` ```sh [bun] bun add @rspress/plugin-playground -D ``` ```sh [deno] deno add npm:@rspress/plugin-playground -D ``` ## Usage ### 1. Register the plugin First, write the following config in the config file: ```ts title="rspress.config.ts" twoslash import { defineConfig } from '@rspress/core'; import { pluginPlayground } from '@rspress/plugin-playground'; export default defineConfig({ plugins: [pluginPlayground()], }); ``` ### 2. Use in MDX files Use the ` ```tsx playground ` syntax in MDX files: ````mdx title="example.mdx" ```tsx playground import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Current count: {count}

); } export default App; ``` ```` It renders as follows: ```tsx playground import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Current count: {count}

); } export default App; ``` :::tip 1. It currently works only in `.mdx` files. 2. Export the component as default; Rspress renders it automatically. 3. Type checking is currently not performed for TSX. ::: ### 3. Write component code in other files (optional) In addition to writing component code in the code block of the mdx file, you can also use it with [File Code Block](https://rspress.rs/guide/use-mdx/code-blocks.md#file-code-block) to write the example code in other files. ````mdx title="example.mdx" ```tsx file="./_playgroundDemo.jsx" playground ``` ```` ```tsx title="_playgroundDemo.jsx" file="./_playgroundDemo.jsx" import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Counter from external file: {count}

); } export default App; ``` It renders as follows: ```tsx file="./_playgroundDemo.jsx" playground import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Counter from external file: {count}

); } export default App; ``` ## Adjusting layout direction \{#direction} You can use the `direction` parameter to specify the layout direction of the editor and preview area. It supports `horizontal` or `vertical`. ### `direction="horizontal"` Horizontal layout is the default mode, with the editor and preview area arranged side by side. Syntax: ````mdx title="example.mdx" ```tsx playground direction=horizontal ``` ```` ### `direction="vertical"` Vertical layout mode, with the editor and preview area arranged top to bottom. Syntax: ````mdx title="example.mdx" ```tsx playground direction=vertical ``` ```` Rendering result: ```tsx playground direction=vertical import { useState } from 'react'; function App() { const [text, setText] = useState('Hello'); return (
setText(e.target.value)} />

You entered: {text}

); } export default App; ``` ### Define the layout of the entire page You can write `playgroundDirection` in frontmatter to define the layout of the editor and preview area for the entire page. ```md title="example.mdx" --- title: Title playgroundDirection: vertical --- ``` Priority: Defined directly on the code block > Page frontmatter definition > Plugin configuration. ## Options This plugin accepts a configuration object with the following type definition: ```ts interface PlaygroundOptions { defaultRenderMode?: 'pure' | 'playground'; defaultDirection?: 'horizontal' | 'vertical'; editorPosition?: 'left' | 'right'; babelUrl?: string; monacoLoader?: Parameters[0]; monacoOptions?: MonacoEditorProps['options']; include?: Array; render?: string; } ``` ### defaultRenderMode - **Type:** `'pure' | 'playground'` - **Default:** `'pure'` Configures the default rendering behavior for code blocks that don't explicitly declare `pure` or `playground`. - ` ```tsx pure`: Render as a regular code block - ` ```tsx `: Render based on `defaultRenderMode` configuration - ` ```tsx playground`: Render as an editable Playground component :::warning It is not recommended to modify the default value, as it may affect the combined usage with `@rspress/plugin-preview`. ::: ### defaultDirection - **Type:** `'horizontal' | 'vertical'` - **Default:** `'horizontal'` Configures the default [layout direction](#direction) of the editor and preview area. ### editorPosition - **Type:** `'left' | 'right'` - **Default:** `'left'` Configures the position of the editor in horizontal layout (left/right). ### babelUrl - **Type:** `string` - **Default:** `'https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.22.20/babel.min.js'` Playground uses `@babel/standalone` to compile demo code. You can modify it to a URL provided by other CDNs, such as unpkg, jsdelivr, etc. ### monacoLoader Configures monaco-loader behaviors. Loaded from [cdnjs.com](https://cdnjs.com/libraries/monaco-editor) by default. You can modify it to a URL provided by other CDNs, such as unpkg, jsdelivr, etc. The full documentation can be found at [suren-atoyan/monaco-loader](https://github.com/suren-atoyan/monaco-loader#config) ### monacoOptions - **Type:** [IStandaloneEditorConstructionOptions](https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor_editor_api.editor.IStandaloneEditorConstructionOptions.html) Configures Monaco Editor options. :::warning Note `monacoLoader` and `monacoOptions` will be serialized to JSON, so some data types, such as functions and circularly referenced objects, are not supported. ::: ### include - **Type:** `Array` By default, this plugin will automatically scan all import statements in demos; packages not used in demos cannot be used in the Playground. If you want to add other packages to the Playground, you can use the `include` parameter: ```ts pluginPlayground({ include: [ // Add dayjs package 'dayjs', // Add a package named "my-package", actually pointing to "/path/to/package/index.js" ['my-package', '/path/to/package/index.js'], ], }); ``` ### render - **Type:** `string` You can customize the render file for rendering Playground. Please note that the file name must be `Playground.(jsx?|tsx?)`. ```ts pluginPlayground({ render: '/path/to/render/Playground.tsx', }); ``` In the custom Playground, you can directly import the original editor and renderer, and import pre-packaged dependencies through `_rspress_playground_imports`: ```ts import getImport from '_rspress_playground_imports'; import { Runner, Editor } from '@rspress/plugin-playground/web'; ``` You can refer to the built-in [Playground.tsx](https://github.com/web-infra-dev/rspress/blob/main/packages/plugin-playground/static/global-components/Playground.tsx) for customization. --- url: https://rspress.rs/plugin/official-plugins/rss.md --- > 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. # @rspress/plugin-rss [Source Code](https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-rss) Generates RSS files for selected documentation pages with [feed](https://github.com/jpmonette/feed). ## Installation ```sh [npm] npm add @rspress/plugin-rss -D ``` ```sh [yarn] yarn add @rspress/plugin-rss -D ``` ```sh [pnpm] pnpm add @rspress/plugin-rss -D ``` ```sh [bun] bun add @rspress/plugin-rss -D ``` ```sh [deno] deno add npm:@rspress/plugin-rss -D ``` ### Update Rspress config ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import { pluginRss } from '@rspress/plugin-rss'; export default defineConfig({ plugins: [ pluginRss({ // The URL of your documentation site siteUrl: 'https://example.com', // ...more configurations below }), ], }); ``` By default, this plugin generates a `blog.xml` file in the `doc_build/rss/` folder for all pages starting with `/blog/`. The RSS file can be accessed via `/rss/blog.xml`. :::tip This plugin only works with `rspress build` and does not generate RSS files on `rspress dev`. ::: ## Usage ### Selecting pages to be included in RSS Use the `feed.test` option to select which pages are included in the RSS file. ```ts pluginRss({ // ... feed: { test: '/zh/blog' }, }); ``` ### Requirements All documents included in the RSS must have either `date` or `published_at` in frontmatter to keep RSS updates stable for readers. ```md --- published_at: 2024-01-10 08:00:00 --- Or frontmatter `date`. ``` ### Generating multiple RSS files Sometimes you may need to generate multiple RSS files, for example for different languages or categories. Pass a list of RSS options to `feed`: ```ts pluginRss({ feed: [ { id: 'blog', test: '/blog/', title: 'Rspress Blog', language: 'en-US' }, { id: 'blog-zh', test: '/zh/blog/', title: 'Rspress 博客', language: 'zh-CN', }, { id: 'rspack', test: ({ frontmatter }) => frontmatter.categories.includes('rspack'), title: 'Rspack Releases', language: 'en-US', }, { id: 'rsbuild', test: ({ frontmatter }) => frontmatter.categories.includes('rsbuild'), title: 'Rsbuild Releases', language: 'en-US', }, ], }); ``` The options above will generate four RSS files: `blog.xml`, `blog-zh.xml`, `rspack.xml`, `rsbuild.xml`, all located in the `rss` folder. ### Modifying the output path You can customize the output path using the `output` and `feed.output` parameters. See [FeedOutputOptions](#feedoutputoptions) below. ### Linking RSS to doc pages By default, this plugin inserts a `` tag into selected pages included in the RSS. The tag points to the RSS file URL, so RSS readers can detect it automatically. To insert this tag into pages that are not included in the RSS, such as the homepage, add `link-rss` frontmatter with the feed ID as the value. For example: ```markdown --- link-rss: blog --- This frontmatter inserts a `` tag into this page and points it to the RSS URL of the `blog` feed. However, this page itself will not be included in that RSS. ``` `link-rss` also supports inserting multiple `` tags associated with feed ids on a single page: ```markdown --- link-rss: - blog - releases --- ``` ### Customize RSS content The RSS file consists of two parts: the RSS basic information, known as the `channel` in the RSS format, and the list of articles, known as the `item` in the RSS format. Customize each part as follows: - The `channel` can be fully modified through the `feed` option. See [Other Options](#other-options) below. - The `item` can be fully modified through the `feed.item` option. See the [item](#item) section below. ## Options ### PluginRssOptions Plugin options. ```ts export interface PluginRssOptions { siteUrl?: string; feed?: Partial | FeedChannel[]; output?: Omit; } ``` #### `siteUrl` - **Type**: `string` - **Default**: [`siteOrigin`](https://rspress.rs/api/config/config-basic.md#siteorigin) + [`base`](https://rspress.rs/api/config/config-basic.md#base), or `base` when `siteOrigin` is not configured The site URL of the current documentation site. It is used in the RSS file. RSS links are consumed outside the documentation page context, so configure an absolute URL with protocol and domain, such as `https://example.com/base/`. When `base` is configured, plugin-level `siteUrl` must include the `base` path. If [`siteOrigin`](https://rspress.rs/api/config/config-basic.md#siteorigin) and [`base`](https://rspress.rs/api/config/config-basic.md#base) are configured in Rspress, you can omit the plugin-level `siteUrl`. The full URL concatenation order is `siteOrigin + base + routePath`. If neither plugin-level `siteUrl` nor `siteOrigin` is configured, the plugin falls back to `base`, which keeps existing relative path behavior but does not generate absolute RSS links. ```ts // rspress.config.ts import path from 'path'; import { defineConfig } from '@rspress/core'; import { pluginRss } from '@rspress/plugin-rss'; export default defineConfig({ siteOrigin: 'https://example.com', base: '/base/', plugins: [ // siteUrl defaults to 'https://example.com/base/' pluginRss(), ], }); ``` #### `feed` - **Type**: `FeedChannel | FeedChannel[]` - **Default**: `{ id: 'blog', test: '/blog/' }` RSS configuration. Pass an array to generate multiple RSS files. See [FeedChannel](#feedchannel) for more information. #### `output` - **Type**: `Omit` - **Default**: `{ dir: 'rss', type: 'atom' }` Output options. See [FeedOutputOptions](#feedoutputoptions) below. ### FeedChannel RSS file options. ```ts export interface FeedChannel extends Partial { id: string; test: RegExp | string | (RegExp | string)[] | ((item: PageIndexInfo) => boolean); item?: ( item: FeedItem, page: PageIndexInfo, siteUrl: string, ) => FeedItem | PromiseLike; output?: FeedOutputOptions; } ``` #### `id` - **Type**: `string` - **Required** The RSS feed ID, which must be unique across multiple RSS options. It is also the default file basename for the RSS file. #### `test` - **Type**: `RegExp | string | (RegExp | string)[] | ((item: PageIndexInfo) => boolean)` - **Required** Selects documents to include in the RSS. Supported values: - `RegExp`: Regular expression that matches the document route. - `string`: Prefix-based match against the document route. - `(item: PageIndexInfo) => boolean`: Match pages based on page data and frontmatter. This is also the recommended way to include a route prefix while excluding specific pages such as `/blog/`. :::tip `item.routePath` does not include the `base` path. ::: For example, if you only want to include article pages under `/blog/` but exclude the blog index page itself: ```ts feed: { id: 'blog', test: (item) => { return ( item.routePath.startsWith('/blog/') && item.routePath !== '/blog/' ); }, } ``` #### `item` - **Type**: `(item: FeedItem, page: PageIndexInfo, siteUrl: string) => FeedItem | PromiseLike` - **Default**: Generates structured data for each article in the RSS file. Refer to the type of structured data: [Source Code](https://github.com/jpmonette/feed/blob/8ca7f3e4e8e421e2a2632bb9524385e86f30744c/src/typings/index.ts#L1-L25) The plugin has a built-in generator that uses document frontmatter and page data. For example, RSS `content` uses `summary` from frontmatter first, then falls back to document content. Provide the `item` function to modify the generated data passed as the first parameter. For example, the following configuration truncates the content of articles in the RSS: ```ts const item: FeedChannel['item'] = item => ({ ...item, content: item.content.slice(0, 1000), }); ``` #### `output` - **Type**: `FeedOutputOptions` - **Default**: Uses the plugin's `output` option by default Compared with the plugin-level `output` option, this option also includes `filename` for changing the output filename. See [FeedOutputOptions](#feedoutputoptions) below. #### Other options `FeedChannel` also inherits `FeedOptions` from the feed package. See [Source Code](https://github.com/jpmonette/feed/blob/8ca7f3e4e8e421e2a2632bb9524385e86f30744c/src/typings/index.ts#L48-L67) for options not listed here. ### FeedOutputOptions RSS output options. They are available both at the plugin level and the `feed` level, with the following type: ```ts interface FeedOutputOptions { dir?: string; type?: 'atom' | 'rss' | 'json'; filename?: string; publicPath?: string; sorting?: (left: FeedItem, right: FeedItem) => number; transform?: ( content: string, context: { type: 'atom' | 'rss' | 'json'; feed: Feed; channel: FeedChannel; }, ) => string | PromiseLike; } ``` Example: ```ts pluginRss({ // Applied to all RSS outputs output: { // Change the output folder for RSS files to 'feeds', relative to `doc_build` dir: 'feeds', // Output in RSS 2.0 format, use `.rss` extension by default. type: 'rss', }, feed: [ { id: 'blog', test: '/blog/', title: 'My Blog', output: { type: 'atom' /* default to using `id` as the base file name */, }, }, { id: 'releases', test: '/releases/', title: 'Releases', output: { dir: 'releases', filename: 'feed.rss' }, }, ], }); ``` Building with the options above will output two files: `feeds/blog.xml` and `releases/feed.rss`. #### `dir` - **Type**: `string` - **Default**: `rss` Output folder for RSS files, relative to `doc_build`. #### `type` - **Type**: `"atom" | "rss" | "json"` - **Default**: `atom` RSS output format. The default is `atom`: | Value | Format | Default Extension | MIME Type | | ------ | ------------------------------------------------------ | ----------------- | ---------------------- | | `atom` | [Atom 1.0](https://www.ietf.org/rfc/rfc4287.txt) | `.xml` | `application/atom+xml` | | `rss` | [RSS 2.0](https://www.rssboard.org/rss-specification) | `.rss` | `application/rss+xml` | | `json` | [JSON Feed 1.1](https://www.jsonfeed.org/version/1.1/) | `.json` | `application/json` | #### `filename` - **Type**: `string` - **Default**: ID as the file basename; extension by RSS output format Modifies the full filename of the RSS file. #### `publicPath` - **Type**: `string` - **Default**: the value of `siteUrl` URL prefix for the RSS file. An RSS URL is composed of `publicPath`, `dir`, and `filename`. #### `sorting` - **Type**:`sorting?: (left: FeedItem, right: FeedItem) => number;` Sorts articles. By default, newest articles appear first. #### `transform` - **Type**: `(content: string, context: { type: 'atom' | 'rss' | 'json'; feed: Feed; channel: FeedChannel }) => string | PromiseLike` Transform the final generated feed content before it is written to disk. This hook is available in both the plugin-level `output` option and the per-feed `output` option, so the same customization pattern can be used for Atom, RSS, and JSON Feed outputs. For example, the following configuration injects a custom `folo:id` into XML feeds and adds the same identifier to JSON Feed: ```ts pluginRss({ siteUrl: 'https://example.com/', output: { transform(content, { type, channel }) { if (type === 'json') { return JSON.stringify({ ...JSON.parse(content), foloId: channel.id, }); } const closingTag = type === 'rss' ? '' : ''; return content.replace( closingTag, `${channel.id}${closingTag}`, ); }, }, }); ``` --- url: https://rspress.rs/plugin/official-plugins/algolia.md --- > 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. # @rspress/plugin-algolia [Source Code](https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-algolia) This plugin replaces Rspress's built-in search with [Algolia](https://www.algolia.com/) through [DocSearch](https://docsearch.algolia.com). ## Installation ```sh [npm] npm add @rspress/plugin-algolia -D ``` ```sh [yarn] yarn add @rspress/plugin-algolia -D ``` ```sh [pnpm] pnpm add @rspress/plugin-algolia -D ``` ```sh [bun] bun add @rspress/plugin-algolia -D ``` ```sh [deno] deno add npm:@rspress/plugin-algolia -D ``` ## Usage First, add the following configuration to `rspress.config.ts`: ```ts // rspress.config.ts import path from 'path'; import { defineConfig } from '@rspress/core'; import { pluginAlgolia } from '@rspress/plugin-algolia'; export default defineConfig({ plugins: [pluginAlgolia()], }); ``` Then override the `Search` component with an Algolia-powered search box through [Custom Theme](https://rspress.rs/guide/basic/custom-theme.md). ```tsx // theme/index.tsx import { Search as PluginAlgoliaSearch } from '@rspress/plugin-algolia/runtime'; const Search = () => { return ( ); }; export { Search }; export * from '@rspress/core/theme-original'; ``` ## Configuration The plugin accepts an options object with the following type: ```ts interface Options { verificationContent?: string; } ``` ### verificationContent - **Type**: `string | undefined` - **Default**: `undefined` Used for meta tag verification when creating an Algolia crawler. Format: ``. See [Create a new crawler - Algolia](https://www.algolia.com/doc/tools/crawler/getting-started/create-crawler/#dns). ## SearchProps The `SearchProps` type from `@rspress/plugin-algolia/runtime` is as follows: ```ts import type { DocSearchProps } from '@docsearch/react'; type Locales = Record< string, { translations: DocSearchProps['translations']; placeholder: string } >; type SearchProps = { /** * @link https://docsearch.algolia.com/docs/api */ docSearchProps?: DocSearchProps; locales?: Locales; }; ``` ### docSearchProps - **Type**: `import('@docsearch/react').DocSearchProps` - **Default**: `undefined` `docSearchProps` is passed directly to the `` component from `@docsearch/react`. For specific types, see the [DocSearch documentation](https://docsearch.algolia.com/docs/api). ### locales - **Type**: ```ts type Locales = Record< string, { translations: DocSearchProps['translations']; placeholder: string } >; ``` - **Default**: `{}` For customizing translated text in different languages, Rspress provides the following translated text for import. ```ts file="/../packages/plugin-algolia/src/runtime/locales.ts" import type { DocSearchProps } from '@docsearch/react'; export type Locales = Record< string, { translations: DocSearchProps['translations']; placeholder: string } >; // cspell:disable export const ZH_LOCALES: Locales = { zh: { placeholder: '搜索文档', translations: { button: { buttonText: '搜索', buttonAriaLabel: '搜索', }, modal: { searchBox: { clearButtonTitle: '清除查询条件', clearButtonAriaLabel: '清除查询条件', closeButtonText: '取消', closeButtonAriaLabel: '取消', }, startScreen: { recentSearchesTitle: '搜索历史', noRecentSearchesText: '没有搜索历史', saveRecentSearchButtonTitle: '保存至搜索历史', removeRecentSearchButtonTitle: '从搜索历史中移除', favoriteSearchesTitle: '收藏', removeFavoriteSearchButtonTitle: '从收藏中移除', }, errorScreen: { titleText: '无法获取结果', helpText: '你可能需要检查你的网络连接', }, footer: { selectText: '选择', navigateText: '切换', closeText: '关闭', poweredByText: '搜索提供者', }, noResultsScreen: { noResultsText: '无法找到相关结果', suggestedQueryText: '你可以尝试查询', reportMissingResultsText: '你认为该查询应该有结果?', reportMissingResultsLinkText: '点击反馈', }, }, }, }, } as const; export const RU_LOCALES: Locales = { ru: { placeholder: 'Поиск в документации', translations: { button: { buttonText: 'Поиск', buttonAriaLabel: 'Поиск', }, modal: { searchBox: { clearButtonTitle: 'Очистить поиск', clearButtonAriaLabel: 'Очистить поиск', closeButtonText: 'Закрыть', closeButtonAriaLabel: 'Закрыть', }, startScreen: { recentSearchesTitle: 'История поиска', noRecentSearchesText: 'Нет истории поиска', saveRecentSearchButtonTitle: 'Сохранить в истории поиска', removeRecentSearchButtonTitle: 'Удалить из истории поиска', favoriteSearchesTitle: 'Избранное', removeFavoriteSearchButtonTitle: 'Удалить из избранного', }, errorScreen: { titleText: 'Невозможно получить результаты', helpText: 'Проверьте подключение к Интернету', }, footer: { selectText: 'выбрать', navigateText: 'перейти', closeText: 'закрыть', poweredByText: 'поиск от', }, noResultsScreen: { noResultsText: 'Ничего не найдено', suggestedQueryText: 'Попробуйте изменить запрос', reportMissingResultsText: 'Считаете, что результаты должны быть?', reportMissingResultsLinkText: 'Сообщите об этом', }, }, }, }, } as const; export const TA_LOCALES: Locales = { ta: { placeholder: 'ஆவணங்களைத் தேடுக...', translations: { button: { buttonText: 'தேடுக', buttonAriaLabel: 'தேடுக', }, modal: { searchBox: { clearButtonTitle: 'தேடலை நீக்கவும்', clearButtonAriaLabel: 'தேடலை நீக்கவும்', closeButtonText: 'இரத்து செய்', closeButtonAriaLabel: 'இரத்து செய்', }, startScreen: { recentSearchesTitle: 'சமீபத்திய தேடல்கள்', noRecentSearchesText: 'சமீபத்திய தேடல்கள் எதுவும் இல்லை', saveRecentSearchButtonTitle: 'தேடல் வரலாற்றில் சேர்க்கவும்', removeRecentSearchButtonTitle: 'தேடல் வரலாற்றிலிருந்து நீக்கவும்', favoriteSearchesTitle: 'பிடித்தவை', removeFavoriteSearchButtonTitle: 'பிடித்தவையிலிருந்து நீக்கவும்', }, errorScreen: { titleText: 'முடிவுகளைப் பெற முடியவில்லை', helpText: 'உங்கள் இணைய இணைப்பைச் சரிபார்க்கவும்', }, footer: { selectText: 'தேர்ந்தெடுக்க', navigateText: 'நகர்த்த', closeText: 'மூட', poweredByText: 'வழங்குபவர்', }, noResultsScreen: { noResultsText: 'முடிவுகள் கிடைக்கவில்லை', suggestedQueryText: 'இவற்றைத் தேட முயற்சிக்கவும்', reportMissingResultsText: 'இதற்கு முடிவுகள் கிடைத்திருக்க வேண்டும் என நினைக்கிறீர்களா?', reportMissingResultsLinkText: 'எங்களுக்குத் தெரியப்படுத்துங்கள்', }, }, }, }, } as const; // cspell:enable ``` Rspress provides Chinese translations by default, and you can customize translated text for different languages through `locales`. - Example: ```tsx import { Search as PluginAlgoliaSearch, ZH_LOCALES } from '@rspress/plugin-algolia/runtime'; // or ``` ## Algolia crawler config Here is an example config based on what this site uses: ```tsx new Crawler({ appId: 'YOUR_APP_ID', apiKey: 'YOUR_API_KEY', rateLimit: 8, maxDepth: 10, startUrls: ['https://rspress.rs'], sitemaps: ['https://rspress.rs/sitemap.xml'], discoveryPatterns: ['https://rspress.rs/**'], actions: [ { indexName: 'doc_search_rspress_v2_pages', pathsToMatch: ['https://rspress.rs/**'], recordExtractor: ({ $, helpers }) => { // Remove badge elements to prevent their text from being indexed $('.rp-badge').remove(); // Remove non-doc elements (e.g. version switcher) from h1 to keep title text clean $('.rspress-doc h1 .rp-not-doc').remove(); const $activeNavItem = $('.rp-nav-menu__item.rp-nav-menu__item--active') .first() .clone(); const lvl0 = $activeNavItem.text().trim() || 'Documentation'; return helpers.docsearch({ recordProps: { lvl0: { selectors: '', defaultValue: lvl0, }, lvl1: '.rspress-doc h1', lvl2: '.rspress-doc h2', lvl3: '.rspress-doc h3', lvl4: '.rspress-doc h4', lvl5: '.rspress-doc h5', lvl6: '.rspress-doc pre > code', // if you want to search code blocks, add this line content: '.rspress-doc p, .rspress-doc li', }, indexHeadings: true, aggregateContent: true, recordVersion: 'v3', }); }, }, ], initialIndexSettings: { doc_search_rspress_v2_pages: { attributesForFaceting: ['type', 'lang'], attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'], attributesToHighlight: ['hierarchy', 'content'], attributesToSnippet: ['content:10'], camelCaseAttributes: ['hierarchy', 'content'], searchableAttributes: [ 'unordered(hierarchy.lvl0)', 'unordered(hierarchy.lvl1)', 'unordered(hierarchy.lvl2)', 'unordered(hierarchy.lvl3)', 'unordered(hierarchy.lvl4)', 'unordered(hierarchy.lvl5)', 'unordered(hierarchy.lvl6)', 'content', ], distinct: true, attributeForDistinct: 'url', customRanking: [ 'desc(weight.pageRank)', 'desc(weight.level)', 'asc(weight.position)', ], ranking: [ 'words', 'filters', 'typo', 'attribute', 'proximity', 'exact', 'custom', ], minWordSizefor1Typo: 3, minWordSizefor2Typos: 7, allowTyposOnNumericTokens: false, minProximity: 1, ignorePlurals: true, advancedSyntax: true, attributeCriteriaComputedByMinProximity: true, removeWordsIfNoResults: 'allOptional', }, }, schedule: 'on tuesday', indexPrefix: 'rspress-v2-crawler-', }); ``` ## Distinguish search results based on i18n You can achieve internationalized search results by combining [Runtime API](https://rspress.rs/ui/hooks/index.md) with `docSearchProps`. Here's an example using `docSearchProps.searchParameters`: ```tsx // theme/index.tsx import { useLang } from '@rspress/core/runtime'; import { Search as PluginAlgoliaSearch } from '@rspress/plugin-algolia/runtime'; const Search = () => { const lang = useLang(); return ( ); }; export { Search }; export * from '@rspress/core/theme-original'; ``` --- url: https://rspress.rs/plugin/official-plugins/twoslash.md --- > 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. # @rspress/plugin-twoslash [Source Code](https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-twoslash) Integrates [Twoslash](https://github.com/twoslashes/twoslash) with Rspress to generate rich TypeScript code blocks with type information. ## Installation ```sh [npm] npm add @rspress/plugin-twoslash -D ``` ```sh [yarn] yarn add @rspress/plugin-twoslash -D ``` ```sh [pnpm] pnpm add @rspress/plugin-twoslash -D ``` ```sh [bun] bun add @rspress/plugin-twoslash -D ``` ```sh [deno] deno add npm:@rspress/plugin-twoslash -D ``` ## Usage ### 1. Register the plugin ```ts twoslash title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import { pluginTwoslash } from '@rspress/plugin-twoslash'; export default defineConfig({ plugins: [pluginTwoslash()], }); ``` ### 2. Write code blocks with twoslash Use special comments within TypeScript code blocks to enable Twoslash features. For detailed usage, see the [Twoslash documentation](https://twoslash.netlify.app/guide/). #### Extract type **Rendered** ```ts twoslash const hi = 'Hello'; const msg = `${hi}, world`; // ^? ``` **Syntax** ````mdx ```ts twoslash const hi = 'Hello'; const msg = `${hi}, world`; // ^? ``` ```` #### Completions **Rendered** ```ts twoslash // @noErrors console.e; // ^| ``` **Syntax** ````mdx ```ts twoslash // @noErrors console.e; // ^| ``` ```` #### Highlighting **Rendered** ```ts twoslash function add(a: number, b: number) { // ^^^ return a + b; } ``` **Syntax** ````mdx ```ts twoslash function add(a: number, b: number) { // ^^^ return a + b; } ``` ```` #### Error **Rendered** ```ts twoslash // @noErrorValidation const str: string = 1; ``` **Syntax** ````mdx ```ts twoslash // @noErrorValidation const str: string = 1; ``` ```` ## Config The plugin accepts an object with the following type: ```ts twoslash import { TwoslashOptions } from 'twoslash'; // ---cut-before--- export interface PluginTwoslashOptions { explicitTrigger?: boolean; cache?: boolean; twoslashOptions?: TwoslashOptions; } ``` ### explicitTrigger `explicitTrigger` is used to configure whether to explicitly trigger the Twoslash feature. Default is `true`. - If set to `false`, all TypeScript code blocks will be processed by default. - If set to `true`, only code blocks with the `twoslash` tag will be processed. ### cache `cache` is used to cache the TypeScript language servers based on compiler options when calling [createTwoslasher](https://twoslash.netlify.app/refs/api#createtwoslasher). Default is `true`. ### twoslashOptions `twoslashOptions` is used to pass options to Twoslash. This allows you to customize the Twoslash behavior, including TypeScript compiler options and other settings. --- url: https://rspress.rs/plugin/community-plugins/overview.md --- > 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. # Overview ## Community plugins You can check out the Rspress plugins provided by the community at [awesome-rstack - Rspress Plugins](https://github.com/rstackjs/awesome-rstack?tab=readme-ov-file#rspress-plugins). You can also discover more Rspress plugins on npm by searching for the keyword [rspress-plugin](https://www.npmjs.com/search?q=rspress-plugin\&ranking=popularity). Here are some community plugins: - [rspress-plugin-file-tree](https://github.com/rstackjs/rspress-plugins/tree/main/packages/rspress-plugin-file-tree): Rspress plugin that adds a tree view for displaying file structures. - [rspress-plugin-gh-pages](https://github.com/rstackjs/rspress-plugins/tree/main/packages/rspress-plugin-gh-pages): Rspress plugin to add support for automatic deployment to GitHub Pages. - [rspress-plugin-translate](https://github.com/byteHulk/rspress-plugin-translate): A plugin that integrates LLM for document translation. - [rspress-plugin-font-open-sans](https://github.com/rstackjs/rspress-plugin-font-open-sans): Use Open Sans as the default font in your Rspress website. - [rspress-plugin-align-image](https://github.com/rstackjs/rspress-plugins/tree/main/packages/rspress-plugin-align-image): Rspress plugin to align images in markdown. - [rspress-plugin-directives](https://github.com/rstackjs/rspress-plugins/tree/main/packages/rspress-plugin-directives): Rspress plugin for custom directives support. - [rspress-plugin-google-analytics](https://github.com/rstackjs/rspress-plugins/tree/main/packages/rspress-plugin-google-analytics): Rspress plugin for Google Analytics integration. - [rspress-plugin-vercel-analytics](https://github.com/rstackjs/rspress-plugins/tree/main/packages/rspress-plugin-vercel-analytics): Rspress plugin for Vercel Analytics integration. - [rspress-plugin-katex](https://github.com/rstackjs/rspress-plugins/tree/main/packages/rspress-plugin-katex): Rspress plugin to add support for rendering math equations using [KaTeX](https://katex.org/). - [rspress-plugin-live2d](https://github.com/rstackjs/rspress-plugins/tree/main/packages/rspress-plugin-live2d): Rspress plugin for live2d, powered by [oh-my-live2d](https://oml2d.hacxy.cn/). - [rspress-plugin-mermaid](https://github.com/rstackjs/rspress-plugins/tree/main/packages/rspress-plugin-mermaid): Rspress plugin to render [Mermaid](https://mermaid.js.org/#/) diagrams in markdown files. - [rspress-plugin-reading-time](https://github.com/rstackjs/rspress-plugins/tree/main/packages/rspress-plugin-reading-time): Rspress plugin to display reading time for doc pages. - [rspress-plugin-supersub](https://github.com/rstackjs/rspress-plugins/tree/main/packages/rspress-plugin-supersub): Rspress plugin to add superscript(``) and subscript(``) support. - [rspress-plugin-auto-meta](https://github.com/smileluck/rspress-plugin-auto-meta.git): Rspress plugin to automatically generate navigation metadata for your documentation. - [rspress-plugin-map](https://github.com/buyfakett/rspress-plugin-map.git): Insert interactive maps into Rspress, inspired by [hexo-tag-map](https://github.com/kuole-o/hexo-tag-map.git). - [rspress-plugin-auto-sidebar](https://github.com/buyfakett/rspress-plugin-auto-sidebar.git): Automatically generate the sidebar from the navbar configuration. - [rspress-plugin-giscus](https://github.com/buyfakett/rspress-plugin-giscus.git): Integrate [giscus](https://github.com/giscus/giscus) into Rspress, a comment system powered by GitHub Discussions. - [rspress-plugin-blog-list](https://github.com/buyfakett/rspress-plugin-blog-list.git): Integrate blog list into Rspress. - [rspress-plugin-pretext-breaker](https://github.com/y-lakhdar/rspress-plugin-pretext-breaker): Add the Pretext Breaker game to your Rspress site. - [rspress-plugin-comments](https://github.com/kalicyh/rspress-plugin-comments): Provide page comments and text selection comments for Rspress, with support for a self-hosted backend and optional Gitea OAuth login. - [rspress-plugin-typesense](https://github.com/typesense/rspress-plugin-typesense): Rspress plugin that replaces the built-in search with [Typesense](https://typesense.org/), an open-source, typo-tolerant search engine. - [rspress-plugin-viz](https://github.com/elecmonkey/rspress-plugin-viz): Add Graphviz diagram rendering support for Rspress using [@viz-js/viz](https://github.com/mdaines/viz-js/). - [rspress-plugin-third-parties](https://github.com/sanjaiyan-dev/rspress-plugin-third-parties): High-performance, zero-config plugin for loading third-party scripts and embeds (Google Analytics, GTM, YouTube, Google Maps, Twitter/X) with maximum Core Web Vitals efficiency. Explore the [Official Docs & Live Demos](https://sanjaiyan-dev.github.io/rspress-plugin-third-parties/). ## Contributing community plugins Community contributions of Rspress plugins are welcome! Plugin npm package names should follow the `rspress-plugin-` prefix convention. You can contribute in the following ways: - Develop and publish a plugin in your own repository, then submit a PR to add it to the community plugins list on this page. - Contribute directly to the [rspress-plugins](https://github.com/rstackjs/rspress-plugins) repository, which already contains several community plugins that can serve as references. --- url: https://rspress.rs/plugin/community-plugins/typesense.md --- > 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. # rspress-plugin-typesense [Source Code](https://github.com/typesense/rspress-plugin-typesense) This plugin replaces Rspress's built-in search with [Typesense](https://typesense.org/), an open-source, typo-tolerant search engine. The plugin **automatically indexes your documentation during the build process** (`rspress build`) and provides a highly-optimized search experience with support for Rspress multi-versioning and internationalization. :::note This is a community-maintained integration. ::: ## Installation ```sh [npm] npm add rspress-plugin-typesense -D ``` ```sh [yarn] yarn add rspress-plugin-typesense -D ``` ```sh [pnpm] pnpm add rspress-plugin-typesense -D ``` ```sh [bun] bun add rspress-plugin-typesense -D ``` ```sh [deno] deno add npm:rspress-plugin-typesense -D ``` ## Usage ### 1. Start typesense server You can either self-host the Typesense server or use their cloud service. Follow their [getting started guide](https://typesense.org/docs/guide/install-typesense.html) to set up your server and obtain the API key and server URL. ### 2. Configure the plugin First, add the plugin to your `rspress.config.ts`. You must provide your Typesense server details and an API key with **write permissions** so the plugin can create collections and index your documents during the build. ```ts // rspress.config.ts import { defineConfig } from '@rspress/core'; import { pluginTypesense } from 'rspress-plugin-typesense'; export default defineConfig({ plugins: [ pluginTypesense({ collectionName: 'my_docs', serverConfig: { nodes: [{ url: 'YOUR_TYPESENSE_SERVER_URL' }], apiKey: 'YOUR_TYPESENSE_ADMIN_API_KEY', // Requires Write permissions }, }), ], }); ``` ### 3. Override the search component Next, override Rspress's default `Search` component via a [Custom Theme](https://rspress.rs/guide/basic/custom-theme.md). Provide a **Search-Only API Key** here. For security reasons, **never expose your Admin API Key in the frontend**. ```tsx // theme/index.tsx import { Search as PluginTypesenseSearch } from 'rspress-plugin-typesense/runtime'; const Search = () => { return ( ); }; export { Search }; export * from '@rspress/core/theme-original'; ``` ### 4. Build and index Run the build command to generate your site and index your content into Typesense. ```sh [npm] npm run build ``` ```sh [yarn] yarn run build ``` ```sh [pnpm] pnpm run build ``` ```sh [bun] bun run build ``` ```sh [deno] deno run npm:build ``` All set! You've successfully integrated typo-tolerant search into your documentation. The plugin automatically handles filtering based on the user's current language and version. For more advanced configuration and usage, refer to [the plugin README](https://github.com/typesense/rspress-plugin-typesense/). --- url: https://rspress.rs/ui/vars.md --- > 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. # CSS variables Rspress exposes commonly used CSS variables, the simplest and most maintainable approach in [custom themes](https://rspress.rs/guide/basic/custom-theme.md). You can edit and preview in real time on this page, then copy the result to your project for style overriding. See [CSS variables](https://rspress.rs/guide/basic/custom-theme.md#css-variables) for how to override these styles. When overriding CSS variables in dark mode, both `html.rp-dark` and `html.dark` can be used as dark mode selectors. :::tip You can use the "Copy Markdown" feature on this page to let your AI Agent help you modify CSS variables. ::: Below are some CSS variables provided by Rspress and their default values: ## Brand colors Default ```css /* Default Rspress brand colors */ :where(:root) { --rp-c-brand: #0095ff; --rp-c-brand-light: #33adff; --rp-c-brand-lighter: #c6e0fd; --rp-c-brand-dark: #0077ff; --rp-c-brand-darker: #005fcc; --rp-c-brand-tint: rgba(127, 163, 255, 0.16); } ``` ## Codeblock - shiki theme DefaultGithub LightGithub DarkGithub Light High ContrastGithub Dark High ContrastLight PlusDark PlusOne LightOne Dark ProNordMaterial ThemeMaterial Theme DarkerMaterial Theme OceanVitesse LightVitesse DarkAndromeedaAyu Dark ```css /* Light Mode */ :where(html:not(.rp-dark)) { --shiki-foreground: inherit; /* Priority higher than var(--rp-code-block-color); */ --shiki-background: transparent; /* Priority higher than var(--rp-code-block-bg); */ --shiki-token-constant: #1976d2; --shiki-token-string: #31a94d; --shiki-token-comment: rgb(182, 180, 180); --shiki-token-keyword: #cf2727; --shiki-token-parameter: #f59403; --shiki-token-function: #7041c8; --shiki-token-string-expression: #218438; --shiki-token-punctuation: #242323; --shiki-token-link: #22863a; /* diff language */ --shiki-token-deleted: #d32828; --shiki-token-inserted: #22863a; } /* Dark Mode */ :where(html.rp-dark) { --shiki-foreground: inherit; /* Priority higher than var(--rp-code-block-color); */ --shiki-background: transparent; /* Priority higher than var(--rp-code-block-bg); */ --shiki-token-constant: #6fb0fa; --shiki-token-string: #f9a86e; --shiki-token-comment: #6a727b; --shiki-token-keyword: #f47481; --shiki-token-parameter: #ff9800; --shiki-token-function: #ae8eeb; --shiki-token-string-expression: #4fb74d; --shiki-token-punctuation: #bbbbbb; --shiki-token-link: #f9a76d; /* diff language */ --shiki-token-deleted: #ee6d7a; --shiki-token-inserted: #36c47f; } ``` ## Codeblock - outer title and container ```css /* Light Mode */ :where(html:not(.rp-dark)) { --rp-code-font-size: 0.875rem; --rp-code-title-bg: #f8f8f9; --rp-code-block-color: rgb(46, 52, 64); --rp-code-block-bg: var(--rp-c-bg); --rp-code-block-border: 1px solid var(--rp-c-divider-light); --rp-code-block-shadow: none; } /* Dark Mode */ :where(html.rp-dark) { --rp-code-font-size: 0.875rem; --rp-code-title-bg: #191919; --rp-code-block-color: rgb(229, 231, 235); --rp-code-block-bg: var(--rp-c-bg); --rp-code-block-border: 1px solid var(--rp-c-divider-light); --rp-code-block-shadow: none; } ``` ```tsx title="foo.ts" console.log('This is a code block'); ``` ## Default homepage ```css /* This is some variables used in HomeLayout. */ /* Light Mode */ :where(html:not(.rp-dark)) { --rp-home-hero-secondary-color: #a673ff; /* HomeHero */ --rp-home-hero-title-color: transparent; --rp-home-hero-title-bg: linear-gradient( 90deg, var(--rp-c-brand-dark) 0%, var(--rp-c-brand-dark) 30%, var(--rp-home-hero-secondary-color) 100% ); /* HomeBackground */ --rp-home-background-bg: radial-gradient( 42.12% 56.13% at 100% 0%, rgba(83, 125, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100% ), radial-gradient( 42.01% 79.63% at 52.86% 0%, rgba(83, 125, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100% ), radial-gradient( 79.67% 58.09% at 0% 0%, rgba(126, 105, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100% ), #fff; /* HomeFeature */ --rp-home-feature-bg: linear-gradient(135deg, #fff, #f9f9f980); } /* Dark Mode */ :where(html.rp-dark) { --rp-home-hero-secondary-color: #a673ff; /* HomeHero */ --rp-home-hero-title-color: transparent; --rp-home-hero-title-bg: linear-gradient( 90deg, var(--rp-c-brand-dark) 0%, var(--rp-c-brand-dark) 30%, var(--rp-home-hero-secondary-color) 100% ); /* HomeBackground */ --rp-home-background-bg: radial-gradient( 42.12% 56.13% at 100% 0%, #0c1d48 0%, rgba(18, 18, 18, 0) 100% ), radial-gradient( 55.81% 87.78% at 48.37% 0%, #000000 0%, rgba(18, 18, 18, 0) 89.55% ), radial-gradient( 122.65% 88.24% at 0% 0%, #34268a 0%, rgba(18, 18, 18, 0) 100% ), #121212; /* HomeFeature */ --rp-home-feature-bg: linear-gradient(135deg, #ffffff00, #ffffff08); } ``` ## Base variables ```css /* Light Mode */ :where(html:not(.rp-dark)) { --rp-c-bg: #ffffff; --rp-c-bg-soft: #f8f8f9; --rp-c-bg-mute: #f1f1f1; --rp-c-bg-alt: #fff; --rp-c-divider: rgba(0, 0, 0, 0.25); --rp-c-divider-light: rgba(0, 0, 0, 0.12); --rp-c-text-0: #000000; --rp-c-text-1: #242424; --rp-c-text-2: rgba(0, 0, 0, 0.7); --rp-c-text-3: rgba(60, 60, 60, 0.33); --rp-c-text-4: rgba(60, 60, 60, 0.18); --rp-c-text-code: #476582; /* inline code */ --rp-c-text-code-bg: rgba(153, 161, 179, 0.06); /* inline code bg */ --rp-c-text-code-border: rgba(0, 0, 0, 0.035); /* inline code border */ --rp-c-link: var(--rp-c-brand-dark); } /* Dark Mode */ :where(html.rp-dark) { --rp-c-bg: #121212; --rp-c-bg-soft: #292e37; --rp-c-bg-mute: #343a46; --rp-c-bg-alt: #000; --rp-c-divider: rgba(84, 84, 84, 0.65); --rp-c-divider-light: rgba(84, 84, 84, 0.48); --rp-c-text-0: #ffffff; --rp-c-text-1: rgba(255, 255, 245, 0.93); --rp-c-text-2: rgba(255, 255, 245, 0.65); --rp-c-text-3: rgba(235, 235, 235, 0.38); --rp-c-text-4: rgba(235, 235, 235, 0.18); --rp-c-text-code: #c9def1; /* inline code */ --rp-c-text-code-bg: rgba(255, 255, 255, 0.06); /* inline code bg */ --rp-c-text-code-border: rgba(255, 255, 255, 0.04); /* inline code border */ --rp-c-link: var(--rp-c-brand-light); } :where(:root) { --rp-c-gray: #8e8e8e; --rp-c-gray-light-1: #aeaeae; --rp-c-gray-light-2: #c7c7c7; --rp-c-gray-light-3: #d1d1d1; --rp-c-gray-light-4: #e5e5e5; --rp-c-gray-light-5: #f2f2f2; --rp-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.02), 0 1px 0 rgba(0, 0, 0, 0.06); --rp-shadow-2: 0 3px 12px rgba(0, 0, 0, 0.06), 0 1px 4px rgba(0, 0, 0, 0.07); --rp-shadow-3: 0 12px 32px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(0, 0, 0, 0.08); --rp-shadow-4: 0 14px 44px rgba(0, 0, 0, 0.12), 0 3px 9px rgba(0, 0, 0, 0.12); --rp-shadow-5: 0 18px 56px rgba(0, 0, 0, 0.16), 0 4px 12px rgba(0, 0, 0, 0.16); --rp-radius: 1rem; --rp-radius-small: 0.5rem; --rp-radius-large: 1.5rem; } ``` --- url: https://rspress.rs/ui/custom-page.md --- > 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. # Customizing page Rspress provides several ways to customize page content: - Adding custom global components. - Adding custom global styles. - Customizing page layout structure. ## Custom global components In some scenarios, you may need custom global components on every page. Use the `globalUIComponents` option for this. ### How to use Add the following configuration in `rspress.config.ts`: ```ts title="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: ```ts title="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: ```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
This is a global layout component
; } ``` 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. ## Custom layout structure Rspress provides `pageType` for customizing page layout. ### Using pageType Rspress convention-based routing supports two route types: document routes, written with `.md(x)` files, and component routes, written with `.jsx` or `.tsx` files. For document routes, add the `pageType` field in frontmatter to specify the page layout: ```mdx title="foo.mdx" --- pageType: custom --- ``` For component routes, export `frontmatter` to specify `pageType`: ```tsx title="foo.tsx" export const frontmatter = { // Declare layout type pageType: 'custom', }; ``` `pageType` supports the following values: - `home`: **Homepage**, including the top navbar and homepage layout content. - `doc`: **Doc page**, including the top navbar, left sidebar, body content, and right-side outline. - `doc-wide`: **Wide doc page**, where the main content can occupy a wider area when `outline: false` and `sidebar: false` are used together. - `custom`: **Custom page**, including the top navbar and custom content. - `blank`: Also a **custom page**, but without the top navbar. - `404`: **Not found page**. ### Using fine-grained switches In addition to page-level `pageType` configuration, Rspress provides fine-grained frontmatter switches: - `navbar`: Whether to display the top navbar. Set it to `false` to hide the navbar. - `sidebar`: Whether to display the sidebar. Set it to `false` to hide the sidebar. - `outline`: Whether to display the outline. Set it to `false` to hide the outline. - `footer`: Whether to display the footer. Set it to `false` to hide the footer. - `globalComponents`: Whether to display global components. Set it to `false` to hide global components. Example: ```mdx title="foo.mdx" --- navbar: false sidebar: false outline: false footer: false globalUIComponents: false --- ``` --- url: https://rspress.rs/ui/tailwindcss.md --- > 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. # Tailwind CSS [Tailwind CSS](https://tailwindcss.com/) is a utility-first CSS framework for rapidly building custom user interfaces. It can be used with MDX files in Rspress to help you style your documentation more efficiently, for example: ```mdx title="docs/foo.mdx" # Foo
Hello world!
``` Rspress is built on [Rsbuild](https://rsbuild.rs/), so Tailwind CSS v4 can be integrated with the same Rsbuild plugin recommended by Rsbuild. For more details, see: - [Rsbuild - Tailwind CSS v4](https://rsbuild.rs/guide/styling/tailwindcss) - [Rsbuild - Tailwind CSS v3](https://rsbuild.rs/guide/styling/tailwindcss-v3) - [Rsbuild - Tailwind CSS plugin](https://rsbuild.rs/plugins/list/plugin-tailwindcss) Below is a guide for integrating Tailwind CSS v4 with Rspress. :::tip All Rspress built-in components use BEM naming conventions and do not use Tailwind CSS internally. Your project owns the Tailwind CSS dependency and build plugin, which avoids version conflicts with Rspress. ::: ### Install dependencies ```sh [npm] npm add @rsbuild/plugin-tailwindcss tailwindcss -D ``` ```sh [yarn] yarn add @rsbuild/plugin-tailwindcss tailwindcss -D ``` ```sh [pnpm] pnpm add @rsbuild/plugin-tailwindcss tailwindcss -D ``` ```sh [bun] bun add @rsbuild/plugin-tailwindcss tailwindcss -D ``` ```sh [deno] deno add npm:@rsbuild/plugin-tailwindcss npm:tailwindcss -D ``` ### Create Tailwind CSS file Create a `tailwind.css` file in the root of your project: ```css title="tailwind.css" @import 'tailwindcss'; @custom-variant dark (&:where(.dark, .dark *)); ``` :::tip Tailwind CSS v4 is not designed to be used with CSS preprocessors like Sass, Less, or Stylus. Keep `@import 'tailwindcss';` at the beginning of a `.css` file. ::: :::tip Dark Mode Rspress toggles dark mode by checking the `.dark` class on the `html` element, so you need to configure `@custom-variant`. See [Tailwind Docs - Dark Mode](https://tailwindcss.com/docs/dark-mode) for details. ::: ### Configure Rspress In your `rspress.config.ts`, use the `globalStyles` option to import the Tailwind CSS file: ```ts title="rspress.config.ts" import * as path from 'node:path'; import { pluginTailwindcss } from '@rsbuild/plugin-tailwindcss'; import { defineConfig } from '@rspress/core'; export default defineConfig({ root: path.join(__dirname, 'docs'), globalStyles: path.join(__dirname, 'tailwind.css'), builderConfig: { plugins: [pluginTailwindcss()], }, }); ``` If your project already has a PostCSS setup, you can also follow the Rsbuild guide to use `@tailwindcss/postcss` instead. ### Usage Now you can use Tailwind utility classes in your MDX files: ```mdx title="docs/foo.mdx" # Foo
Hello world!
``` --- url: https://rspress.rs/ui/shadcn-ui.md --- > 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. # shadcn/ui [shadcn/ui](https://ui.shadcn.com/) is a collection of reusable components built with Radix UI / Base UI and Tailwind CSS. This guide covers how to use shadcn/ui components in your Rspress documentation site. Make sure you have already set up [Tailwind CSS](https://rspress.rs/ui/tailwindcss.md) in your project before proceeding. ### Configure path aliases Add `paths` to the `compilerOptions` in your `tsconfig.json` so that shadcn/ui components can be resolved correctly: ```json title="tsconfig.json" { "compilerOptions": { "paths": { "@/*": ["./src/*"] } }, "include": ["doc", "src", "rspress.config.ts"] } ``` ### Create components.json and utility function Since `shadcn init` cannot automatically detect the Rspress framework, you need to follow the [manual installation](https://ui.shadcn.com/docs/installation/manual) approach to create the configuration files. Create a `components.json` file in your project root to configure the shadcn/ui CLI: ```json title="components.json" { "$schema": "https://ui.shadcn.com/schema.json", "style": "new-york", "tailwind": { "config": "", "css": "tailwind.css", "baseColor": "neutral", "cssVariables": true, "prefix": "" }, "rsc": false, "tsx": true, "aliases": { "utils": "@/lib/utils", "components": "@/components", "ui": "@/components/ui", "lib": "@/lib", "hooks": "@/hooks" } } ``` :::tip - `tailwind.config` is omitted because Tailwind CSS v4 no longer requires a config file. - `rsc` is set to `false` because Rspress does not use React Server Components. ::: Then install the dependencies and create the utility function: ```sh [npm] npm install clsx tailwind-merge class-variance-authority ``` ```sh [yarn] yarn add clsx tailwind-merge class-variance-authority ``` ```sh [pnpm] pnpm add clsx tailwind-merge class-variance-authority ``` ```sh [bun] bun add clsx tailwind-merge class-variance-authority ``` ```sh [deno] deno add npm:clsx npm:tailwind-merge npm:class-variance-authority ``` ```ts title="src/lib/utils.ts" import { type ClassValue, clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } ``` ### Add components Use the `shadcn` CLI to add the components you need. For example, to add a Button: ```sh [npx] npx shadcn@latest add button ``` ```sh [yarn] yarn dlx shadcn@latest add button ``` ```sh [pnpm] pnpm dlx shadcn@latest add button ``` ```sh [bunx] bunx shadcn@latest add button ``` ```sh [deno] deno run -A npm:shadcn@latest add button ``` ### Usage in MDX Import and use components in your MDX files: ```mdx title="doc/index.mdx" import { Button } from '@/components/ui/button'; # My page ``` :::tip Since shadcn/ui is not a traditional npm package but a collection of copy-paste components, you have full control over the component code and can customize them as needed. ::: --- url: https://rspress.rs/ui/components/index.md --- > 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. # Doc Components ## Doc Components ### [Badge](/ui/components/badge.md) ### [Callout](/ui/components/callout.md) ### [CodeBlockRuntime](/ui/components/code-block-runtime.md) ### [PackageManagerTabs](/ui/components/package-manager-tabs.md) ### [PageTabs](/ui/components/page-tabs.md) ### [Prompt](/ui/components/prompt.md) ### [SourceCode](/ui/components/source-code.md) ### [Steps](/ui/components/steps.md) ### [Tabs/Tab](/ui/components/tabs.md) --- url: https://rspress.rs/ui/components/badge.md --- > 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. # Badge The Badge component is used to display a small inline badge. ## Usage ```mdx title="index.mdx" import { Badge } from '@rspress/core/theme'; ``` NEW ## Types The Badge component supports four types, each with a different color: ```mdx preview title="index.mdx" import { Badge } from '@rspress/core/theme'; ``` ## Outline style ```mdx preview title="index.mdx" import { Badge } from '@rspress/core/theme'; ``` ## Custom children You can use the `children` prop to render custom content inside the badge: ```mdx preview title="index.mdx" import { Badge, IconSearch, SvgWrapper } from '@rspress/core/theme'; Rspress Search ``` ## Inline with text Badge can be used inline with text: ```mdx preview title="index.mdx" import { Badge } from '@rspress/core/theme'; Inlined with text ``` ## In headings Badge can be used in headings: ```mdx ##### H5 Heading #### H4 Heading ### H3 Heading ``` ##### H5 Heading Info #### H4 Heading Warning ### H3 Heading Danger ## Props ```ts interface BadgeProps { /** * The content to display inside the badge. Can be a string or React nodes. */ children?: React.ReactNode; /** * The type of badge, which determines its color and style. * @default 'tip' */ type?: 'tip' | 'info' | 'warning' | 'danger'; /** * The text content to display inside the badge (for backwards compatibility). */ text?: string; /** * Whether to display the badge with an outline style. * @default false */ outline?: boolean; } ``` --- url: https://rspress.rs/ui/components/callout.md --- > 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. # Callout The Callout component is used to display highlighted information blocks such as tips, warnings, and notes. :::tip We recommend using [container syntax](https://rspress.rs/guide/use-mdx/container.md) which works in both Markdown and MDX files. ::: ## Container syntax In most cases, use the container syntax to create callouts: **Rendered Result** :::note This is a `note` callout ::: :::tip This is a `tip` callout ::: :::important This is an `important` callout ::: :::info This is an `info` callout ::: :::warning This is a `warning` callout ::: :::danger This is a `danger` callout ::: :::details This is a `details` callout ::: :::tip Custom Title This is a callout with a custom title ::: :::tip\{title="Custom Title"} This is a callout with a custom title ::: **Syntax** ```markdown :::note This is a `note` callout ::: :::tip This is a `tip` callout ::: :::important This is an `important` callout ::: :::info This is an `info` callout ::: :::warning This is a `warning` callout ::: :::danger This is a `danger` callout ::: :::details This is a `details` callout ::: :::tip Custom Title This is a callout with a custom title ::: :::tip{title="Custom Title"} This is a callout with a custom title ::: ``` For more container syntax details, see [Container](https://rspress.rs/guide/use-mdx/container.md). ## Component usage You can also use the Callout component directly in MDX files: ```mdx title="index.mdx" import { Callout } from '@rspress/core/theme'; This is a tip callout This is a warning with custom title ``` Tip This is a tip callout Warning This is a warning with custom title ## Customization You can eject the Callout component to customize its styles and behavior: ```bash npx rspress eject Callout ``` This will copy the component to `theme/components/Callout`. After customization, re-export it in your `theme/index.tsx`: ```tsx title="theme/index.tsx" export { Callout } from './components/Callout'; export * from '@rspress/core/theme-original'; ``` ## Props ```ts interface CalloutProps { /** * The type of callout, which determines its color and icon. */ type: | 'tip' | 'note' | 'important' | 'warning' | 'caution' | 'danger' | 'info' | 'details'; /** * Custom title for the callout. If not provided, the capitalized type will be used. */ title?: string; /** * The content to display inside the callout. */ children: React.ReactNode; } ``` --- url: https://rspress.rs/ui/components/code-block-runtime.md --- > 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. # CodeBlockRuntime `CodeBlockRuntime` renders runnable [code blocks](https://rspress.rs/guide/use-mdx/code-blocks.md) at runtime. ## Usage ```tsx title="index.mdx" import { CodeBlockRuntime } from '@rspress/core/theme'; export default function Page() { return ( ); } ``` ```js title=index.js console.log('Hello World!') ``` Pass `lang`, `title`, and `code` to render the block; `shikiOptions` customizes highlighting and also supports transformers. :::warning Use `CodeBlockRuntime` only when necessary. It increases runtime bundle size, especially when multiple languages are included, and cannot benefit from compile-time highlighting. ::: ## Using shiki options Here is an example using a transformer for line highlighting: ```mdx title="foo.mdx" import { CodeBlockRuntime } from '@rspress/core/theme'; import { transformerNotationHighlight } from '@shikijs/transformers'; ``` ```ts title=highlight.ts console.log('Highlighted'); // [!code highlight] // [!code highlight:1] console.log('Highlighted'); console.log('Not highlighted'); ``` ## Importing file content You can use the `?raw` query to import file content as a string and pass it to the `code` prop. See [Rsbuild - Static Assets](https://rsbuild.rs/guide/basic/static-assets) for details. ```mdx title="foo.mdx" import { CodeBlockRuntime } from '@rspress/core/theme'; import codeContent from './example.ts?raw'; ``` This approach is suitable for scenarios where you need to dynamically display external file content, such as showing example code files. :::warning If you only need to reference external files as code blocks, use the static [file code block](https://rspress.rs/guide/use-mdx/code-blocks.md#file-code-block) syntax. It is processed at compile time, with better performance and a smaller bundle size. ::: --- url: https://rspress.rs/ui/components/package-manager-tabs.md --- > 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. # PackageManagerTabs PackageManagerTabs displays commands for different package managers. ## Basic usage ```mdx title="index.mdx" import { PackageManagerTabs } from '@rspress/core/theme'; ``` ```sh [npm] npm install -D @rspress/core ``` ```sh [yarn] yarn add -D @rspress/core ``` ```sh [pnpm] pnpm add -D @rspress/core ``` ```sh [bun] bun add -D @rspress/core ``` ```sh [deno] deno add -D npm:@rspress/core ``` ## Set commands per package manager You can pass an object to define the command for each package manager: ```mdx preview title="index.mdx" import { PackageManagerTabs } from '@rspress/core/theme'; ``` ## Add extra tabs Use `additionalTabs` to add more package managers: ```mdx preview title="index.mdx" import { PackageManagerTabs } from '@rspress/core/theme'; ``` ## Props ```ts type PackageManagerTabProps = ( | { command: string; /** * If true, use local package execution (npx , yarn , pnpm , bun , deno run ). * For packages installed in node_modules. */ exec?: boolean; /** * If true, use remote package execution (npx, yarn dlx, pnpm dlx, bunx, deno run). * For downloading and running packages directly without local install. * Takes priority over exec. */ dlx?: boolean; } | { command: { // Set commands for different package managers npm?: string; yarn?: string; pnpm?: string; bun?: string; deno?: string; }; exec?: never; dlx?: never; } ) & // Configure extra tabs { additionalTabs?: { // Extra package manager name tool: string; // Icon for the extra package manager icon?: React.ReactNode; }[]; }; ``` :::tip - When `command` is a string, the component auto prefixes the correct package manager command and renders npm, yarn, pnpm, bun, and deno tabs by default. - For install commands, yarn, pnpm, bun, and deno tabs automatically replace `install` with `add`. - In the deno tab, packages without an explicit source automatically get the `npm:` prefix. ::: --- url: https://rspress.rs/ui/components/page-tabs.md --- > 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. # PageTabs :::info The PageTabs component creates sub-tabs within a page so a single page can be split into multiple views. To keep anchors and the TOC correct, each page may contain exactly one PageTabs. ::: API How it works ## Basic usage ```mdx title="docs/guide/getting-started.mdx" # Getting started import { PageTabs, PageTab } from '@rspress/core/theme'; ## Foo ## Bar ``` ## Using MDX fragments We recommend using [MDX fragments](https://rspress.rs/guide/use-mdx/components.md) to split a page into multiple sub-pages. ```mdx title="docs/guide/getting-started.mdx" # Getting started import { PageTabs, PageTab } from '@rspress/core/theme'; import Foo from './fragments/_foo.mdx'; import Bar from './fragments/_bar.mdx'; ``` ## Dynamic TOC Based on extensive feedback from V1 users, we found that static TOC extraction often failed when using [MDX fragments](https://rspress.rs/guide/use-mdx/components.md) that include headers. Rspress V2 introduces Dynamic TOC, which generates the TOC at runtime by monitoring DOM changes through [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver). This keeps the TOC accurate while letting you fully leverage [MDX fragments](https://rspress.rs/guide/use-mdx/components.md), making the `` component possible. ```ts import { useDynamicTOC } from '@rspress/core/theme'; ``` --- url: https://rspress.rs/ui/components/prompt.md --- > 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. # Prompt `Prompt` highlights reusable instructions that readers can copy and paste directly into their AI tools. ## Usage Import `Prompt` in your MDX file before using it: ```mdx title="index.mdx" import { Prompt } from '@rspress/core/theme'; ``` For your Agent Start a Rspress project in one shot Copy this prompt and send it to your AI agent. It will scaffold a new Rspress site for you automatically. Copy Prompt Create a Rspress project by following the official quick start guide at https://rspress.rs/guide/start/getting-started.md. 1. Scaffold the project with `create rspress@latest`. 2. Install dependencies. 3. Start the dev server. 4. Verify the site renders correctly. The prompt content can be folded. Click anywhere on the card to copy the full prompt text. ## Custom content Set `custom` to keep only the eyebrow and outer border, then render the inner content with MDX children. Custom prompts do not include copy or collapse behavior. ```mdx title="index.mdx" **hello** world ``` For your Agent **hello** world :::tip If the prompt content is long, you can put it in a separate file and import it via `?raw`: ```mdx title="index.mdx" import { Prompt } from '@rspress/core/theme'; import promptText from './_prompt.txt?raw'; ``` ::: ## Use with custom themes You can eject the `Prompt` component to customize its styles and behavior: ```bash npx rspress eject Prompt ``` This copies the component into `theme/components/Prompt`. After customization, re-export it in your `theme/index.tsx`: ```tsx title="theme/index.tsx" export { Prompt } from './components/Prompt'; export * from '@rspress/core/theme-original'; ``` ## Props ```ts interface PromptProps extends React.HTMLAttributes { /** * Render custom MDX content without copy or collapse behavior. * @default false */ custom?: boolean; /** * Inline description rendered in the prompt header. */ description?: string; /** * Header label for the prompt block. * @default 'Agent Prompt' */ title?: string; /** * Eyebrow label shown above the title. * @default 'For your Agent' */ eyebrow?: string; /** * Controls the initial folded state. * @default true */ defaultCollapsed?: boolean; /** * The prompt text to display and copy. */ prompt?: string; } ``` --- url: https://rspress.rs/ui/components/source-code.md --- > 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. # SourceCode `SourceCode` renders a link to repository source code. ## Usage ```mdx title="index.mdx" preview import { SourceCode } from '@rspress/core/theme'; ``` ## Props ```ts interface SourceCodeProps { /** Source code link */ href: string; /** Code hosting platform, determines which icon to display */ platform?: 'github' | 'gitlab'; } ``` Use `platform` to switch the icon between GitHub and GitLab. Defaults to `'github'`. --- url: https://rspress.rs/ui/components/steps.md --- > 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. # Steps `Steps` renders Markdown content into step-by-step instruction blocks. ## Usage ### Step 1 Content for step 1. ### Step 2 > Content for step 2. ```mdx title="index.mdx" import { Steps } from '@rspress/core/theme'; ### Step 1 Content for step 1. ### Step 2 > Content for step 2. ``` Write headings inside ``; each heading starts a new step. Markdown under a heading becomes that step’s body. --- url: https://rspress.rs/ui/components/tabs.md --- > 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. # Tabs/Tab `Tabs` and `Tab` switch between multiple content panes. ## Usage ```mdx title="index.mdx" preview import { Tab, Tabs } from '@rspress/core/theme'; Tab 1 content Tab 2 content ``` ## Code blocks ````mdx title="index.mdx" preview import { Tab, Tabs } from '@rspress/core/theme'; ```tsx title="src/index.mjs" import foo from 'foo'; import bar from 'bar'; ``` ```tsx title="src/index.cjs" const foo = require('foo'); const bar = require('bar'); ``` ```` ## Group synchronization Use the same `groupId` to synchronize the active tab across multiple `Tabs`. ```mdx title="index.mdx" preview import { Tab, Tabs } from '@rspress/core/theme'; npm install rspress pnpm add rspress npm run dev pnpm dev ``` ## Custom labels Use `label` on each `Tab` to render custom tab labels. ```mdx title="index.mdx" preview import { IconGithub, IconGitlab, SvgWrapper, Tab, Tabs, } from '@rspress/core/theme'; GitHub } > GitHub repository settings GitLab } > GitLab project settings ``` ## Separate labels and content Use `values` to define tab labels separately from panel content. Each item provides a `value`, and the matching `` supplies the content. Use `defaultValue` to preselect a tab by `value`. ```mdx title="index.mdx" preview import { Tab, Tabs } from '@rspress/core/theme'; This is an apple 🍎 This is an orange 🍊 This is a banana 🍌 ``` ## Props ```ts interface TabsProps { children: React.ReactNode; values?: Array<{ label: React.ReactNode; value: string }>; defaultIndex?: number; defaultValue?: string; groupId?: string; tabPosition?: 'left' | 'center'; } interface TabProps { label?: React.ReactNode; value?: string; children: React.ReactNode; } ``` `label` accepts any renderable React node, so it can include icons or custom markup. Use `defaultIndex` to preselect a tab by index, or `defaultValue` to preselect a tab by `value`; `groupId` syncs selection across multiple `Tabs`; `tabPosition` sets list alignment. --- url: https://rspress.rs/ui/runtime-components/index.md --- > 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. # Runtime components ## Runtime Components ### [BrowserOnly](/ui/runtime-components/browser-only.md) ### [Head](/ui/runtime-components/head.md) ### [NoSSR](/ui/runtime-components/no-ssr.md) --- url: https://rspress.rs/ui/runtime-components/browser-only.md --- > 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. # BrowserOnly Rspress statically renders your React code into HTML during the build phase. This means the code is executed in a Node.js environment, where browser globals like `window`, `document`, and `localStorage` do not exist. When a component or third-party library depends on these browser-only APIs, you need to escape from [static site generation (SSG)](https://rspress.rs/guide/basic/ssg.md). `BrowserOnly` renders a fallback during the SSG phase and renders its children only after hydration is complete in the browser. ## Usage ```mdx title="index.mdx" import { BrowserOnly } from '@rspress/core/runtime'; Loading...}> {async () => { const { LibComponent } = await import('some-lib-that-accesses-window'); return ; }} ``` Loading... ## Why must children be a function? The `children` of `BrowserOnly` must be a function that returns a React node. It is important to realize that the children is not a JSX element, but a function. This is an intentional design decision. Consider this incorrect code: ```mdx import { BrowserOnly } from '@rspress/core/runtime'; {/* Do not do this — it still evaluates `window` during SSG */} Current URL: {window.location.href} ; ``` If you pass JSX directly as children, React evaluates the expressions inside while building the JSX tree, before `window` and other browser objects are available, which causes errors. By writing children as a function, the expressions are not evaluated in advance. They only execute after BrowserOnly confirms it is running in the browser, thus avoiding browser API access during SSR. ## How it works `BrowserOnly` is implemented using **useEffect + dynamic imports**, thus avoiding SSR compatibility issues. --- url: https://rspress.rs/ui/runtime-components/head.md --- > 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. # Head The Head component lets you inject custom head content (built on [unhead](https://www.npmjs.com/package/unhead)). If you prefer declaring head entries as objects, or need to compute them from component state and props, use the [`useHead`](https://rspress.rs/ui/hooks/use-head.md) hook. ## Usage ```mdx title="index.mdx" import { Head } from '@rspress/core/runtime'; ``` Use it inside MDX or React pages to add meta tags, canonical links, Open Graph data, favicons, and more. --- url: https://rspress.rs/ui/runtime-components/no-ssr.md --- > 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. # NoSSR :::danger Deprecated `NoSSR` is deprecated. Use [`BrowserOnly`](https://rspress.rs/ui/runtime-components/browser-only.md) instead. ::: `NoSSR` is used to skip server-side rendering of its subtree. ## Usage ```mdx title="index.mdx" import { NoSSR } from '@rspress/core/runtime'; ``` ## See also - [`BrowserOnly`](https://rspress.rs/ui/runtime-components/browser-only.md) — render content only in the browser after hydration. --- url: https://rspress.rs/ui/icons/index.md --- > 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. # Built-in icons When Rspress uses icons, it uses a `SvgWrapper` component to render icons. It supports icon as a URL or an svgr React component: ```ts type Icon = React.FC> | string; ``` The following code is an example of how Rspress uses `IconGithub`: ```mdx preview import { SvgWrapper, IconGithub } from '@rspress/core/theme'; ``` ## Usage When you want to replace Rspress built-in icons, use [Custom Theme - Re-export](https://rspress.rs/guide/basic/custom-theme.md#reexport) for replacement. ```tsx title="theme/index.tsx" export { IconGithub } from './my-icons'; export * from '@rspress/core/theme-original'; ``` All icons used by Rspress are as follows: [Source Code](https://github.com/web-infra-dev/rspress/blob/main/packages/core/src/theme/icons.ts) ```tsx preview import { SvgWrapper, IconAnthropic, IconArrowDown, IconArrowRight, IconClose, IconCopy, IconDeprecated, IconDown, IconEdit, IconEmpty, IconExperimental, IconExternalLink, IconFile, IconGithub, IconGitlab, IconHeader, IconJump, IconLoading, IconMenu, IconMoon, IconOpenAI, IconOpenInChat, IconScrollToTop, IconSearch, IconSmallMenu, IconSuccess, IconSun, IconTitle, IconWrap, IconWrapped, IconLink, } from '@rspress/core/theme'; export default () => { return (
{[ IconAnthropic, IconArrowDown, IconArrowRight, IconClose, IconCopy, IconDeprecated, IconDown, IconEdit, IconEmpty, IconExperimental, IconExternalLink, IconFile, IconGithub, IconGitlab, IconHeader, IconJump, IconLoading, IconMenu, IconMoon, IconOpenAI, IconOpenInChat, IconScrollToTop, IconSearch, IconSmallMenu, IconSuccess, IconSun, IconTitle, IconWrap, IconWrapped, IconLink, ].map((Icon, idx) => ( ))}
); }; ``` --- url: https://rspress.rs/ui/layout-components/index.md --- > 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. # Layout Components ## Layout Components ### [Banner](/ui/layout-components/banner.md) ### [DocFooter](/ui/layout-components/doc-footer.md) ### [EditLink](/ui/layout-components/edit-link.md) ### [getCustomMDXComponent](/ui/layout-components/get-custom-mdx-component.md) ### [HomeBackground](/ui/layout-components/home-background.md) ### [HomeFeature](/ui/layout-components/home-feature.md) ### [HomeFooter](/ui/layout-components/home-footer.md) ### [HomeHero](/ui/layout-components/home-hero.md) ### [HomeLayout](/ui/layout-components/home-layout.md) ### [LastUpdated](/ui/layout-components/last-updated.md) ### [Layout](/ui/layout-components/layout.md) ### [NavTitle](/ui/layout-components/nav-title.md) ### [OverviewGroup](/ui/layout-components/overview-group.md) ### [PrevNextPage](/ui/layout-components/prev-next-page.md) ### [Root](/ui/layout-components/root.md) ### [Tag](/ui/layout-components/tag.md) --- url: https://rspress.rs/ui/layout-components/banner.md --- > 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. # Banner `Banner` displays a notification banner at the top of the page, supporting link navigation and close functionality. ## Usage Use the Banner component through custom Layout: ```tsx title="theme/index.tsx" import { Layout as BasicLayout, Banner } from '@rspress/core/theme'; import { useLang } from '@rspress/core/runtime'; const Layout = () => { const lang = useLang(); return ( } /> ); }; export { Layout }; ``` ## Props ```ts type BannerProps = { /** Whether to display the Banner, defaults to true */ display?: boolean; /** Custom CSS class name */ className?: string; } & ( | { /** Storage method for closed state, defaults to 'localStorage' */ storage?: 'localStorage' | 'sessionStorage' | false; /** Storage key for closed state, defaults to 'rp-banner-closed' */ storageKey?: string; /** Link to navigate when clicked */ href: string; /** Message content to display */ message: string | ReactNode; } | { /** Fully customized content */ customChildren: ReactNode; } ); ``` ### display - **Type:** `boolean` - **Default:** `true` Controls whether the Banner is displayed. ### storage - **Type:** `'localStorage' | 'sessionStorage' | false` - **Default:** `'localStorage'` How to store the closed state after user closes the Banner. Set to `false` to disable storage. ### storageKey - **Type:** `string` - **Default:** `'rp-banner-closed'` Storage key for the closed state. ### href - **Type:** `string` Link to navigate when clicking the Banner. ### message - **Type:** `string | ReactNode` Message content displayed in the Banner. ### customChildren - **Type:** `ReactNode` Fully customized Banner content. When using this property, `href` and `message` will be ignored. --- url: https://rspress.rs/ui/layout-components/doc-footer.md --- > 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. # DocFooter `DocFooter` renders the footer area at the bottom of doc pages, including the edit link, last updated time, and prev/next page navigation. ## Usage This component is automatically rendered at the bottom of doc pages and usually does not need to be used manually. To customize it, eject the component: ```tsx preview import { DocFooter as BasicDocFooter } from '@rspress/core/theme-original'; export default function DocFooter() { return ; } ``` ```tsx title="theme/components/DocFooter/index.tsx" file="/../packages/core/src/theme/components/DocFooter/index.tsx" import { EditLink, LastUpdated, PrevNextPage } from '@rspress/core/theme'; import './index.scss'; export function DocFooter() { return (
); } ``` ## Included components `DocFooter` consists of the following components: - [EditLink](https://rspress.rs/ui/layout-components/edit-link.md) - Displays "Edit this page" link - [LastUpdated](https://rspress.rs/ui/layout-components/last-updated.md) - Displays page last updated time - [PrevNextPage](https://rspress.rs/ui/layout-components/prev-next-page.md) - Displays prev/next page navigation --- url: https://rspress.rs/ui/layout-components/edit-link.md --- > 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. # EditLink `EditLink` renders an "Edit this page" link that navigates to the document source file's editing page (e.g., GitHub). ## Usage This component is rendered automatically in both the [DocFooter](https://rspress.rs/ui/layout-components/doc-footer.md) and the right-side outline panel, and doesn't need manual usage. ```tsx preview import { EditLink as BasicEditLink } from '@rspress/core/theme-original'; export default function EditLink() { return ; } ``` ## Props | Prop | Type | Default | Description | | ----------- | --------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | `isOutline` | `boolean` | `false` | When `true`, renders a compact style with an edit icon for use in the outline panel. When `false`, renders the default text link style for the doc footer. | ## Related configuration Configure `editLink` in `rspress.config.ts`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { editLink: { docRepoBaseUrl: 'https://github.com/web-infra-dev/rspress/tree/main/website/docs', text: '📝 Edit this page on GitHub', }, }, }); ``` - `docRepoBaseUrl` - Base URL of the documentation repository - `text` - Text displayed on the link If `editLink` is not configured, the component won't render anything. --- url: https://rspress.rs/ui/layout-components/get-custom-mdx-component.md --- > 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. # getCustomMDXComponent `getCustomMDXComponent` returns the default components used by the Rspress doc layout to render native Markdown and MDX elements. Use it from a custom theme when you need to override how headings, links, code blocks, images, tables, and other document elements are rendered. ## Usage Import `getCustomMDXComponent` from `@rspress/core/theme-original` in your custom theme, then export a new function with the same name: ```tsx title="theme/index.tsx" import { getCustomMDXComponent as getBasicCustomMDXComponent } from '@rspress/core/theme-original'; function getCustomMDXComponent() { const mdxComponents = getBasicCustomMDXComponent(); const { h1: H1, p: P } = mdxComponents; return { ...mdxComponents, h1: props => ( <>

below h1

), }; } export { getCustomMDXComponent }; export * from '@rspress/core/theme-original'; ``` The exported `getCustomMDXComponent` will replace the default one for the site. Rspress will call it when rendering doc content and pass the returned component map to MDX. In the example above, every H1 keeps the default renderer and gets an extra paragraph below it. --- url: https://rspress.rs/ui/layout-components/home-background.md --- > 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. # HomeBackground This component is part of the [homepage](https://rspress.rs/guide/basic/home-page.md). `HomeBackground` renders background effects on the homepage and automatically sets the navbar to transparent style. ## Usage Modify or override through [custom theme](https://rspress.rs/guide/basic/custom-theme.md). ```tsx import { HomeBackground as BasicHomeBackground } from '@rspress/core/theme-original'; export function HomeBackground() { return ; } ``` --- url: https://rspress.rs/ui/layout-components/home-feature.md --- > 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. # HomeFeature This component is part of the [homepage](https://rspress.rs/guide/basic/home-page.md). `HomeFeature` renders a feature grid below the Hero section on the homepage. ## Usage Modify or override through [custom theme](https://rspress.rs/guide/basic/custom-theme.md). You can configure `features` in the frontmatter of your mdx file, and the component will automatically read it through [`useFrontmatter`](https://rspress.rs/ui/hooks/use-frontmatter.md). For detailed configuration options, refer to [Frontmatter Configuration](https://rspress.rs/api/config/config-frontmatter.md#features). ```tsx preview import { HomeFeature as BasicHomeFeature } from '@rspress/core/theme-original'; export default function HomeFeature() { return ; } ``` ## Props ### features - **Type:** `Feature[]` - **Default:** Read from frontmatter ```ts interface Feature { /** * Feature icon, supports: * - Emoji: '🚀' * - HTML string: '...' * - SVG string: '...' * - Image URL: '/icons/feature.svg' or 'https://example.com/icon.png' */ icon: string; /** Feature title */ title: string; /** Feature description, supports HTML string */ details: string; /** Grid column span, supports 2, 3, 4, 6, defaults to 4 */ span?: 2 | 3 | 4 | 6; /** Link to navigate when clicking the card */ link?: string; } ``` - `span` controls how many grid columns each card occupies, total 12 columns - `icon` supports emoji, HTML strings, SVG strings, and image URLs - `details` supports HTML strings - Setting `link` makes the card clickable for navigation --- url: https://rspress.rs/ui/layout-components/home-footer.md --- > 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. # HomeFooter This component is part of the [homepage](https://rspress.rs/guide/basic/home-page.md). `HomeFooter` renders footer information at the bottom of the homepage. ## Usage Modify or override through [custom theme](https://rspress.rs/guide/basic/custom-theme.md). ```tsx preview import { HomeFooter as BasicHomeFooter } from '@rspress/core/theme-original'; export default function HomeFooter() { return ; } ``` This component doesn't accept any props. It internally reads the [`themeConfig.footer`](https://rspress.rs/api/config/config-theme.md#footer) configuration through [`useSite`](https://rspress.rs/ui/hooks/use-site.md). --- url: https://rspress.rs/ui/layout-components/home-hero.md --- > 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. # HomeHero This component is part of the [homepage](https://rspress.rs/guide/basic/home-page.md). `HomeHero` renders the Hero section on the homepage. ## Usage Modify or override through [custom theme](https://rspress.rs/guide/basic/custom-theme.md). ```tsx import { HomeHero as BasicHomeHero } from '@rspress/core/theme-original'; export default function HomeHero() { return ; } ``` The `HomeHero` component reads the `hero` configuration from frontmatter through [`useFrontmatter`](https://rspress.rs/ui/hooks/use-frontmatter.md). For detailed `hero` configuration options, refer to [Frontmatter Configuration](https://rspress.rs/api/config/config-frontmatter.md#hero). ### Custom slots Use the `beforeHeroActions` and `afterHeroActions` props to insert custom content before and after the action buttons: ```tsx title="index.mdx" import { HomeHero } from '@rspress/core/theme'; Content before buttons} afterHeroActions={
Content after buttons
} />; ``` ## Props ### beforeHeroActions - **Type:** `React.ReactNode` Custom content to insert before the Hero buttons. ### afterHeroActions - **Type:** `React.ReactNode` Custom content to insert after the Hero buttons. --- url: https://rspress.rs/ui/layout-components/home-layout.md --- > 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. # HomeLayout `HomeLayout` is the layout component for the [homepage](https://rspress.rs/guide/basic/home-page.md), responsible for integrating and rendering the Hero, Features, and Footer sections. ## Usage Modify or override through [custom theme](https://rspress.rs/guide/basic/custom-theme.md): ```tsx title="theme/index.tsx" import { HomeLayout as BasicHomeLayout } from '@rspress/core/theme-original'; export default function HomeLayout() { return ; } ``` The `HomeLayout` component reads the `hero` and `features` configuration from frontmatter through [`useFrontmatter`](https://rspress.rs/ui/hooks/use-frontmatter.md). For detailed configuration options, refer to [Frontmatter Configuration](https://rspress.rs/api/config/config-frontmatter.md#hero). ### Custom slots Use slot props to insert custom content before and after each section: ```tsx title="theme/index.tsx" import { HomeLayout as BasicHomeLayout } from '@rspress/core/theme-original'; export default function HomeLayout() { return ( Content before Hero} afterHero={
Content after Hero
} beforeFeatures={
Content before Features
} afterFeatures={
Content after Features
} beforeHeroActions={
Content before Hero buttons
} afterHeroActions={
Content after Hero buttons
} /> ); } ``` ## Props ### beforeHero - **Type:** `React.ReactNode` Custom content to insert before the Hero section. ### afterHero - **Type:** `React.ReactNode` Custom content to insert after the Hero section. ### beforeHeroActions - **Type:** `React.ReactNode` Custom content to insert before the Hero buttons, passed to the [HomeHero](https://rspress.rs/ui/layout-components/home-hero.md) component. ### afterHeroActions - **Type:** `React.ReactNode` Custom content to insert after the Hero buttons, passed to the [HomeHero](https://rspress.rs/ui/layout-components/home-hero.md) component. ### beforeFeatures - **Type:** `React.ReactNode` Custom content to insert before the Features section. ### afterFeatures - **Type:** `React.ReactNode` Custom content to insert after the Features section. ## Sub-components `HomeLayout` uses the following components internally: - [HomeBackground](https://rspress.rs/ui/layout-components/home-background.md) - Homepage background - [HomeHero](https://rspress.rs/ui/layout-components/home-hero.md) - Hero section - [HomeFeature](https://rspress.rs/ui/layout-components/home-feature.md) - Features section - [HomeFooter](https://rspress.rs/ui/layout-components/home-footer.md) - Footer section --- url: https://rspress.rs/ui/layout-components/last-updated.md --- > 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. # LastUpdated `LastUpdated` displays the page's last updated time, and optionally the last author. Typically used with the theme's `lastUpdated` configuration. ## Usage ```tsx preview import { LastUpdated as BasicLastUpdated } from '@rspress/core/theme-original'; export default function LastUpdated() { return ; } ``` This component doesn't accept any props and automatically reads the last updated time from page metadata. ## Related configuration Enable `lastUpdated` in `rspress.config.ts`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { lastUpdated: true, }, }); ``` When `lastUpdated` is enabled, the component automatically reads and formats the page metadata. ### Displaying the author Configure `lastUpdated.author` to display the last commit author: ```ts title="rspress.config.ts" export default defineConfig({ themeConfig: { lastUpdated: { // Show the commit author's name: // author: true, // Or use custom display text: author: ({ name, email }) => `${name} <${email}>`, }, }, }); ``` The callback receives `{ name, email, filePath }` (the commit author info from `git log` and the source file path) and returns the string to render. To customize the display text or time format, you can export and modify `theme/components/LastUpdated/index.tsx` using `rspress eject LastUpdated`. --- url: https://rspress.rs/ui/layout-components/layout.md --- > 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. # Layout `Layout` is the core layout component of Rspress, serving as the layout container for the entire page. It provides rich slot props to extend the default theme layout without ejecting. ## Usage Use the Layout component through [custom theme](https://rspress.rs/guide/basic/custom-theme.md): ```tsx title="theme/index.tsx" import { Layout as BasicLayout } from '@rspress/core/theme-original'; const Layout = () => some content} />; export { Layout }; export * from '@rspress/core/theme-original'; ``` ## Slot props The `Layout` component provides a series of slot props for extending the default theme layout: ```tsx title="theme/index.tsx" import { Layout as BasicLayout, getCustomMDXComponent as basicGetCustomMDXComponent, } from '@rspress/core/theme-original'; const Layout = () => ( beforeHero} /* After homepage Hero section */ afterHero={
afterHero
} /* Before homepage Features section */ beforeFeatures={
beforeFeatures
} /* After homepage Features section */ afterFeatures={
afterFeatures
} /* Before doc page Footer section */ beforeDocFooter={
beforeDocFooter
} /* After doc page Footer section */ afterDocFooter={
afterDocFooter
} /* At the beginning of doc page */ beforeDoc={
beforeDoc
} /* At the end of Doc page */ afterDoc={
afterDoc
} /* Before document content */ beforeDocContent={
beforeDocContent
} /* After document content */ afterDocContent={
afterDocContent
} /* Before navbar */ beforeNav={
beforeNav
} /* After navbar */ afterNav={
afterNav
} /* Before nav title in top-left corner */ beforeNavTitle={😄} /* Nav title */ navTitle={
Custom Nav Title
} /* After nav title in top-left corner */ afterNavTitle={
afterNavTitle
} /* Before nav menu */ beforeNavMenu={
beforeNavMenu
} /* After nav menu */ afterNavMenu={
afterNavMenu
} /* Above left sidebar */ beforeSidebar={
beforeSidebar
} /* Below left sidebar */ afterSidebar={
afterSidebar
} /* Above right outline */ beforeOutline={
beforeOutline
} /* Below right outline */ afterOutline={
afterOutline
} /* At the very top of the page */ top={
top
} /* At the very bottom of the page */ bottom={
bottom
} /* Custom MDX components */ components={{ h1: props => { const { h1: OriginalH1, p: OriginalP } = basicGetCustomMDXComponent(); return ( <> This is a custom paragraph added after every H1 heading. ); }, }} /> ); export { Layout }; export * from '@rspress/core/theme-original'; ``` --- url: https://rspress.rs/ui/layout-components/nav-title.md --- > 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. # NavTitle This component is part of the navbar. `NavTitle` renders the site Logo and title in the top-left corner of the navbar. ## Usage Use it through a [custom theme](https://rspress.rs/guide/basic/custom-theme.md). The component reads configuration from `rspress.config.ts` through [`useSite`](https://rspress.rs/ui/hooks/use-site.md): ```ts title="rspress.config.ts" import { defineConfig } from 'rspress/config'; export default defineConfig({ title: 'My Site', logo: '/logo.png', // Or support dark/light mode: logo: { light: '/logo-light.png', dark: '/logo-dark.png', }, logoText: 'My Site', }); ``` ### Custom NavTitle You can customize NavTitle through the `navTitle` prop of the Layout component: ```tsx title="theme/index.tsx" import { Layout as BasicLayout } from '@rspress/core/theme-original'; const Layout = () => } />; export { Layout }; export * from '@rspress/core/theme-original'; ``` Or use `beforeNavTitle` and `afterNavTitle` props to insert custom content: ```tsx title="theme/index.tsx" import { Layout as BasicLayout } from '@rspress/core/theme-original'; const Layout = () => ( Before} afterNavTitle={
After
} /> ); export { Layout }; export * from '@rspress/core/theme-original'; ``` For more information about custom themes, see the [Custom Theme](https://rspress.rs/guide/basic/custom-theme.md) documentation. ## Configuration ### logo - **Type:** `string | { light: string; dark: string }` Site Logo. Can be a single image path, or separate images for light/dark mode. ### logoText - **Type:** `string` Text displayed next to the Logo. ### title - **Type:** `string` Site title. Displayed when `logo` and `logoText` are not configured. ## i18n Support For multilingual sites, you can configure `title` in each locale: ```ts title="rspress.config.ts" import { defineConfig } from 'rspress/config'; export default defineConfig({ title: 'My Site', themeConfig: { locales: [ { lang: 'en', title: 'My Site', }, { lang: 'zh', title: '我的网站', }, ], }, }); ``` The NavTitle component will automatically display the corresponding title based on the current language. --- url: https://rspress.rs/ui/layout-components/overview-group.md --- > 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. # OverviewGroup `OverviewGroup` renders group cards in overview pages, displaying page lists and their heading anchors. It's part of the [Overview page](https://rspress.rs/guide/advanced/overview-page.md). ## Usage You can modify the component's styles through [custom theme](https://rspress.rs/guide/basic/custom-theme.md), or use `OverviewGroup` freely for UI display without relying on Rspress's built-in Overview page, for example: ```mdx title="index.mdx" import { OverviewGroup } from '@rspress/core/theme'; ``` ## Usage Test ### [Introduction](/guide/introduction.md) - [What is Rspress](/guide/introduction.md#what-is-rspress) - [Features](/guide/introduction.md#features) ### [Installation](/guide/installation.md) ## Props ### group - **Type:** `Group` - **Required:** Yes ```ts interface GroupItem { /** Item title */ text: string; /** Item link */ link: string; /** List of heading anchors within the page */ headers?: Header[]; /** Custom sub-items list */ items?: { text: string; link: string }[]; } interface Group { /** Group name */ name: string; /** List of items in the group */ items: GroupItem[]; } interface Header { id: string; text: string; depth: number; } ``` - `name` - Group title, rendered as h2 heading - `items` - List of pages in the group - `headers` - Heading anchors within each page, clickable to jump to corresponding position - `items` (within GroupItem) - Custom sub-items, used to replace auto-extracted headers --- url: https://rspress.rs/ui/layout-components/prev-next-page.md --- > 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. # PrevNextPage `PrevNextPage` renders the prev/next page navigation links at the bottom of the page. ## Usage ```tsx preview import { PrevNextPage as BasicPrevNextPage } from '@rspress/core/theme-original'; export default function PrevNextPage() { return ; } ``` This component doesn't accept any props and automatically calculates prev/next page links based on sidebar order. ## How it works The component internally uses the `usePrevNextPage` hook to get prev and next page information: ```ts import { usePrevNextPage } from '@rspress/core/theme'; const { prevPage, nextPage } = usePrevNextPage(); // prevPage: { text: string; link: string } | null // nextPage: { text: string; link: string } | null ``` - Prev/next pages are automatically calculated based on the current page's position in the sidebar - If the current page is the first page, `prevPage` will be `null` - If the current page is the last page, `nextPage` will be `null` --- url: https://rspress.rs/ui/layout-components/root.md --- > 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. # Root `Root` is the wrapper component for the entire application, wrapping all content (including Layout and global UI components). Its source code is as follows: ```tsx export function Root({ children }: RootProps) { return <>{children}; } ``` ## Usage Use it through eject to wrap custom Providers: ```tsx title="theme/components/Root/index.tsx" import type { RootProps } from '@rspress/core/theme'; export function Root({ children }: RootProps) { return {children}; } ``` ## Props ### children - **Type:** `ReactNode` - **Required:** Yes Child elements to render, containing the entire application content. --- url: https://rspress.rs/ui/layout-components/tag.md --- > 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. # Tag The Tag component displays labels in the **sidebar or navbar**. It supports multiple formats, including common tags, SVG icons, images, and plain text. ## Usage Add it through [frontmatter](https://rspress.rs/guide/use-mdx/frontmatter.md) to display it in the sidebar or navbar: ```mdx title="foo.mdx" --- tag: new --- # Foo some text ``` new Multiple tags are supported, separated by `,`: ```mdx --- tag: new, experimental --- ``` newexperimental You can also use it in `_meta.json`. For example: ```json title="_meta.json" [ { "name": "foo", "type": "file", "tag": "new, experimental" } ] ``` :::tip The **sidebar** and **navbar** use the Tag component as the entry point for label rendering. The right-side **outline** is more flexible and supports any React component inside headings. ```mdx title="index.mdx" # Foo ### Bar ``` ::: ## Tag types To keep frontmatter values convenient, the Tag component supports the following tag types: ### Common tags new The component has built-in common tags that display with ``. All common tags are: | tag | Corresponding Badge UI | | -------------- | -------------------------- | | `new` | | | `experimental` | | | `deprecated` | | | `updated` | | :::tip Extending Common Tags The Tag component is ejectable. When you want to extend common tags, you can use wrap/eject to modify the Tag component. The tag value is passed as props to the Tag component. Here's an example from this site adding a custom `theme-only` tag through wrap: ```tsx title="theme/components/Tag/index.tsx" import { Badge as BasicBadge, Tag as BasicTag, } from '@rspress/core/theme-original'; export const Tag = ({ tag }: { tag: string }) => { if (tag === 'theme-only') { return ; } return ; }; ``` ```mdx title="index.mdx" --- tag: new, theme-only --- ``` ::: ### SVG string You can pass an SVG string directly as a tag: ```mdx --- tag: --- ``` ### Image URL You can use an external URL, data URL, or public folder path as a tag: ```mdx --- tag: https://example.com/icon.png --- ``` ```mdx --- tag: data:image/svg+xml;base64,... --- ``` ```mdx --- tag: /icons/status.svg --- ``` ### Plain text Any text that doesn't match the above patterns will be displayed as a plain text Badge: ```tsx import { Tag } from '@rspress/core/theme'; ``` v1.0.0Beta ## Props ```ts interface TagProps { /** * Tag content. Supports: * - Common tags: 'new', 'experimental', 'deprecated', 'updated' * - Multiple common tags: 'new, experimental' * - SVG string: '...' * - Image URL: 'https://...', 'data:...', or '/icons/status.svg' * - Plain text: any other string */ tag?: string; } ``` --- url: https://rspress.rs/ui/hooks/index.md --- > 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. # Built-in hooks ## Built-in Hooks ### [Router hooks](/ui/hooks/router-hooks.md) ### [useDark](/ui/hooks/use-dark.md) ### [useFrontmatter](/ui/hooks/use-frontmatter.md) ### [useHead](/ui/hooks/use-head.md) ### [useI18n](/ui/hooks/use-i18n.md) ### [useLang](/ui/hooks/use-lang.md) ### [~~usePageData~~](/ui/hooks/use-page-data.md) ### [usePage](/ui/hooks/use-page.md) ### [usePages](/ui/hooks/use-pages.md) ### [useSite](/ui/hooks/use-site.md) ### [useVersion](/ui/hooks/use-version.md) --- url: https://rspress.rs/ui/hooks/router-hooks.md --- > 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. # Router hooks Rspress re-exports the routing utilities from `react-router-dom`, letting you access navigation and location data without adding extra dependencies. - **Type:** the same signatures as the corresponding `react-router-dom` hooks Commonly used hooks include `useLocation`, `useNavigate`, `useParams`, `useSearchParams`, and `useMatches`. ```tsx import { useLocation, useNavigate } from '@rspress/core/runtime'; export default function LocationDebugger() { const location = useLocation(); const navigate = useNavigate(); return (
Current path: {location.pathname}
); } ``` --- url: https://rspress.rs/ui/hooks/use-dark.md --- > 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. # useDark `useDark` reports whether the current theme is dark mode. - **Type:** `() => boolean` ```tsx preview import { useDark } from '@rspress/core/runtime'; export default function ThemeSwitchHint() { const isDark = useDark(); return
{isDark ? 'Dark theme enabled' : 'Light theme enabled'}
; } ``` :::warning Note During SSG, `useDark` cannot accurately reflect the user's browser theme setting because SSG is executed at build time. This hook will only return the correct theme value after client-side hydration is complete. If you need to apply dark theme styles during SSG, use the `.dark` CSS selector. Rspress adds the `dark` class name to the document root element, which works correctly in both SSG and client-side rendering: ```css /* Light mode */ .my-component { color: black; background-color: white; } /* Dark mode */ .dark .my-component { color: white; background-color: #1a1a1a; } ``` ::: ``` ``` --- url: https://rspress.rs/ui/hooks/use-frontmatter.md --- > 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. # useFrontmatter `useFrontmatter` returns the [frontmatter](https://rspress.rs/api/config/config-frontmatter.md) of the current page in a convenient object. - **Type:** `() => { frontmatter: FrontMatterMeta }` Example: render a custom badge when the page is marked as `beta` in frontmatter. ```tsx import { useFrontmatter } from '@rspress/core/runtime'; export default function BetaBadge() { const { frontmatter } = useFrontmatter(); return frontmatter.beta ? Beta : null; } ``` > Combine with [`usePage`](https://rspress.rs/ui/hooks/use-page.md) when you also need other page metadata (title, route, toc, etc.). --- url: https://rspress.rs/ui/hooks/use-head.md --- > 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. # useHead `useHead` lets you declare document head tags from React components or custom layouts. - **Type:** `(input: UseHeadInput) => ActiveHeadEntry | void` Rspress re-exports this hook from `@rspress/core/runtime`, so you can use the same head API in custom pages, theme components, and layout code. ```tsx import { useHead } from '@rspress/core/runtime'; export function ProductMeta() { useHead({ title: 'Rspress', meta: [ { name: 'description', content: 'Static site generator based on Rsbuild and MDX.', }, { property: 'og:title', content: 'Rspress', }, ], link: [ { rel: 'canonical', href: 'https://rspress.dev/', }, ], }); return null; } ``` Use `useHead` when your head data is easier to build from JavaScript objects or depends on component state and props. > If you prefer authoring tags directly in MDX, use the [`Head`](https://rspress.rs/ui/runtime-components/head.md) component instead. --- url: https://rspress.rs/ui/hooks/use-i18n.md --- > 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. # useI18n `useI18n` lets you read localized text inside custom components using the configured source. For setup details, see [config.i18nSource](https://rspress.rs/api/config/config-basic.md#i18nsource). Rspress provides the [`useI18n`](https://rspress.rs/ui/hooks/use-i18n.md) hook to get the internationalized text, the usage is as follows: ```tsx import { useI18n } from '@rspress/core/runtime'; const MyComponent = () => { const t = useI18n(); return
{t('gettingStarted')}
; }; ``` For better type hinting, you can configure `paths` in tsconfig.json: ```json { "compilerOptions": { "paths": { "i18n": ["./i18n.json"] } } } ``` Then use it like this in the component: ```tsx import { useI18n } from '@rspress/core/runtime'; const MyComponent = () => { const t = useI18n(); return
{t('gettingStarted')}
; }; ``` This way you get type hints for all text keys defined in `i18n.json`. --- url: https://rspress.rs/ui/hooks/use-lang.md --- > 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. # useLang `useLang` returns the current locale code so you can render language-specific content or route users accordingly. - **Type:** `() => string` The hook reads the active language from the runtime context and stays in sync when users switch locales. ```tsx preview import { useLang } from '@rspress/core/runtime'; export default function Comp() { const lang = useLang(); return Current language: {lang}; } ``` --- url: https://rspress.rs/ui/hooks/use-page-data.md --- > 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. # ~~usePageData~~ `usePageData` exposes the metadata of the current page so you can render it inside custom components or utilities. - **Type:** `() => PageData` The returned `PageData` object includes information such as the page title, route path, frontmatter, and site-wide data. This hook is available on both the server and client, making it suitable for SSR and SSG-safe rendering. > Capabilities have been split into [`usePage`](https://rspress.rs/ui/hooks/use-page.md), [`usePages`](https://rspress.rs/ui/hooks/use-pages.md), and [`useSite`](https://rspress.rs/ui/hooks/use-site.md); prefer these dedicated hooks as needed. ```tsx import { usePageData } from '@rspress/core/runtime'; export default function PageTitle() { const { page } = usePageData(); return

{page.title}

; } ``` > Related: you can pair this hook with [`useLang`](https://rspress.rs/ui/hooks/use-lang.md) or [`useVersion`](https://rspress.rs/ui/hooks/use-version.md) to tailor content by locale or documentation version. --- url: https://rspress.rs/ui/hooks/use-page.md --- > 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. # usePage `usePage` provides metadata extracted from the current Markdown or MDX page, and is a core hook of Rspress. - **Type:** `() => { page: PageDataLegacy['page'] }` The `page` object contains parsed frontmatter and runtime details such as `title`, `toc`, `lang`, `version`, `routePath`, `pagePath`, `description`, `pageType`, `lastUpdatedTime`, etc., making it easy to build contextual UI based on the current document. Here is an example of getting the current page's title and description: ```tsx preview import { usePage } from '@rspress/core/runtime'; export default function () { const { page } = usePage(); return (

Current page title: {page.title}

Current page description: {page.description}

); } ``` > When you need to get both page metadata and global site configuration, use together with [`useSite`](https://rspress.rs/ui/hooks/use-site.md). --- url: https://rspress.rs/ui/hooks/use-pages.md --- > 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. # usePages `usePages` returns metadata for all pages in the site and is handy for building custom [overview pages](https://rspress.rs/guide/advanced/overview-page.md) such as a blog index. - **Type:** `() => { pages: PageData['pages'] }` Below is a real-world example showing how to retrieve blog posts located at `/blog/*` in the current language from the `/blog/index` page, sorted in descending order by the `date` field in Frontmatter: ```tsx import { useLang, usePages } from '@rspress/core/runtime'; const useBlogPages = () => { const { pages } = usePages(); const lang = useLang(); const defaultDate = new Date('1970-01-01'); const getDate = (page: (typeof pages)[number]) => page.frontmatter?.date ? new Date(page.frontmatter.date as string) : defaultDate; const blogPages = pages .filter(page => page.lang === lang) .filter( page => page.routePath.includes('/blog/') && !page.routePath.endsWith('/blog/'), ) .sort((a, b) => { return getDate(b).getTime() - getDate(a).getTime(); }); return blogPages; }; ``` > `usePages` does not support HMR; restart the dev server after adding or removing documents to update the list. --- url: https://rspress.rs/ui/hooks/use-site.md --- > 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. # useSite `useSite` returns the serialized site configuration from `rspress.config.ts`. - **Type:** `() => { site: SiteData }` Here is an example of getting the [title](https://rspress.rs/api/config/config-basic.md#title) configuration from `rspress.config.ts`: ```tsx preview import { useSite } from '@rspress/core/runtime'; export default function SiteTitle() { const { site } = useSite(); return {site.title}; } ``` > Can be used together with [`usePage`](https://rspress.rs/ui/hooks/use-page.md) to get both global site configuration and current page metadata. --- url: https://rspress.rs/ui/hooks/use-version.md --- > 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. # useVersion `useVersion` provides the current documentation version when multi-version docs are enabled. - **Type:** `() => string` Use it to display the current version in UI or to execute branch logic for different versions. ```tsx import { useVersion } from '@rspress/core/runtime'; export default function VersionTag() { const version = useVersion(); return
Current documentation version: {version}
; } ``` --- url: https://rspress.rs/api/index.md --- > 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. # API Overview ## Config ### [Basic config](/api/config/config-basic.md) - [root](/api/config/config-basic.md#root) - [base](/api/config/config-basic.md#base) - [siteOrigin](/api/config/config-basic.md#siteorigin) - [title](/api/config/config-basic.md#title) - [description](/api/config/config-basic.md#description) - [icon](/api/config/config-basic.md#icon) - [lang](/api/config/config-basic.md#lang) - [i18nSourcePath](/api/config/config-basic.md#i18nsourcepath) - [i18nSource](/api/config/config-basic.md#i18nsource) - [logo](/api/config/config-basic.md#logo-1) - [logoHref](/api/config/config-basic.md#logohref) - [logoText](/api/config/config-basic.md#logotext) - [outDir](/api/config/config-basic.md#outdir) - [themeDir](/api/config/config-basic.md#themedir) - [locales](/api/config/config-basic.md#locales) - [head](/api/config/config-basic.md#head) - [globalStyles](/api/config/config-basic.md#globalstyles) - [llms](/api/config/config-basic.md#llms) - [mediumZoom](/api/config/config-basic.md#mediumzoom) - [search](/api/config/config-basic.md#search) - [globalUIComponents](/api/config/config-basic.md#globaluicomponents) - [multiVersion](/api/config/config-basic.md#multiversion) - [route](/api/config/config-basic.md#route) - [ssg](/api/config/config-basic.md#ssg) - [replaceRules](/api/config/config-basic.md#replacerules) - [languageParity](/api/config/config-basic.md#languageparity) ### [Theme config](/api/config/config-theme.md) - [nav](/api/config/config-theme.md#nav) - [sidebar](/api/config/config-theme.md#sidebar) - [footer](/api/config/config-theme.md#footer) - [lastUpdated](/api/config/config-theme.md#lastupdated) - [socialLinks](/api/config/config-theme.md#sociallinks) - [nextPageText](/api/config/config-theme.md#nextpagetext) - [locales](/api/config/config-theme.md#locales) - [darkMode](/api/config/config-theme.md#darkmode) - [editLink](/api/config/config-theme.md#editlink) - [enableContentAnimation](/api/config/config-theme.md#enablecontentanimation) - [enableAppearanceAnimation](/api/config/config-theme.md#enableappearanceanimation) - [search](/api/config/config-theme.md#search) - [enableScrollToTop](/api/config/config-theme.md#enablescrolltotop) - [~~localeRedirect~~](/api/config/config-theme.md#localeredirect) - [fallbackHeadingTitle](/api/config/config-theme.md#fallbackheadingtitle) - [llmsUI](/api/config/config-theme.md#llmsui) ### [Frontmatter config](/api/config/config-frontmatter.md) - [title](/api/config/config-frontmatter.md#title) - [description](/api/config/config-frontmatter.md#description) - [pageType](/api/config/config-frontmatter.md#pagetype) - [titleSuffix](/api/config/config-frontmatter.md#titlesuffix) - [sidebar](/api/config/config-frontmatter.md#sidebar) - [outline](/api/config/config-frontmatter.md#outline) - [footer](/api/config/config-frontmatter.md#footer) - [navbar](/api/config/config-frontmatter.md#navbar) - [icon](/api/config/config-frontmatter.md#icon) - [context](/api/config/config-frontmatter.md#context) - [search](/api/config/config-frontmatter.md#search) - [head](/api/config/config-frontmatter.md#head) - [Overview page related](/api/config/config-frontmatter.md#overview-page-related) - [Homepage related](/api/config/config-frontmatter.md#homepage-related) ### [Build config](/api/config/config-build.md) - [builderConfig](/api/config/config-build.md#builderconfig) - [builderConfig.plugins](/api/config/config-build.md#builderconfigplugins) - [markdown](/api/config/config-build.md#markdown) ## Commands ### [Commands](/api/commands.md) - [rspress dev](/api/commands.md#rspress-dev) - [rspress build](/api/commands.md#rspress-build) - [rspress preview](/api/commands.md#rspress-preview) - [rspress eject](/api/commands.md#rspress-eject) --- url: https://rspress.rs/api/config/config-basic.md --- > 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. # Basic config ## root - **Type**: `string` - **Default**: `docs` Specifies the docs root directory. For example: ```ts title="rspress.config.ts" twoslash import { defineConfig } from '@rspress/core'; export default defineConfig({ 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: ```bash 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/"`: ```ts title="rspress.config.ts" twoslash import { defineConfig } from '@rspress/core'; export default defineConfig({ base: '/bar/', }); ``` ## siteOrigin [Added in v2.0.17](https://github.com/web-infra-dev/rspress/releases/tag/v2.0.17) - **Type**: `string` - **Default**: `""` The optional deployment origin of the site, for example `https://foo.github.io`. Rspress uses this value together with [`base`](#base) when generated files need absolute URLs, such as `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/"`: ```ts title="rspress.config.ts" twoslash import { defineConfig } from '@rspress/core'; export default defineConfig({ siteOrigin: 'https://foo.github.io', base: '/bar/', }); ``` ## title - **Type**: `string` - **Default**: `"Rspress"` Site title. Rspress uses this as the HTML page title. For example: ```ts title="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: ```ts title="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: ```ts title="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 [Internationalization](https://rspress.rs/guide/basic/i18n.md) for more details. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ lang: 'en', locales: [ { lang: 'en', // ... }, { lang: 'zh', // ... }, ], }); ``` ## 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: ```ts title="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> | ((value: Record>) => Record> | Promise>>)` - **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](https://rspress.rs/ui/hooks/use-i18n.md). :::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: ```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. Here is an example of modifying Rspress's built-in i18n text: ```ts title="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: ```ts 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: ```ts file="../../../../../packages/core/src/node/runtimeModule/DEFAULT_I18N_TEXT.ts" 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: 'Вернуться на главную', }, 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; // cspell:enable ``` ## logo \{#logo-1} - **Type**: `string | { dark: string; light: string }` - **Default**: `""` Site logo. Rspress uses this path for the logo in the upper-left corner of the navbar. For example: ```ts title="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: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ logo: { dark: '/logo-dark.png', light: '/logo-light.png', }, }); ``` ## 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: ```ts title="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: ```ts title="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: ```ts title="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: ```ts title="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](https://rspress.rs/guide/basic/custom-theme.md). ## locales - **Type**: `Locale[]` ```ts export interface Locale { lang: string; label: string; title?: string; description?: string; } ``` Site i18n configuration. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ locales: [ { lang: 'en-US', label: 'English', title: 'My Site', description: 'My site description', }, { lang: 'zh-CN', label: '简体中文', title: '站点标题', description: '站点描述', }, ], }); ``` ## head - **Type**: `string` | `[string, Record]` | `(route) => string | [string, Record] | undefined` - Can be appended per page via [frontmatter](https://rspress.rs/api/config/config-frontmatter.md#head) Adds extra elements to the page's HTML `` in production builds. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ // ... other user config head: [ '', // or ['meta', { name: 'author', content: 'John Doe' }], // [htmlTag, { attrName: attrValue, attrName2: attrValue2 }] // or route => { if (route.routePath.startsWith('/jane/')) return ""; 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: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import path from 'path'; export default defineConfig({ globalStyles: path.join(__dirname, 'styles/global.css'), }); ``` ```css title="styles/global.css" :root { --rp-c-brand: #f00; } ``` ## llms - **Type**: ```ts boolean | { llmsTxt?: (context: LlmsTxtContext) => string | Promise; remarkSplitMdxOptions?: RemarkSplitMdxOptions; } ``` - **Default**: `false` Whether to enable [SSG-MD](https://rspress.rs/guide/basic/ssg-md.md) to generate `llms.txt`, `llms-full.txt`, and Markdown files for each page, making your documentation easier for large language models to understand. Use `llmsTxt` to compose the complete `llms.txt` content from site metadata and page sections. See [Customize llms.txt](https://rspress.rs/guide/basic/ssg-md.md#customize-llmstxt) for details. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ llms: true, }); ``` :::warning `llms` is an experimental feature. If SSG-MD cannot be enabled due to SSR incompatibility, use [@rspress/plugin-llms](https://rspress.rs/plugin/official-plugins/llms.md) as a fallback. ::: For detailed usage, configuration options, and implementation principles, see [llms.txt (SSG-MD)](https://rspress.rs/guide/basic/ssg-md.md). ## 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](https://github.com/francoischalifour/medium-zoom) library. Example usage: ```ts title="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', }, }); ``` ## search - **Type**: ```ts type SearchOptions = { searchHooks?: string; versioned?: boolean; codeBlocks?: boolean; }; ``` :::tip To exclude an individual page from the search index, set [`search: false`](https://rspress.rs/api/config/config-frontmatter.md#search) in its frontmatter. ::: ### searchHooks - **Type**: `string` - **Default**: `undefined` Use `searchHooks` to add runtime hooks for search. For example: ```ts title="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](https://rspress.rs/guide/advanced/custom-search.md). ### versioned - **Type**: `boolean` - **Default**: `true` When using [`multiVersion`](https://rspress.rs/guide/basic/multi-version.md), 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. ```ts title="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. ```ts title="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: ```ts title="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: ```ts title="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: ```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
This is a global layout component
; } ``` 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. ## multiVersion - **Type**: `{ default: string; versions: string[] }` Enable multi-version support with `multiVersion`. For example: ```ts title="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: ```js 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](https://rspress.rs/plugin/system/plugin-api.md#addpages) in a custom Rspress plugin. ::: ### route.exclude - **Type**: `string[]` - **Default**: `[]` Exclude some files from the route. For example: ```js 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](https://rspress.rs/guide/use-mdx/components.md) that makes it easier to keep components in the [docs directory](https://rspress.rs/api/config/config-basic.md#root). 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-`: ```js title="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: ```js import { defineConfig } from '@rspress/core'; export default defineConfig({ route: { extensions: ['.md', '.mdx'], }, }); ``` ### route.cleanUrls - **Type**: `Boolean` - **Default**: `false` Generates URLs without file extensions when `cleanUrls` is `true`. :::warning 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. ::: ```js import { defineConfig } from '@rspress/core'; export default defineConfig({ route: { cleanUrls: true, }, }); ``` ### 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`](#routecleanurls). `route.cleanUrls` controls the preferred URL format used by generated links, while `route.cleanUrlsRedirect` only normalizes the browser address bar. :::warning 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 URL | Matched route | Browser URL update | | -------------------- | ------------- | ---------------------------- | | `/file` | `/file` | No update | | `/file.html` | `/file` | `replaceState` to `/file` | | `/file/` | `/file` | `replaceState` to `/file` | | `/file/index` | `/file` | `replaceState` to `/file` | | `/file/index.html` | `/file` | `replaceState` 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 URL | Matched route | Browser URL update | | -------------------- | ------------- | -------------------------------------- | | `/file` | `/file` | `replaceState` to `/file.html` | | `/file.html` | `/file` | No update | | `/file/` | `/file` | `replaceState` to `/file.html` | | `/file/index` | `/file` | `replaceState` to `/file.html` | | `/file/index.html` | `/file` | `replaceState` 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](https://developers.cloudflare.com/workers/static-assets/routing/advanced/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: ```js import { defineConfig } from '@rspress/core'; export default defineConfig({ route: { cleanUrlsRedirect: false, }, }); ``` ### route.localeRedirect [Added in v2.0.19](https://github.com/web-infra-dev/rspress/releases/tag/v2.0.19) - **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. :::tip 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. ::: ```js title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ route: { localeRedirect: 'never', }, }); ``` ### route.useTransitions [Added in v2.0.17](https://github.com/web-infra-dev/rspress/releases/tag/v2.0.17) - **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. ```js title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ route: { useTransitions: false, }, }); ``` ### route.prefetchLink [Added in v2.0.17](https://github.com/web-infra-dev/rspress/releases/tag/v2.0.17) - **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`](https://rsbuild.rs/config/dev/lazy-compilation), 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: ```js title="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 static site generation is enabled. Rspress enables it by default and generates both CSR and SSG outputs. If your documentation site only needs CSR output, set `ssg` to `false`. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ ssg: false, }); ``` :::tip SSG requires source code to be SSR-compatible. If the code is not compatible with SSR, the build will fail. You can try: 1. Fix the code to make it SSR-compatible. 2. Set `ssg: false`, but the SSG feature will be lost. ::: ### 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](https://github.com/tinylibs/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. ## 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. ```ts title="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.enable - **Type**: `boolean` - **Default**: `false` Whether to enable language parity checks. ```ts title="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: ```ts title="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. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ languageParity: { exclude: ['excluded-directory', 'articles/secret.md'], }, }); ``` --- url: https://rspress.rs/api/config/config-theme.md --- > 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. # Theme config Theme configuration is defined under `themeConfig`. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { // ... }, }); ``` ## nav - **Type**: `Array` - **Default**: `[]` The `nav` configuration is an array of `NavItem` with the following types: ```ts interface NavItem { // Navbar text text: string; // Navbar link link: '/'; // Whether it is a download link download?: boolean; // Activation rules for navbar links activeMatch: '^/$|^/'; // Icon displayed before the navbar text icon?: string; // Tag displayed after the navbar text tag?: string; } ``` `activeMatch` matches the current route. When the route matches the `activeMatch` rule, the nav item is highlighted. By default, `activeMatch` uses the nav item's `link`. For local icons, place the image in the `public` directory and reference it with an absolute path such as `/icon.png`. Inline SVG strings, emoji, external URLs, and data URLs are also supported. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { nav: [ { text: 'Home', link: '/', icon: '/icon.png', }, { text: 'Guide', link: '/guide/', }, ], }, }); ``` You can also configure multi-level menus in the `nav` array with the following type: ```ts interface NavGroup { text: string; // submenu items: NavItem[]; // Icon displayed before the navbar text icon?: string; // Tag displayed after the navbar text tag?: string; } ``` For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { nav: [ { text: 'Home', link: '/', }, { text: 'Guide', items: [ { text: 'Getting Started', link: '/guide/getting-started', }, { text: 'Advanced', link: '/guide/advanced', }, // Also supports nested groups { text: 'Group', items: [ { text: 'Personal', link: 'http://example.com/', }, { text: 'Company', link: 'http://example.com/', }, ], }, ], }, ], }, }); ``` ## sidebar - **Type**: `Object` Site sidebar configuration. It is an object with the following type: ```ts // The key is the path of SidebarGroup // value is an array of SidebarGroup type Sidebar = Record; interface SidebarGroup { text: string; link?: string; items: SidebarItem[]; // Whether the group can be collapsed collapsible?: boolean; // Whether to be collapsed by default collapsed?: boolean; // Icon displayed before the sidebar text icon?: string; // Tag displayed after the sidebar text tag?: string; } type SidebarItem = { // sidebar text text: string; // sidebar link link: string; // Icon displayed before the sidebar text icon?: string; // Tag displayed after the sidebar text tag?: string; }; ``` For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { sidebar: { '/guide/': [ { text: 'Getting Started', icon: '/icon.png', items: [ { text: 'Introduction', link: '/guide/getting-started/introduction', icon: '...', tag: 'new', }, { text: 'Installation', link: '/guide/getting-started/installation', }, ], }, { text: 'Advanced', items: [ { text: 'Customization', link: '/guide/advanced/customization', }, { text: 'Markdown', link: '/guide/advanced/markdown', }, ], }, ], }, }, }); ``` ## footer - **Type**: `Object` - **Default**: `{}` Homepage footer configuration. The `footer` config is a `Footer` object: ```ts export interface Footer { message?: string; } ``` `message` is a string that can contain HTML content. This string will be inserted into the footer using `dangerouslySetInnerHTML`, allowing you to pass in HTML template tags to design your footer. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { footer: { message: '

This is a footer with a link and bold text

', }, }, }); ``` ## lastUpdated - **Type**: `boolean | { author?: boolean | ((info: { name: string; email: string; filePath: string }) => string) }` - **Default**: `false` Controls whether each doc page shows its last updated time. Rspress reads this value from the file's latest Git commit. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { lastUpdated: true, }, }); ``` When deploying in CI, make sure the Git history is available. For example, use `fetch-depth: 0` with `actions/checkout` on GitHub Actions. Set `author` to display the last commit author as well. Pass a function to customize the rendered author text. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { lastUpdated: { author: ({ name, email }) => `${name} <${email}>`, }, }, }); ``` ## socialLinks - **Type**: `Array` - **Default**: `[]` Add related links, such as GitHub or X links. Related links support five modes: `link`, `text`, `img`, `dom`, and `github-stars`. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { socialLinks: [ { icon: 'github', mode: 'link', content: 'https://github.com/sanyuan0704/island.js', }, { icon: 'wechat', mode: 'text', content: 'wechat: foo', }, { icon: 'qq', mode: 'img', content: '/qrcode.png', }, { icon: 'github', mode: 'dom', content: '', }, { icon: 'github', mode: 'github-stars', content: 'https://github.com/web-infra-dev/rspress', }, ], }, }); ``` - In `link` mode, clicking the icon opens the link. - In `text` mode, hovering over the icon displays a tooltip with the configured text. - In `img` mode, hovering over the icon displays a tooltip with the configured image. The image must be placed in the `public` directory. - In `dom` mode, pass the HTML string to render directly to `content`. Wrap it in quotes. - When in `github-stars` mode, `content` should be the GitHub repository URL. The repository's star count is fetched from the GitHub REST API and rendered next to the icon. The result is cached in `localStorage` for one hour to avoid hitting the API rate limit. If the request fails (offline, rate-limited, private repo), the icon falls back to a plain link. Related links support the following icons via the `icon` field: ```ts export type SocialLinkIcon = | 'lark' | 'discord' | 'facebook' | 'github' | 'instagram' | 'linkedin' | 'slack' | 'x' | 'youtube' | 'wechat' | 'qq' | 'juejin' | 'zhihu' | 'bilibili' | 'weibo' | 'gitlab' | 'X' | 'bluesky' | 'npm' | { svg: string }; ``` To use a custom icon, pass an object with an `svg` field. The `svg` value is the custom icon content: ```js import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { socialLinks: [ { icon: { svg: 'foo', }, mode: 'link', content: 'https://github.com/', }, ], }, }); ``` ## nextPageText - **Type**: `string` - **Default**: `Next Page` Text for the next page link. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { nextPageText: 'Next Page', }, }); ``` ## locales - **Type**: `Array` - **Default**: `undefined` I18n configuration. This is an array of `LocaleConfig` objects: ```ts export interface LocaleConfig { /** * General locale config for site, which will have a higher priority than `locales` */ // language name lang?: string; // HTML title, takes precedence over `themeConfig.title title?: string; // HTML description, takes precedence over `themeConfig.description` description?: string; // Display text for the corresponding language label: string; } ``` `LocaleConfig` contains many of the same options as the theme config, but locale-specific values have higher priority. ## darkMode - **Type**: `boolean | 'dark' | 'light' | 'auto' | 'force-light' | 'force-dark' | 'force-auto'` - **Default**: `true` When dark mode is active, Rspress adds the `dark` class to the `` element. You can use the `html.dark` selector to customize dark mode styles: ```css html.dark .custom-content { color: white; } ``` Configure the Dark/Light mode behavior: - `true`: same as `'auto'`. - `false`: same as `'force-light'`. - `'light'`: show the toggle button and use light mode by default when the user has no saved preference. - `'dark'`: show the toggle button and use dark mode by default when the user has no saved preference. - `'auto'`: show the toggle button and follow the user's system preference by default when the user has no saved preference. - `'force-light'`: always use light mode and hide the toggle button. - `'force-dark'`: always use dark mode and hide the toggle button. - `'force-auto'`: always follow the user's system preference and hide the toggle button. For example, always use dark mode and hide the toggle button: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { darkMode: 'force-dark', }, }); ``` ## editLink - **Type**: ```ts interface EditLink { /** * Custom repository url for edit link. */ docRepoBaseUrl: string; } ``` - **Default**: `undefined` Display a link to edit the page on Git management services such as GitHub, or GitLab. The link appears in both the doc footer and the right-side outline panel. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { editLink: { docRepoBaseUrl: 'https://github.com/web-infra-dev/rspress/tree/main/website/docs', }, }, }); ``` ## enableContentAnimation - **Type**: `boolean` - **Default**: `false` Controls whether page transitions are animated. This is implemented with the [View Transition API](https://developer.mozilla.org/docs/Web/API/View_Transitions_API). For example: > The animation is not configurable for now. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { enableContentAnimation: true, }, }); ``` ## enableAppearanceAnimation - **Type**: `boolean` - **Default**: `false` Controls whether switching between light and dark mode is animated. This is implemented with the [View Transition API](https://developer.mozilla.org/docs/Web/API/View_Transitions_API). For example: > The animation is not configurable for now. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { enableAppearanceAnimation: true, }, }); ``` ## search - **Type**: `boolean` - **Default**: `true` Whether to display the search box. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { search: false, }, }); ``` ## enableScrollToTop - **Type**: `boolean` - **Default**: `true` Enables the scroll-to-top button in docs pages. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { enableScrollToTop: true, }, }); ``` ## ~~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`. :::warning Configuration moved This option has moved to [`route.localeRedirect`](https://rspress.rs/api/config/config-basic.md#routelocaleredirect). `themeConfig.localeRedirect` remains supported for backward compatibility, but is deprecated. Migrate the option to `route`; when both options are set, `route.localeRedirect` takes precedence. ::: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ route: { localeRedirect: 'never', }, }); ``` ## fallbackHeadingTitle - **Type**: `boolean` - **Default**: `true` Controls whether [`frontmatter.title`](https://rspress.rs/api/config/config-frontmatter.md#title) is used as a fallback when a document has no H1 heading. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ themeConfig: { fallbackHeadingTitle: false, }, }); ``` ```mdx --- title: Document Title --- ## Content ``` ## llmsUI - **Type**: ```ts type LlmsUI = | boolean | { injectLlmsHint?: boolean; viewOptions?: false | Array<'markdownLink' | 'chatgpt' | 'claude'>; placement?: 'title' | 'outline'; }; ``` - **Default**: `false` (automatically set to `true` when `llms: true` is configured) Configuration for the llms UI components. When enabled, `LlmsCopyButton` and `LlmsViewOptions` are automatically added below all H1 headings by default, or as rows in the outline panel. This is useful when using the [llms](https://rspress.rs/guide/basic/ssg-md.md) feature to generate llms.txt files, because users can copy or open Markdown content in AI tools. :::warning SSG-MD only runs during builds, so copying Markdown content does not work in `dev` mode. Run `rspress build` first, then debug with `rspress preview`. See [Differences between dev and build](https://rspress.rs/guide/basic/ssg.md#differences-between-dev-and-build) for details. ::: For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ llms: true, themeConfig: { llmsUI: { injectLlmsHint: true, viewOptions: ['markdownLink', 'chatgpt', 'claude'], placement: 'outline', }, }, }); ``` ### injectLlmsHint [Added in v2.0.18](https://github.com/web-infra-dev/rspress/releases/tag/v2.0.18) - **Type**: `boolean` - **Default**: `true` This option controls whether an LLM directive hint is injected into generated pages. The same `LlmsHint` component has two output forms: - In SSG HTML output, it renders a visually hidden plain-text DOM element near the top of the page. It does not use `display: none`, the `hidden` attribute, `aria-hidden`, or nested links, so agent-side HTML-to-Markdown conversion can preserve the directive as text. - In SSG-MD Markdown output, it renders a blockquote string near the top of the Markdown page. Assuming [`siteOrigin`](https://rspress.rs/api/config/config-basic.md#siteorigin) is `https://example.com`, the following HTML directive is injected into the `/guide/` page: ```html
For AI agents: the complete documentation index is available at https://example.com/llms.txt, the full documentation bundle is available at https://example.com/llms-full.txt, and this page is available as Markdown at https://example.com/guide/index.md.
``` The SSG-MD Markdown output for the same page starts with: ```md > For AI agents: the complete documentation index is available at https://example.com/llms.txt, the full documentation bundle is available at https://example.com/llms-full.txt. ``` The URLs automatically include the configured `siteOrigin`, [`base`](https://rspress.rs/api/config/config-basic.md#base), locale, and version prefixes. Without `siteOrigin`, the URLs remain base-aware paths. Set `injectLlmsHint` to `false` to disable this behavior: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ llms: true, themeConfig: { llmsUI: { injectLlmsHint: false, }, }, }); ``` ### viewOptions - **Type**: `false | Array<'markdownLink' | 'chatgpt' | 'claude'>` - **Default**: `['markdownLink', 'chatgpt', 'claude']` Options for the LlmsViewOptions dropdown menu. Built-in options include: - `'markdownLink'`: Copy markdown file link - `'chatgpt'`: Open in ChatGPT - `'claude'`: Open in Claude Set `viewOptions` to `false` or `[]` to hide the view options UI. ### placement - **Type**: `'title' | 'outline'` - **Default**: `'title'` Controls where the LLMS UI components are displayed. - `'title'`: Show as buttons below the H1 title (default behavior) - `'outline'`: Show as separate rows in the right-side outline panel ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ llms: true, themeConfig: { llmsUI: { placement: 'outline', }, }, }); ``` --- url: https://rspress.rs/api/config/config-frontmatter.md --- > 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. # Frontmatter config This page explains how to configure page-level properties with frontmatter, including title, description, page type, and navbar visibility. See [Frontmatter](https://rspress.rs/guide/use-mdx/frontmatter.md) for the frontmatter syntax, and [useFrontmatter](https://rspress.rs/ui/hooks/use-frontmatter.md) for accessing frontmatter in code. ## title - **Type**: `string` The page title. By default, Rspress uses the page's H1 heading as the HTML document title. To use a different title, set it in frontmatter: ```mdx --- title: My Homepage --- This is my **homepage content**. ``` It is equivalent to: ```mdx # My homepage This is my **homepage content**. ``` ## description - **Type**: `string` A custom description for the page. Rspress uses it to generate a `` tag on the page for SEO optimization. By default, Rspress extracts the first contentful paragraph below the `h1` heading as the description (see [`markdown.extractDescription`](https://rspress.rs/api/config/config-build.md#markdownextractdescription)). If the extracted result does not meet your needs, you can use this field to override it. For more details, see [Custom Head - How description is determined](https://rspress.rs/guide/advanced/custom-head.md#how-description-is-determined). ```yaml --- description: This is my homepage --- ``` ## pageType - **Type**: `'home' | 'doc' | 'doc-wide' | 'custom' | 'blank' | '404'` - **Default**: `'doc'` The page type. The default is `doc`. To use a different page type, set the `pageType` frontmatter field: ```yaml --- pageType: home --- ``` The meaning of each `pageType` config is as follows: - `home`: **Homepage**, including the top navbar and homepage layout content. - `doc`: **Doc page**, including the top navbar, left sidebar, body content, and right-side outline. - `doc-wide`: **Wide doc page**, where the main content can occupy a wider area when `outline: false` and `sidebar: false` are used together. - `custom`: **Custom page**, including the top navbar and custom content. - `blank`: Also a **custom page**, but without the top navbar. - `404`: **Not found page**. ## titleSuffix - **Type**: `string` Set the suffix of the page title. When `titleSuffix` is not set, the site's [title](https://rspress.rs/api/config/config-basic.md#title) is used as the suffix by default. ```yaml --- titleSuffix: 'Rsbuild-based Static Site Generator' --- ``` The default separator between the title and suffix is `-`. You can also use `|`: ```yaml --- titleSuffix: '| Rsbuild-based Static Site Generator' --- ``` ## sidebar - **Type**: `boolean | 'placeholder'` - **Default**: `true` Controls whether the left sidebar is shown. By default, `doc` pages display the left sidebar. To hide it, use the following frontmatter: ```yaml --- sidebar: false --- ``` :::tip `sidebar: false` hides the sidebar and keeps a `12vw` placeholder on the left to keep the content visually centered on large screens. If you want the main content to occupy a wider screen space, you can use [`pageType: doc-wide`](#pagetype) with `sidebar: false`: ```yaml --- pageType: doc-wide sidebar: false --- ``` The main content area will then expand into the space normally used by the sidebar. If you want to keep the blank space for the left sidebar, use `sidebar: 'placeholder'`: ```yaml --- sidebar: 'placeholder' --- ``` ::: ## outline Controls whether the right-side outline is shown. By default, `doc` pages display the right-side outline. To hide it, use: ```yaml --- outline: false --- ``` :::tip `outline: false` only hides the outline column, but the space originally occupied by the outline column is still reserved. If you want the main content to occupy a wider screen space, you can use [`pageType: doc-wide`](#pagetype) with `outline: false`: ```yaml --- pageType: doc-wide outline: false --- ``` The main content area will then expand into the space normally used by the outline. ::: ## footer Controls whether footer components, such as previous/next page links, are shown at the bottom of the page. By default, `doc` pages display the footer. To hide it, use: ```yaml --- footer: false --- ``` ## navbar Controls whether the top navbar is shown. By default, all pages display the top navbar. To hide it, use: ```yaml --- navbar: false --- ``` ## icon [Added in v2.0.19](https://github.com/web-infra-dev/rspress/releases/tag/v2.0.19) - **Type**: `string` Sets the icon displayed before the page title in an automatically generated sidebar. For local images, place the asset in the `public` directory and reference it with an absolute path: ```yaml --- icon: /icon.png --- ``` Inline SVG strings, emoji, external URLs, and data URLs are also supported. If the same file item defines `icon` in both frontmatter and `_meta.json`, the frontmatter value takes precedence. See [Sidebar icons and tags](https://rspress.rs/guide/basic/auto-nav-sidebar.md#sidebar-icons-and-tags) for more examples. ## context - **Type**: `string` When configured, Rspress adds a `data-context` attribute with this value to the generated sidebar DOM node. ```yaml title="foo.mdx" --- context: 'context-foo' --- ``` ```yaml title="bar.mdx" --- context: 'context-bar' --- ``` The DOM structure of the final generated sidebar is abbreviated as follows: ```html
``` ## search - **Type**: `boolean` - **Default**: `true` Whether to include the current page in the built-in search index. By default every `doc` page is indexed for full-text search. If you want to exclude a specific page from the search results, set `search` to `false`: ```yaml --- search: false --- ``` This only affects the built-in search. Pages with `pageType: home` are always excluded from the search index regardless of this field. ## head - **Type**: `[string, Record][]` Specify extra head tags to be injected for the current page. They will be appended after the head tags injected by Rspress globally. For example, you can use these headers to specify custom meta tags for [Open Graph](https://ogp.me/). ```yaml --- head: - - meta - property: og:url content: https://example.com/foo/ - - meta - property: og:image content: https://example.com/bar.jpg # - - [htmlTag] # - [attributeName]: [attributeValue] # [attributeName]: [attributeValue] --- ``` The generated head tags are as follows: ```html ``` ## Overview page related The following configurations are related to the [Overview Page](https://rspress.rs/guide/advanced/overview-page.md) feature. ### overview - **Type**: `boolean` - **Default**: `false` Enables the overview page feature for the current doc page. When set to `true`, the current page becomes an [Overview Page](https://rspress.rs/guide/advanced/overview-page.md). For example: ```yaml --- overview: true --- ``` ### overviewHeaders - **Type**: `number[]` - **Default**: `[2]` Heading levels to show on the overview page. By default, H2 headings are shown. To display other heading levels, set the `overviewHeaders` frontmatter field: ```yaml --- overview: true overviewHeaders: [] --- ``` Or ```yaml --- overviewHeaders: [2, 3] --- ``` ## Homepage related The following options are related to the [homepage](https://rspress.rs/guide/basic/home-page.md) feature. ### hero - **Type**: `Object` Hero configuration for the `home` page. It has the following type: ```ts interface Hero { name: string; text: string; tagline: string; image?: { src: string | { dark: string; light: string }; alt: string; /** * `srcset` and `sizes` are `` attributes. See https://mdn.io/srcset for usage. * When the value is an array, Rspress joins array members with commas. **/ srcset?: string | string[]; sizes?: string | string[]; }; actions: { text: string; link: string; theme: 'brand' | 'alt'; }[]; } ``` For example, use the following frontmatter to specify a page's hero configuration: ```yaml --- pageType: home hero: name: Rspress text: A Documentation Solution tagline: A modern documentation development technology stack actions: - theme: brand text: Introduction link: /en/guide/introduction - theme: alt text: Quick Start link: /en/guide/getting-started --- ``` When setting `hero.text`, you can use the `|` symbol in YAML to manually control line breaks: ```yaml --- pageType: home hero: name: Rspress text: | A Documentation Solution ``` You can also use `HTML` in the page's hero configuration: ```yaml --- pageType: home hero: name: Rspress text: A Documentation Solution tagline: A modern documentation development technology stack actions: - theme: brand text: Introduction link: /en/guide/introduction - theme: alt text: Quick Start link: /en/guide/getting-started --- ``` ### features - **Type**: `Array` - **Default**: `[]` Feature configuration for the `home` page. It has the following type: ```ts interface Feature { title: string; details: string; icon: string; // The length of the card grid, currently only supports [3, 4, 6] span?: number; // The link of the feature card, optional. link?: string; } export type Features = Feature[]; ``` For example, use the following frontmatter to specify the features for the `home` page: ```yaml --- pageType: home features: - title: 'MDX: Write content with flexible syntax' details: MDX is a powerful way to write content. You can use React components in Markdown. icon: 📦 - title: 'Feature Rich: One-stop solution' details: Out-of-the-box support for full-text search, i18n, and other common features. icon: 🎨 - title: 'Highly Extensible: Multiple customization paths' details: Use extension APIs to customize the theme UI and build behavior. icon: 🚀 --- ``` --- url: https://rspress.rs/api/config/config-build.md --- > 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. # Build config ## builderConfig - **Type**: `RsbuildConfig` Customizes the Rsbuild configuration. For details, see [Rsbuild - Config](https://rsbuild.rs/config/). - Example: Use [resolve.alias](https://rsbuild.rs/config/resolve/alias) to configure path aliases: ```ts title="rspress.config.ts" export default defineConfig({ builderConfig: { resolve: { alias: { '@common': './src/common', }, }, }, }); ``` - Example: Use [tools.rspack](https://rsbuild.rs/config/tools/rspack) to modify the Rspack configuration, such as registering a webpack or Rspack plugin: ```ts title="rspress.config.ts" export default defineConfig({ builderConfig: { tools: { rspack: async config => { const { default: ESLintPlugin } = await import('eslint-webpack-plugin'); config.plugins?.push(new ESLintPlugin()); return config; }, }, }, }); ``` ::: warning To modify the output directory, use [outDir](https://rspress.rs/api/config/config-basic.md#outdir). ::: ## builderConfig.plugins - **Type**: `RsbuildPlugin[]` To register [Rsbuild plugins](https://rsbuild.rs/plugins/list/). You can leverage Rsbuild's extensive plugin ecosystem to enhance and extend your build capabilities. - Example: Support Vue SFCs with [@rsbuild/plugin-vue](https://rsbuild.rs/plugins/list/plugin-vue) ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import { pluginVue } from '@rsbuild/plugin-vue'; export default defineConfig({ builderConfig: { plugins: [pluginVue()], }, }); ``` - Example: Add Google Analytics with [rsbuild-plugin-google-analytics](https://github.com/rstackjs/rsbuild-plugin-google-analytics). ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import { pluginGoogleAnalytics } from 'rsbuild-plugin-google-analytics'; export default defineConfig({ builderConfig: { plugins: [ pluginGoogleAnalytics({ // replace this with your Google tag ID id: 'G-xxxxxxxxxx', }), ], }, }); ``` - Example: Add Open Graph meta tags with [rsbuild-plugin-open-graph](https://github.com/rstackjs/rsbuild-plugin-open-graph). ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import { pluginOpenGraph } from 'rsbuild-plugin-open-graph'; export default defineConfig({ builderConfig: { plugins: [ pluginOpenGraph({ title: 'My Website', type: 'website', // ...options }), ], }, }); ``` You can also override the built-in plugin [@rsbuild/plugin-react](https://rsbuild.rs/plugins/list/plugin-react) and customize the plugin options. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import { pluginReact } from '@rsbuild/plugin-react'; export default defineConfig({ builderConfig: { plugins: [ pluginReact({ // ...options }), ], }, }); ``` ### Default config To inspect the default Rspack or Rsbuild config, set `DEBUG=rsbuild` when running `rspress dev` or `rspress build`: ```bash DEBUG=rsbuild rspress dev ``` After the command runs, Rspress creates `rsbuild.config.js` in the `doc_build` directory. The file contains the complete `builderConfig`. > See [Rsbuild - Debug Mode](https://rsbuild.rs/guide/debug/debug-mode) for more information about debugging Rsbuild. ## markdown Configures MDX compilation. ### markdown.remarkPlugins - **Type**: `Array` - **Default**: `[]` Configures remark plugins. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { remarkPlugins: [ [ require('remark-autolink-headings'), { behavior: 'wrap', }, ], ], }, }); ``` ### markdown.rehypePlugins - **Type**: `Array` Configures rehype plugins. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { rehypePlugins: [ [ require('rehype-autolink-headings'), { behavior: 'wrap', }, ], ], }, }); ``` ### markdown.shiki - **Type**: `import('@shikijs/rehype').RehypeShikiOptions` - **Default**: ```ts const cssVariablesTheme = createCssVariablesTheme({ name: 'css-variables', variablePrefix: '--shiki-', variableDefaults: {}, fontStyle: true, }); const shikiOptions = { theme: cssVariablesTheme, defaultLanguage: 'txt', lazy: true, langs: ['tsx', 'ts', 'js'], addLanguageClass: true, }; ``` Configure Shiki-related options. For details, see [RehypeShikiOptions](https://github.com/shikijs/shiki/blob/main/packages/rehype/src/types.ts). ### markdown.link - **Type**: ```ts export type RemarkLinkOptions = { checkDeadLinks?: boolean | { excludes: string[] | ((url: string) => boolean) }; checkAnchors?: boolean | { excludes: string[] | ((url: string) => boolean) }; autoPrefix?: boolean; }; ``` - **Default**: `{ checkDeadLinks: true, checkAnchors: false, autoPrefix: true }` Configure link-related options. #### markdown.link.checkDeadLinks - **Type**: `boolean | { excludes: string[] | ((url: string) => boolean) }` - **Default**: `true` When enabled, Rspress checks document links against the conventional routes. If a link is not accessible, the build fails. If a link is reported incorrectly, ignore it with `excludes`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { link: { checkDeadLinks: { excludes: ['/guide/getting-started', '/llms.txt'], }, }, }, }); ``` #### markdown.link.checkAnchors - **Type**: `boolean | { excludes: string[] | ((url: string) => boolean) }` - **Default**: `false` :::info `checkAnchors` is currently disabled by default. It will be enabled by default in a future version. ::: After enabling this configuration, Rspress will check whether internal link anchors exist in the target Markdown or MDX page. It checks same-page anchors, relative links, and absolute links, but skips external URL anchors. If an anchor is reported incorrectly, ignore it with `excludes`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { link: { checkAnchors: { excludes: ['/guide/getting-started#custom-anchor'], }, }, }, }); ``` #### markdown.link.autoPrefix - **Type**: `boolean` - **Default**: `true` When enabled, Rspress automatically adds link prefixes based on the conventional routes for [i18n](https://rspress.rs/guide/basic/i18n.md) and [multi-version docs](https://rspress.rs/guide/basic/multi-version.md). If a user writes a link `[](/guide/getting-started)` in `docs/zh/guide/index.md`, Rspress will automatically convert it to `[](/zh/guide/getting-started)`. ### markdown.image - **Type**: ```ts export type RemarkImageOptions = { checkDeadImages?: boolean | { excludes: string[] | ((url: string) => boolean) }; }; ``` - **Default**: `{ checkDeadImages: true }` Configure image-related options. #### markdown.image.checkDeadImages - **Type**: `boolean | { excludes: string[] | ((url: string) => boolean) }` - **Default**: `true` When enabled, Rspress checks local images in documents. If an image references a file that does not exist, the build fails. For relative image paths (e.g., `./image.png`), the file is resolved relative to the current document. For absolute image paths (e.g., `/image.png`), the file is resolved from the `public` directory. If an image is reported incorrectly, ignore it with `excludes`: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { image: { checkDeadImages: { excludes: ['/generated-diagram.png'], }, }, }, }); ``` ### markdown.showLineNumbers - **Type**: `boolean` Controls whether code blocks show line numbers. Defaults to `false`. When enabled globally, you can use `lineNumbers=false` in the code block meta to disable line numbers for a specific block. Conversely, when disabled globally, you can use `lineNumbers` or `lineNumbers=true` to enable line numbers for a specific block. See [Show code line numbers](https://rspress.rs/guide/use-mdx/code-blocks.md#show-code-line-numbers) for details. ### markdown.defaultWrapCode - **Type**: `boolean` Controls whether long code lines wrap by default. Defaults to `false`. When enabled globally, you can use `wrapCode=false` in the code block meta to disable wrapping for a specific block. Conversely, when disabled globally, you can use `wrapCode` or `wrapCode=true` to enable wrapping for a specific block. See [Wrap code](https://rspress.rs/guide/use-mdx/code-blocks.md#wrap-code) for details. ### markdown.defaultCodeOverflow - **Type**: `{ height?: number; behavior?: 'fold' | 'scroll' }` By default, Rspress code blocks are fully expanded with no overflow behavior. You can use meta attributes like ` ```tsx fold ` to control overflow for individual code blocks. This config sets the global default overflow behavior, which is automatically applied when code blocks exceed the specified height. - `height`: Height threshold in pixels. When not set, no overflow behavior is applied. - `behavior`: How to handle code blocks exceeding the height. Defaults to `'scroll'`. - `'scroll'`: Fixed height with vertical scrollbar. - `'fold'`: Collapsible with an expand/collapse button. ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { defaultCodeOverflow: { height: 400, behavior: 'fold', }, }, }); ``` Individual code blocks can override the default using `height` or `fold` meta attributes. See [Code block height](https://rspress.rs/guide/use-mdx/code-blocks.md#code-block-height) for details. ### markdown.crossCompilerCache - **Type**: `boolean` - **Default**: `true` Whether to enable cross-compiler cache for MDX compilation during `rspress build`. When enabled, Rspress will cache MDX parsing results across multiple compilers (web and node), which can speed up the production build process by approximately 10%. This option only takes effect in production builds and is inspired by [Docusaurus](https://docusaurus.io/). ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { crossCompilerCache: true, }, }); ``` ### markdown.globalComponents - **Type**: `string[]` Registers components globally so they are available in every MDX file without import statements. For example: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; import path from 'path'; export default defineConfig({ markdown: { globalComponents: [path.join(__dirname, 'src/src/components/Alert.tsx')], }, }); ``` Then you can use the `Alert` component in any MDX file: ```mdx title="test.mdx" This is an info alert ``` ### markdown.extractDescription - **Type**: `boolean` - **Default**: `true` Whether to automatically extract the description from the markdown content. When enabled, Rspress extracts the first contentful paragraph below the `h1` heading as the page description. If `description` is specified in [frontmatter](https://rspress.rs/api/config/config-frontmatter.md#description), it takes priority and automatic extraction is skipped. The extracted description is used for `` and Open Graph `` tags. See [Custom Head - How description is determined](https://rspress.rs/guide/advanced/custom-head.md#how-description-is-determined) for details. ### markdown.cjkFriendlyEmphasis - **Type**: `boolean` - **Default**: `true` Whether to enable CJK-friendly emphasis and strikethrough parsing. When enabled, `**`, `*`, and `~~` will correctly parse as emphasis/strikethrough when CJK characters are adjacent to the outside of the markers, even if punctuation (CJK or ASCII) appears inside the markers. This addresses a [CommonMark spec limitation](https://github.com/commonmark/commonmark-spec/issues/650) where emphasis markers are not recognized correctly when CJK characters are adjacent. For example, `**该星号不会被识别,而是直接显示。**这是因为它没有被识别为强调符号。` would not render the first sentence as bold without this option, because CJK characters follow the closing `**`. For more details on this extension, see [markdown-cjk-friendly](https://github.com/tats-u/markdown-cjk-friendly). Enabled by default. To disable: ```ts title="rspress.config.ts" import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { cjkFriendlyEmphasis: false, }, }); ``` --- url: https://rspress.rs/api/commands.md --- > 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. # Commands This page introduces the built-in Rspress commands and their common options. For `dev`, `build`, and `preview`, the optional `[root]` argument specifies the docs root directory. If omitted, Rspress uses `root` from the config file, or `docs` in the current directory when `root` is not configured. ## rspress dev The `rspress dev` command starts a local development server for previewing and debugging your docs. ```txt Usage: $ rspress dev [root] Options: --port Set the port number for the server --host [host] Set the host that the server listens to --base Set the base path and override config.base -v, --version Display version number -h, --help Display this message -c, --config Set the configuration file (relative or absolute path) ``` ## rspress build The `rspress build` command builds the documentation site for production. ```txt Usage: $ rspress build [root] Options: --base Set the base path and override config.base -h, --help Display this message -c, --config Set the configuration file (relative or absolute path) ``` ## rspress preview The `rspress preview` command is used to preview the output files of the `rspress build` command locally. ```txt Usage: $ rspress preview [root] Options: --port Set the port number for the server --host [host] Set the host that the server listens to --base Set the base path and override config.base -h, --help Display this message -c, --config Set the configuration file (relative or absolute path) ``` ## rspress eject The `rspress eject` command copies a built-in theme component to your project so you can customize it. ```txt Usage: $ rspress eject [component] Options: -h, --help Display this message -c, --config Set the configuration file (relative or absolute path) ``` The optional `[component]` argument is the theme component to eject. If omitted, Rspress lists all ejectable components. After ejection, the component files are placed in `theme/components/`. Re-export the component in `theme/index.tsx` to use your customized version. --- url: https://rspress.rs/blog/index.md --- > 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. # Rspress blogs ## [Announcing Rspress 2.0](/blog/rspress-v2) > January 30, 2026 · Sooniter Rspress 2.0 is officially released, featuring a brand new theme, AI-native SSG-MD and llms.txt generation, Shiki code highlighting, lazyCompilation, an improved documentation development experience. --- url: https://rspress.rs/blog/rspress-v2.md --- > 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. _January 30, 2026_ # Announcing Rspress 2.0 ![Rspress 2.0 Banner](https://assets.rspack.rs/rspress/assets/banner.png) *** We are excited to announce the official release of Rspress 2.0! Rspress is a static site generator built on [Rsbuild](https://rsbuild.rs/), designed as a documentation site tool for developers. Since its initial release in 2023, Rspress 1.x has gone through **144 releases**, with **125 contributors** participating in the project. More and more developers have chosen Rspress for its **fast compilation performance, convention-based routing, and component library previews** to build beautiful and reliable documentation sites. Based on community feedback, Rspress 2.0 brings major improvements to [**theme aesthetics**](#brand-new-theme), [**AI-native**](#llms-txt-ssg-md), [**documentation development experience**](#doc-dx), [**integration with Rslib**](#rslib-rspress), and more. ## Why Rspress 2.0 Rspress 1.x already solved the compilation performance problem for documentation site frameworks, but some other issues still affected the core experience as a documentation development tool. Version 2.0 goes beyond the pursuit of compilation performance and also focuses on other aspects of the documentation site experience: - **Theme Styling**: A **more beautiful default theme**, along with multiple [custom theme](https://rspress.rs/guide/basic/custom-theme.md) approaches, addressing the lack of stable APIs for theme customization in 1.x. - **AI-native**: Documentation serves not only human readers but also needs to be better understood and used by Agents. Rspress now has built-in [llms.txt](https://llmstxt.org/) generation and the [**SSG-MD**](https://rspress.rs/guide/basic/ssg-md.md) capability derived from SSG, generating high-quality Markdown content for Agents to read. - **lazyCompilation, Instant Startup**: [lazyCompilation](https://rspack.rs/guide/features/lazy-compilation) is enabled by default, combined with resource prefetching on link hover, building only the required files when visiting specific routes, achieving **instant startup** regardless of project size. - **Shiki Code Highlighting**: Shiki is integrated by default, completing **syntax highlighting at build time**, with support for theme switching and transformer extensions like [@rspress/plugin-twoslash](https://rspress.rs/plugin/official-plugins/twoslash.md), delivering richer code block display effects. - **Documentation Development Experience**: Optimized HMR for `_nav.json`, `_meta.json` and other files, added [json schema](https://rspress.rs/guide/basic/auto-nav-sidebar.md#json-schema-type-hint) for IDE code hints; dead link checking enabled by default; new file code block syntax supporting external file references; [@rspress/plugin-preview](https://rspress.rs/plugin/official-plugins/preview.md) and [@rspress/plugin-playground](https://rspress.rs/plugin/official-plugins/playground) can now be used simultaneously. - **Rslib Integration**: You can now select Rspress as the documentation tool when creating a component library project with `create-rslib`, quickly setting up a component documentation site. This is a comprehensive upgrade to the existing architecture. Below we introduce Rspress 2.0 and its **brand new theme, high-quality llms.txt generation, Shiki integration, lazyCompilation**, and other important features. ![Rspress 2.0 Features](https://assets.rspack.rs/rspress/assets/features.png) ## 2.0 New features ### Brand new theme \{#brand-new-theme} The 2.0 default theme has undergone a systematic upgrade, crafted by designer [@Zovn Wei](https://x.com/wei_zhong41532), with significant improvements in visual effects and reading experience. Each component is individually replaceable, providing high customizability. ![New Theme](https://assets.rspack.rs/rspress/assets/new-theme.png) #### Theme customization From low to high levels of customization, there are four [custom theme](https://rspress.rs/guide/basic/custom-theme.md) approaches: CSS variables, BEM class names, ESM re-export overrides, and component eject. - **CSS Variables**: The new theme exposes more CSS variables, covering theme colors, code blocks, homepage styles, and more. You can interactively preview and adjust all CSS variables on the [CSS Variables](https://rspress.rs/ui/vars.md) page, then copy the configuration directly into your project once you find a satisfying setup. ```css :root { /* Custom theme colors */ --rp-c-brand: #3451b2; --rp-c-brand-dark: #2e4599; /* Custom code block styles */ --rp-code-block-bg: #1e1e1e; } ``` - **BEM Class Names**: All built-in components now adopt the [BEM naming convention](https://getbem.com/). This is an old-school choice, but also a well-considered decision. Users can precisely adjust styles through CSS selectors, with clearer HTML structure; at the same time, it decouples from any CSS framework the user may be using, allowing free choice of CSS frameworks ([Tailwind](https://tailwindcss.com/), [Less](https://lesscss.org/), [Sass](https://sass-lang.com/), etc.), such as using Tailwind V4 or V3 without worrying about version conflicts with Rspress's built-in CSS. ```css /* BEM naming convention */ .rp-[component-name]__[element-name]--[modifier-name] { } /* Easily override component styles using BEM class names */ .rp-nav__title { height: 32px; } .rp-nav-menu__item--active { color: purple; } ``` - **ESM Re-export Overrides**: If CSS modifications cannot meet your customization needs, you can perform deeper customization through JS. Using [ESM re-exports](https://rspress.rs/guide/basic/custom-theme.md#reexport) in `theme/index.tsx`, you can **override** any built-in Rspress component. ```tsx title="theme/index.tsx" import { Layout as BasicLayout } from '@rspress/core/theme-original'; const Layout = () => some content} />; export { Layout }; //[!code highlight] export * from '@rspress/core/theme-original'; //[!code highlight] ``` - **Component Eject**: You can use the new [`rspress eject [component]`](https://rspress.rs/api/commands.md#rspress-eject) command, which copies the source code of the specified component to the `theme/components/` directory. You can freely modify this code, or even hand it to AI for modifications, to achieve deep customization. ```bash # Export the DocFooter component to the theme directory rspress eject DocFooter ``` #### Navbar and sidebar tags Rspress 2.0 implements a [Tag component](https://rspress.rs/ui/layout-components/tag.md). You can now use the tag property in frontmatter to add UI annotations in the sidebar or navbar. ```mdx --- tag: new, experimental # Displayed in H1 and Sidebar --- import { Tag } from '@rspress/core/theme'; # Tag ## Common tags {/* displayed in the right-side outline */} ``` ![Tag component display in sidebar](https://assets.rspack.rs/rspress/assets/tag-component.png) #### Built-in Multi-language Support In version 1.x, Rspress included only English UI text. Using other languages such as zh required manually configuring every string, which was cumbersome. The 2.0 theme now includes built-in translations for zh, en, ja, ko, ru, and more languages. The system automatically tree-shakes translations based on language configuration and usage, bundling only the text and languages you use. Languages that are not built in fall back to en text. You can also extend or override translations through the [`i18nSource`](https://rspress.rs/api/config/config-basic.md#i18nsource) configuration option. Rspress will add more built-in languages in the future. If you're interested, see [this contributor's Pull Request](https://github.com/web-infra-dev/rspress/pull/2827). ### llms.txt: SSG-MD for High-Quality Markdown content \{#llms-txt-ssg-md} Rspress now integrates [llms.txt](https://llmstxt.org/) generation into core, and implements the new SSG-MD (Static Site Generation to Markdown) capability. In React-based dynamic rendering frontend frameworks, extracting static information is often difficult, and Rspress faces the same challenge. Rspress allows users to enhance documentation expressiveness through [MDX fragments](https://rspress.rs/guide/use-mdx/components.md), React components, Hooks, and TSX routes. However, this dynamic content faces the following issues when converting to Markdown text: - Feeding MDX directly to AI includes a large amount of code syntax noise and loses React component content - Converting HTML to Markdown often yields poor results with unreliable information quality To solve this problem, Rspress 2.0 introduces the [SSG-MD](https://rspress.rs/guide/basic/ssg-md.md) feature. This is a new capability, similar to [Static Site Generation (SSG)](https://rspress.rs/guide/basic/ssg.md), but instead of rendering pages as HTML files, it renders them as Markdown files and generates [llms.txt](https://llmstxt.org/) and llms-full.txt files. ![SSG-MD feature overview](https://assets.rspack.rs/rspress/assets/ssg-md-overview.jpg) Compared to traditional approaches like converting HTML to Markdown, SSG-MD has access to richer information sources during rendering, such as the React virtual DOM, resulting in higher static information quality and flexibility. ![SSG-MD rendering flow](https://assets.rspack.rs/rspress/assets/ssg-md-flow.jpg) Enabling it is simple: ```typescript import { defineConfig } from '@rspress/core'; export default defineConfig({ llms: true, }); ``` After the build, Rspress generates the following structure: ```tree doc_build ├── llms.txt ├── llms-full.txt ├── guide │ └── start │ └── introduction.md └── ... ``` If you want to customize the rendering content in custom components, you can control it through environment variables: ```tsx export function Tab({ label }: { label: string }) { if (import.meta.env.SSG_MD) { // Output plain text description in SSG-MD mode return <>{`**Tab: ${label}**`}; } // Render interactive component normally return
{label}
; } ``` This preserves the interactive documentation experience while helping AI understand the semantic information of components. > See [SSG-MD Usage Guide](https://rspress.rs/guide/basic/ssg-md.md) for details ### Shiki Build-time code block highlighting \{#shiki-code-highlighting} Rspress 2.0 uses [Shiki](https://shiki.style/) by default for code highlighting. Compared to the 1.x Prism runtime highlighting approach, Shiki performs highlighting at compile time. 1. Supports multiple theme styles. You can interactively switch and preview different Shiki themes on the [CSS Variables](https://rspress.rs/ui/vars.md) page. 2. Shiki also allows extensions through custom [transformers](https://shiki.style/guide/transformers) to enrich writing, such as twoslash. 3. Programming languages are imported on demand, adding no runtime overhead or bundle size. 4. Achieves accurate syntax highlighting consistent with VS Code based on TextMate grammar. Here are some Shiki transformer examples to give you a feel for the documentation creativity Shiki enables: > Using [@rspress/plugin-twoslash](https://rspress.rs/plugin/official-plugins/twoslash.md) ```ts twoslash const hi = 'Hello'; const msg = `${hi}, world`; // ^? ``` > Using [transformerNotationFocus](https://rspress.rs/guide/use-mdx/code-blocks.md#transformernotationfocus) ```ts console.log('Not focused'); console.log('Focused'); // [!code focus] console.log('Not focused'); ``` > See [Code Blocks](https://rspress.rs/guide/use-mdx/code-blocks.md#shiki-transformers) for details ### Build Performance: lazyCompilation and persistent cache \{#build-performance-lazy-compilation-cache} Rspress 2.0 is powered by Rsbuild and Rspack 2.0 prerelease, with [lazyCompilation](https://rspack.rs/guide/features/lazy-compilation) and [persistent cache](https://rsbuild.rs/config/performance/build-cache) enabled by default. #### lazyCompilation [dev.lazyCompilation](https://rsbuild.rs/config/dev/lazy-compilation) is enabled by default — pages are only compiled when you visit them, dramatically improving development startup speed and even achieving millisecond-level cold starts. Rspress also implements a route prefetch strategy that prefetches target route pages when hovering over links, working together with lazyCompilation to provide a lossless development experience. ![lazyCompilation demo](https://assets.rspack.rs/rspress/assets/lazy-compilation.gif) #### Persistent cache 2.0 also enables [persistent cache](https://rsbuild.rs/config/performance/build-cache) by default, reusing previous compilation results during warm starts to improve build speed by 30%-60%. This means that once you've run `rspress dev` or `rspress build` in your project, subsequent `rspress` startups will be noticeably faster. ### Documentation development experience \{#doc-dx} #### Dead link checking enabled by default Rspress 2.0 enables dead link checking by default. During the build process, it automatically detects invalid links in documentation, helping you discover and fix issues promptly. ```typescript import { defineConfig } from '@rspress/core'; export default defineConfig({ markdown: { link: { checkDeadLinks: true, // Enabled by default, can be disabled with false }, }, }); ``` ![Dead link checking example](https://assets.rspack.rs/rspress/assets/dead-link-check.png) > See [Links](https://rspress.rs/guide/use-mdx/link.md) for details #### File code blocks You can use the `file="./path/to/file"` attribute to reference external files as code block content, maintaining example code in separate files. ````mdx ```ts file="./_demo.ts" ``` ```` ````mdx ```tsx file="/src/components/Button.tsx" ``` ```` > See [File Code Blocks](https://rspress.rs/guide/use-mdx/code-blocks.md#file-code-block) for details #### More flexible meta usage for preview [@rspress/plugin-preview](https://rspress.rs/plugin/official-plugins/preview.md) is now based on meta attributes, making it more flexible and compatible with file code blocks. Here is an example using iframe preview for a code block: ````mdx ```tsx preview="iframe-follow" file="./_demo.ts" ``` ```` It will render as: ```tsx preview="iframe-follow" import { useState } from 'react'; function App() { const [count, setCount] = useState(0); return (

Current count: {count}

); } export default App; ``` Additionally, [@rspress/plugin-playground](https://rspress.rs/plugin/official-plugins/playground.md) now supports being used together with plugin-preview, switching via meta attributes, e.g., ` ```tsx playground ` #### HMR support for configuration files Based on the redesigned [virtual module plugin](https://github.com/rstackjs/rsbuild-plugin-virtual-module) for Rsbuild, HMR is now supported for `i18n.json`, `_nav.json`, `_meta.json`, file code blocks, and iframe-related configurations in `@rspress/plugin-preview`. After modifying these configuration files, the page will automatically hot-reload without manual refresh. ### Rslib & Rspress \{#rslib-rspress} When creating a project with `create-rslib`, you can now select the Rspress tool. This allows you to quickly set up a documentation site alongside your component library for writing usage guides, displaying API references, or live-previewing component effects. Run `npm create rslib@latest` and select Rspress to generate the following file structure: ```tree ├── docs │ └── index.mdx ├── src │ └── Button.tsx ├── package.json ├── tsconfig.json ├── rslib.config.ts └── rspress.config.ts ``` The template includes the [rsbuild-plugin-workspace-dev](https://github.com/rstackjs/rsbuild-plugin-workspace-dev) plugin, which automatically runs Rslib's watch command alongside the Rspress development server. Simply run `npm run doc` to start the Rspress development server and preview your Rslib component library: ```json title="package.json" { "scripts": { "dev": "rslib build --watch", "doc": "rspress dev" // Run this command } } ``` ### More official Rspress plugins Rspress 2.0 has added several official plugins: - [**@rspress/plugin-algolia**](https://rspress.rs/plugin/official-plugins/algolia.md): Replace Rspress's built-in search with [Algolia DocSearch](https://docsearch.algolia.com/) (thanks to the [@algolia](https://x.com/algolia) team for their assistance). - [**@rspress/plugin-twoslash**](https://rspress.rs/plugin/official-plugins/twoslash.md): Add type hints to TypeScript code blocks. - [**@rspress/plugin-llms**](https://rspress.rs/plugin/official-plugins/llms.md): Provide llms.txt generation capability for projects that don't support SSG and SSG-MD. - [**@rspress/plugin-sitemap**](https://rspress.rs/plugin/official-plugins/sitemap.md): Automatically generate [Sitemap](https://www.sitemaps.org) files for SEO optimization. *** ## Other breaking changes ### Migrating from Rspress 1.x If you are a 1.x user, we have prepared a detailed migration guide to help you upgrade from 1.x to 2.0. You can use the "Copy Markdown" feature on the page and feed it to your preferred coding agent (such as Claude Code) to complete the migration. > Please refer to the [Migration Guide](https://rspress.rs/guide/migration/rspress-1-x.md). ### Removal of `mdxRs` configuration We noticed that a large portion of 1.x users were actively disabling `mdxRs` to use Shiki, component library preview features, and custom remark/rehype plugins. With lazyCompilation and persistent cache enabled, performance optimization is already quite significant even with the JS version of the MDX parser. In exchange for better extensibility and maintainability, we decided to stop using the Rust-based MDX parser (`@rspress/mdx-rs`) in the Markdown/MDX compilation pipeline. This enables Rspress to better integrate tools from the JavaScript ecosystem like Shiki. ### Node.js and upstream dependency version requirements Rspress 2.0 requires Node.js version **20+** and React version **18+**. | Dependency | Allowed Range | Default | Notes | | ------------------ | ---------------------- | ------- | --------------------------------------------------------------- | | `react` | `^18.0.0 \|\| ^19.0.0` | 19 | React 17 no longer supported; uses project version if installed | | `react-dom` | `^18.0.0 \|\| ^19.0.0` | 19 | Matches react version | | `react-router-dom` | `^6.0.0 \|\| ^7.0.0` | 7 | Uses project version if installed | | `unified` | `^11.0.0` | 11 | Custom remark/rehype plugins must be compatible | ### Package name and import path changes Rspress has consolidated `rspress`, `@rspress/runtime`, `@rspress/shared`, and `@rspress/theme-default` into `@rspress/core`. Projects and plugins now only need to install a single `@rspress/core` package. ```diff title="package.json" { "dependencies": { - "rspress": "1.x" - "@rspress/shared": "1.x" + "@rspress/core": "^2.0.0" } } ``` ```diff title="rspress.config.ts" - import { defineConfig } from 'rspress/config'; + import { defineConfig } from '@rspress/core'; ``` ```diff title="docs/index.mdx" - import { useDark } from 'rspress/runtime' - import { PackageManagerTabs } from 'rspress/theme'; + import { useDark } from '@rspress/core/runtime' + import { PackageManagerTabs } from '@rspress/core/theme'; ``` If you have developed an Rspress plugin, please change the plugin's peerDependencies from `rspress` to `@rspress/core`: ```json { "peerDependencies": { "@rspress/core": "^2.0.0" } } ``` ## Next steps The release of Rspress 2.0 is just a new beginning. After this release, Rspress will continue to iterate: - **Advancing Ecosystem Integration**: Deeper integration with Rslib and Rstest to provide an integrated development experience for frontend projects and component library projects. - **Exploring Deeper AI and Documentation Integration**: Such as intelligent Q\&A, automatic summarization, and more; refining SSG-MD to make it stable and easier to use. Thank you to all developers and users who have contributed to Rspress! If you encounter any issues or have suggestions during use, please provide feedback in [GitHub Issues](https://github.com/web-infra-dev/rspress/issues). Upgrade to Rspress 2.0 now and experience a brand new documentation development journey! ```sh [npm] npm create rspress@latest ``` ```sh [yarn] yarn create rspress ``` ```sh [pnpm] pnpm create rspress@latest ``` ```sh [bun] bun create rspress@latest ``` ```sh [deno] deno init --npm rspress@latest ``` --- url: https://rspress.rs/index.md --- > 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. # Rspress Lightning Fast Static Site Generator > Made for humans. Understood by AI [Introduction](./guide/start/introduction) | [Quick Start](./guide/start/getting-started) ## Features - [/speed.svg **Blazing fast build speed**](./guide/start/introduction): Built on the Rust-powered front-end toolchain for a faster development experience. - [/mdx.svg **Support for MDX**](./guide/use-mdx/components): MDX is a powerful way to write content, allowing you to use React components in Markdown. - [/search.svg **Built-in full-text search**](./guide/advanced/custom-search): Automatically generates a full-text search index during builds, with search available out of the box. - [/ai.svg **AI-friendly**](./guide/basic/ssg-md): Use SSG-MD to generate llms.txt-compliant indexes and Markdown files so large language models can better understand your docs. - [/static.svg **Static site generation**](./guide/basic/ssg): Builds static HTML files for production so your site can be deployed anywhere. - [/custom.svg **Flexible customization**](./guide/basic/custom-theme): Extend the theme UI and build process through Rspress extension APIs.