MDX Custom Components
Relevant source files
The following files were used as context for generating this wiki page:
The Railway documentation site utilizes a system of custom React components to render MDX content. This architecture enhances standard Markdown and MDX files, transforming them into interactive and consistently styled documentation pages. By mapping both standard HTML elements and custom-named elements to bespoke React components, the system provides a rich user experience beyond what plain Markdown can offer.
This functionality is primarily managed through a components object defined in the page rendering logic, which is then passed to the MDX renderer provided by next-contentlayer. This allows for a clean separation between the content (written in MDX) and its presentation (defined in React components).
Sources: src/pages/dynamic/[...slug].tsx:20-31, src/pages/[...slug].tsx:20-31
Core Architecture
The rendering of MDX content follows a pipeline orchestrated by Next.js, Contentlayer, and a set of custom components. At build time, Contentlayer processes all .md files, converting them into structured data and runnable code. When a user requests a page, Next.js retrieves the appropriate page object and uses the useMDXComponent hook to render the content, injecting the custom React components to replace their corresponding MDX elements.
The following diagram illustrates the high-level data flow for rendering a documentation page.
Component Mapping
Both static (/[...slug].tsx) and dynamic (/dynamic/[...slug].tsx) page handlers define a components object that maps MDX elements to their corresponding React components. This includes overriding standard HTML tags like h2, a, and pre, as well as defining custom components that can be used directly in MDX, such as <Banner /> or <Collapse />.
Component Map Definition
The following table details the primary components mapped in the system.
| MDX Tag/Element | Mapped React Component | Description |
|---|---|---|
a | Anchor | A custom-styled link component. |
h2, h3, h4 | H2, H3, H4 | Custom components for rendering headings with specific styles. |
pre | CodeBlock | A wrapper for code blocks that provides syntax highlighting and handles color mode. |
code | InlineCode | A component for rendering inline code snippets, also aware of color mode. |
Collapse | Collapse | A custom component for creating collapsible content sections. |
Image | Image | A custom component for rendering images. |
Banner | Banner | A component for displaying various types of banners. |
PriorityBoardingBanner | PriorityBoardingBanner | A specific banner related to "Priority Boarding". |
DeprecationBanner | DeprecationBanner | A specific banner used to mark deprecated features. |
TallyButton|TallyButton| A button component for integrating with Tally forms. |
Sources: src/pages/[...slug].tsx:20-32, src/pages/dynamic/[...slug].tsx:20-32
Special Prop Injection
For components like CodeBlock and InlineCode, additional props are required that are not available within the MDX content itself (e.g., colorModeSSR). The system handles this by creating a new componentsWithProps object, which wraps the original components in functions to inject these server-side rendered props at runtime.
// src/pages/[...slug].tsx:40-48
const componentsWithProps = {
...components,
pre: (props: CodeBlockProps) => (
<CodeBlock {...props} colorModeSSR={colorModeSSR} />
),
code: (props: InlineCodeProps) => (
<InlineCode {...props} colorModeSSR={colorModeSSR} />
),
};
Sources: src/pages/[...slug].tsx:40-48, src/pages/dynamic/[...slug].tsx:46-54
Key Custom Components
Several custom components are critical to the functionality and user experience of the documentation.
Layout and Structure
Layout(src/mdxLayouts/index.tsx): This component serves as the primary layout wrapper for all MDX content. Its main role is to receive thefrontMatterandrawMarkdownand pass them to the more complexDocsLayout.DocsLayout(src/layouts/DocsLayout.tsx): This is the main structural component for a documentation page. It is responsible for rendering the page title, handling SEO, providing "Copy as Markdown" and "Edit on GitHub" functionality, and rendering the previous/next page navigation buttons.PageNav(src/components/PageNav.tsx): This component dynamically generates the "On This Page" sidebar navigation. It works by querying the rendered DOM forh2,h3, andh4elements within the.docs-contentcontainer, building a hierarchical tree of headers, and then rendering them as a list of links. It also tracks the user's scroll position to highlight the currently active section.
The following diagram shows the logic flow for building the PageNav component.
Interactive & Rich Content
CodeBlockand Directives: TheCodeBlockcomponent replaces the standard<pre>element. It uses anormalizeutility to parse special comment directives within the code, enabling features like line highlighting. This allows authors to draw attention to specific parts of a code snippet directly from the Markdown.
The normalize function supports the following directives:
| Directive | Example | Function |
|---|---|---|
highlight-next-line | // highlight-next-line | Highlights the line immediately following the comment. |
highlight-line | code here // highlight-line | Highlights the line where the comment is placed. |
highlight-start | // highlight-start | Begins a multi-line block to be highlighted. |
highlight-end | // highlight-end | Ends a multi-line highlight block. |
hide-start / hide-end | // hide-start | Hides a block of code from the rendered output. |
Sources: src/components/CodeBlock/normalize.ts:6-11, 84-149
Content Processing Pipeline
The foundation of the MDX system is contentlayer, which is configured in contentlayer.config.ts. It defines the document type (Page), its fields (title, description), and the MDX processing pipeline. The remarkPlugins are crucial for enhancing the raw Markdown.
remark-gfm: Adds support for GitHub Flavored Markdown features like tables and strikethrough.remark-slug: Generates URL-friendly slugs for all headings (e.g.,## My Headingbecomes<h2 id="my-heading">).remark-autolink-headings: Uses the slugs generated byremark-slugto automatically create anchor links for each heading.
This pipeline ensures that the raw MDX is properly structured and augmented with necessary metadata and functionality before it is even passed to the React rendering layer.
Sources: contentlayer.config.ts:3-5, 24
Summary
The MDX custom component system in the Railway documentation is a sophisticated solution that combines the simplicity of Markdown with the power of React. By using Contentlayer to preprocess MDX files and then mapping elements to a suite of custom components, the platform delivers a rich, interactive, and maintainable documentation experience. Key features like dynamic page navigation, advanced code block highlighting, and consistent layout are all enabled by this architecture, providing a solid foundation for authors and a superior experience for end-users.
Sources: src/pages/dynamic/[...slug].tsx, src/components/PageNav.tsx