DBMS Topics
Reusable Content in MDX
title: "Reusable Content in MDX",
You know that install block you've copy-pasted into 20 different docs pages? Or that warning callout you keep rewriting slightly differently each time?
Stop doing that. MDX lets you write content once and reuse it everywhere — through partials, snippets, templates, and variables. When something changes (and it will), you update one file instead of hunting through dozens.
Content Partials
Partials are small MDX files containing a chunk of content. Import them, drop them in, done.
Creating Partials
{/* partials/_install-node.mdx */}
## Prerequisites
Make sure you have Node.js 18+ installed:node --version # Should output v18.0.0 or higher
nvm install 18 nvm use 18
{/* partials/_typescript-config.mdx */}
### TypeScript Configuration
Add the following to your `tsconfig.json`:{ "compilerOptions": { "target": "ES2020", "module": "ESNext", "moduleResolution": "bundler", "jsx": "react-jsx", "strict": true, "esModuleInterop": true, "skipLibCheck": true } }
Using Partials
Now any guide can pull those in:
{/* guides/getting-started.mdx */}
import InstallNode from '../partials/_install-node.mdx';
import TypeScriptConfig from '../partials/_typescript-config.mdx';
# Getting Started
Follow these steps to set up your development environment.
<InstallNode />
## Installationnpm install my-library
Parameterized Partials
Need the same pattern with different data? Pass props:
One component, any package, every package manager. No more maintaining four separate install blocks.
Shared Snippets
Snippets are smaller than partials — think callouts, badges, API endpoint labels. Tiny reusable pieces you drop in everywhere.
Global Snippet Registration
Register them globally so you never need import statements in your MDX files:
// mdx-components.jsx (Next.js App Router)
import { Callout } from './snippets/Callout';
import { VersionBadge } from './snippets/VersionBadge';
import { ApiEndpoint } from './snippets/ApiEndpoint';
export function useMDXComponents(components) {
return {
Callout,
VersionBadge,
ApiEndpoint,
...components,
};
}Now just use them anywhere — no imports needed:
# User API <VersionBadge version="2.1.0" status="stable" />
<ApiEndpoint method="GET" path="/api/v2/users/:id" auth={true} />
<Callout type="warning" title="Rate Limited">
This endpoint is limited to 100 requests per minute per API key.
</Callout>Component Composition for Content Reuse
Feature Comparison Tables
Instead of maintaining markdown tables that get out of sync, use a data-driven component:
Step-by-Step Reusable Pattern
Numbered steps show up all over docs. Build them once:
<Steps>
<Step number={1} title="Install Dependencies">
Run the installation command for your package manager.
</Step>
<Step number={2} title="Configure Your Project">
Add the configuration file to your project root.
</Step>
<Step number={3} title="Start Development Server">
Launch the dev server and open your browser.
</Step>
</Steps>Template Patterns
Documentation Page Template
If every API page has the same structure (title, version badge, deprecation notice, content), make it a template:
// templates/DocTemplate.jsx
import { Callout } from '../snippets/Callout';
import { VersionBadge } from '../snippets/VersionBadge';
import { ApiEndpoint } from '../snippets/ApiEndpoint';
export function DocTemplate({
title,
version,
status,
description,
since,
deprecated,
children,
}) {
return (
<article>
<header className="mb-8">
<div className="flex items-center gap-3">
<h1 className="text-3xl font-bold">{title}</h1>
{version && <VersionBadge version={version} status={status} />}
</div>
{description && <p className="text-lg text-gray-600 mt-2">{description}</p>}
{since && <p className="text-sm text-gray-500">Available since v{since}</p>}
</header>
{deprecated && (
<Callout type="danger" title="Deprecated">
This feature is deprecated and will be removed in a future version.
{deprecated.alternative && (
<span> Use <code>{deprecated.alternative}</code> instead.</span>
)}
</Callout>
)}
<div className="doc-content prose prose-lg">
{children}
</div>
</article>
);
}Content Variables
Define your product name, version, and URLs in one place. When the version bumps, you change one file:
// content/variables.js
export const PRODUCT_NAME = 'AcmeDocs';
export const CURRENT_VERSION = '3.2.1';
export const MIN_NODE_VERSION = '18.0.0';
export const GITHUB_URL = 'https://github.com/acme/acmedocs';
export const DOCS_URL = 'https://docs.acme.com';
export const SUPPORT_EMAIL = 'support@acme.com';
export const INSTALL_COMMAND = `npm install ${PRODUCT_NAME.toLowerCase()}@${CURRENT_VERSION}`;
export const LINKS = {
quickstart: '/docs/quickstart',
api: '/docs/api-reference',
examples: '/docs/examples',
changelog: '/docs/changelog',
};import { PRODUCT_NAME, CURRENT_VERSION, MIN_NODE_VERSION, INSTALL_COMMAND } from '../content/variables';
# Welcome to {PRODUCT_NAME}
You are reading the documentation for **{PRODUCT_NAME} v{CURRENT_VERSION}**.
## Requirements
- Node.js {MIN_NODE_VERSION} or higher
- npm 9+
## Quick Install{INSTALL_COMMAND}
Conditional Content Inclusion
Environment-Based Content
Show different content in dev vs production, or based on feature flags:
import { IfEnv, Platform } from '../components/ConditionalContent';
## Installation
<Platform only="mac">brew install acmedocs
choco install acmedocs
curl -fsSL https://get.acme.com | bash
Audience-Based Content
Let readers self-select their experience level:
// components/Audience.jsx
export function ForBeginners({ children }) {
return (
<details className="beginner-content border rounded-lg p-4 my-4">
<summary className="cursor-pointer font-medium">
📘 New to this concept? Expand for a beginner explanation
</summary>
<div className="mt-3">{children}</div>
</details>
);
}
export function ForAdvanced({ children }) {
return (
<details className="advanced-content border rounded-lg p-4 my-4">
<summary className="cursor-pointer font-medium">
🔬 Advanced Details
</summary>
<div className="mt-3">{children}</div>
</details>
);
}DRY Principles Summary
| Pattern | Use Case | Benefit |
|---|---|---|
| Content Partials | Multi-paragraph reusable blocks | Single source of truth |
| Snippets | Small inline elements (badges, callouts) | Consistent UI patterns |
| Template Components | Page structure patterns | Uniform documentation |
| Content Variables | Names, versions, URLs | Change once, update everywhere |
| Conditional Content | Platform/audience-specific text | Targeted documentation |
| Composition | Complex reusable layouts | Flexible building blocks |
Before (Repetitive) vs After (DRY)
Before — duplicated in 20 files:
After — single source of truth:
<Callout type="warning" title="Node.js Required">
This feature requires Node.js {MIN_NODE_VERSION} or higher.
Run `node --version` to verify your installation.
</Callout>Rule of thumb: If you've pasted the same content into three places, it's time to make it a partial or component. Duplicated content rots fast — a single typo fix should only require changing one file.
Apply these patterns and your docs become a proper codebase: modular, easy to maintain, and consistent across hundreds of pages.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Reusable Content in MDX.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this MDX topic.
Search Terms
mdx, mdx tutorial, learn mdx, markdown, jsx, tutorial, advanced, reusable
Related MDX Topics