rspress-custom-theme
Skill97 starsChanged 3 months agoMITView on GitHub
Customize Rspress v2 themes with CSS variables, class overrides, Layout slots, icons, or component ejection.
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 1 is distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 14
Set up
theme/index.tsx: if needed (Levels 1A, 3, 4 all need it) - Very specific: line 93
All built-in components follow BEM naming: .rp-[component]__[element]--[modifier].
- Distinctive: line 97
Use these in your CSS file for targeted style changes when CSS variables aren't granular enough.
- Very specific: line 117
Use runtime hooks inside slot components — import from @rspress/core/runtime: useDark(), useLang(), useVersion(), usePage(), useSite(), …
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Rspress custom theme
Guide for customizing Rspress (v2) themes. Rspress offers four levels of customization, from lightest to heaviest. Always prefer the lightest approach that meets the requirement — lighter approaches are more maintainable and survive Rspress upgrades.
Workflow
- Understand the user's goal — what do they want to change? (colors, layout, inject content, replace a component entirely?)
- Pick the right level using the decision flow below
- Set up
theme/index.tsxif needed (Levels 1A, 3, 4 all need it) - Implement following the patterns in this skill and reference files
- Verify the user's Rspress version is v2 (imports use
@rspress/core/*notrspress/*)
Decision flow
| User wants to... | Level | Approach |
| Change brand colors, fonts, spacing, shadows | 1 | CSS variables |
| Adjust a specific component's style (borders, padding, etc.) | 2 | BEM class overrides |
| Add content around existing components (banners, footers, logos) | 3 | Layout slots (wrap) |
Override MDX rendering (custom <h1>, <code>, etc.) | 3 | components slot |
| Wrap the app in a provider (state, analytics, auth) | 4 | Eject Root |
| Replace built-in icons (logo, GitHub, search, etc.) | — | Icon re-export |
| Completely replace a built-in component | 4 | Eject that component |
| Add a global floating component (back-to-top, chat widget) | — | globalUIComponents config |
| Control page layout structure (hide sidebar, blank page) | — | Frontmatter pageType |
theme/index.tsx — The entry point
Levels 1A, 3, and 4 all require a theme/index.tsx file in the project root (sibling to docs/). This is the single entry point for all theme customizations:
project/
├── docs/
├── theme/
│ ├── index.tsx # Theme entry — re-exports + overrides
│ ├── index.css # CSS variable / BEM overrides (optional)
│ └── components/ # Ejected components (Level 4)
└── rspress.config.tsMinimal setup:
// theme/index.tsx
import './index.css'; // optional
export * from '@rspress/core/theme-original';Critical import rule: Inside theme/ files, always import from @rspress/core/theme-original. The path @rspress/core/theme resolves to your own theme/index.tsx, which causes circular imports. (In docs/ MDX files, @rspress/core/theme is fine — it correctly points to your custom theme.)
Level 1: CSS variables
Override CSS custom properties for brand colors, backgrounds, text, code blocks, and more.
Option A — theme/index.css (use when you also have component overrides in theme/index.tsx):
/* theme/index.css */
:root {
--rp-c-brand: #7c3aed;
--rp-c-brand-light: #8b5cf6;
--rp-c-brand-dark: #6d28d9;
}
.dark {
--rp-c-brand: #a78bfa;
}Option B — globalStyles (use when you only need CSS changes, no component overrides):
// rspress.config.ts
export default defineConfig({
globalStyles: path.join(__dirname, 'styles/custom.css'),
});Full variable list: Read
references/css-variables.mdfor all available CSS variables with light/dark defaults.
Level 2: BEM class overrides
All built-in components follow BEM naming: .rp-[component]__[element]--[modifier].
Common targets: .rp-nav, .rp-link, .rp-tabs, .rp-codeblock, .rp-codeblock__title, .rp-nav-menu__item--active.
Use these in your CSS file for targeted style changes when CSS variables aren't granular enough.
Level 3: wrap (Layout Slots)
Inject content at specific positions in the layout without replacing built-in components. Override Layout in theme/index.tsx:
// theme/index.tsx
import { Layout as OriginalLayout } from '@rspress/core/theme-original';
export * from '@rspress/core/theme-original';
export function Layout() {
return (
<OriginalLayout beforeNavTitle={<MyLogo />} bottom={<CustomFooter />} />
);
}Use runtime hooks inside slot components — import from @rspress/core/runtime: useDark(), useLang(), useVersion(), usePage(), useSite(), useFrontmatter(), useI18n().
All slots & examples: Read
references/layout-slots.mdfor the complete slot list and usage patterns including i18n and MDX component overrides.
Level 4: eject
Copy a built-in component's source for full replacement. Only use when wrap/slots cannot achieve the customization.
rspress eject # list available components
rspress eject DocFooter # eject to theme/components/DocFooter/Then re-export in theme/index.tsx (named export takes precedence over the wildcard):
export * from '@rspress/core/theme-original';
export { DocFooter } from './components/DocFooter';Component list & patterns: Read
references/eject-components.mdfor available components, workflow, and common patterns.
Custom icons
Rspress has 27 built-in icons used across the UI. You can replace any of them by re-exporting your own icon component with the same name — no ejection needed. This uses the same theme/index.tsx mechanism: your named export takes precedence over the wildcard re-export.
Icon type: Each icon is a React component or a URL string:
import type { FC, SVGProps } from 'react';
type Icon = FC<SVGProps<SVGSVGElement>> | string;Example 1 — Replace an icon with a custom SVG component:
// theme/index.tsx
export * from '@rspress/core/theme-original';
// Named export overrides the wildcard — replaces the GitHub icon site-wide
export const IconGithub = (props: React.SVGProps<SVGSVGElement>) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" {...props}>
<path d="M12 2C6.477 2 2 6.484 2 12.017c0 ..." fill="currentColor" />
</svg>
);Example 2 — Use an SVGR import:
// theme/index.tsx
export * from '@rspress/core/theme-original';
import CustomGithubIcon from './icons/github.svg?react';
export const IconGithub = CustomGithubIcon;Using SvgWrapper in MDX or custom components:
import { SvgWrapper, IconGithub } from '@rspress/core/theme';
<SvgWrapper icon={IconGithub} width={24} height={24} />Available icons: IconArrowDown, IconArrowRight, IconClose, IconCopy, IconDeprecated, IconDown, IconEdit, IconEmpty, IconExperimental, IconExternalLink, IconFile, IconGithub, IconGitlab, IconHeader, IconJump, IconLink, IconLoading, IconMenu, IconMoon, IconScrollToTop, IconSearch, IconSmallMenu, IconSuccess, IconSun, IconTitle, IconWrap, IconWrapped.
Source: See the icons source for default implementations.
Global UI components
For components that should render on every page without theme overrides:
// rspress.config.ts
export default defineConfig({
globalUIComponents: [
path.join(__dirname, 'components', 'BackToTop.tsx'),
[
path.join(__dirname, 'components', 'Analytics.tsx'),
{ trackingId: '...' },
],
],
});Page types
Control layout per page via frontmatter pageType:
| Value | Description |
home | Home page with navbar |
doc | Standard doc with sidebar and outline |
doc-wide | Doc without sidebar/outline |
custom | Custom content with navbar only |
blank | Custom content without navbar |
404 | 404 error page |
Fine-grained: set navbar: false, sidebar: false, outline: false, footer: false individually.
Common pitfalls
- Circular import: Using
@rspress/core/themeinstead of@rspress/core/theme-originalintheme/files — causes infinite loop. - Eject over-use: Ejecting when a Layout slot or CSS variable would suffice — creates upgrade burden.
- Missing re-export: Forgetting
export * from '@rspress/core/theme-original'intheme/index.tsx— breaks all un-overridden components. - v1 imports: Using
rspress/themeor@rspress/theme-default— these are v1 paths. v2 uses@rspress/core/theme-original.
Reference
- Custom theme guide: https://rspress.rs/guide/basic/custom-theme
- CSS variables: https://rspress.rs/ui/vars
- Layout component: https://rspress.rs/ui/layout-components/layout
- Built-in icons: https://rspress.rs/ui/icons/
- Built-in hooks: https://rspress.rs/ui/hooks/
- CLI commands (eject): https://rspress.rs/api/commands
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 1
- open-spaced-repetition/ts-fsrs★ 84694% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository31 other files it gives its agents.
- AGENTS.mdAGENTS.md
- create-draft-release-notesSkill
- mdx-to-markdownSkill
- pr-creatorSkill
- release-blog-writerSkill
- rstack-docs-writerSkill
- rstack-eco-ci-debugSkill
- rstack-repo-maintainSkill
- rstack-skill-evaluatorSkill
- migrate-to-rsbuildSkill
- migrate-to-rslibSkill
- migrate-to-rslintSkill
- migrate-to-rstestSkill
- rsbuild-best-practicesSkill
- rsbuild-v2-upgradeSkill
- rsdoctor-analysisSkill
- rsdoctor-v2-upgradeSkill
- rslib-best-practicesSkill
- rslib-modern-packageSkill
- rspack-best-practicesSkill
- rspack-debuggingSkill
- rspack-split-chunksSkill
- rspack-tracingSkill
- rspack-v2-upgradeSkill
- rspress-best-practicesSkill
- rspress-description-generatorSkill
- rspress-docs-generatorSkill
- rspress-v2-upgradeSkill
- rstest-best-practicesSkill
- rstest-debuggingSkill
- storybook-rsbuildSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

