MDX Notes
How to import React components, npm packages, utilities, and data into your MDX files — with patterns for keeping things clean.
Imports are how you bring the React ecosystem into your MDX files. Want a chart library? Import it. Custom button component? Import it. Utility function for formatting dates? Import it. Standard ES module syntax, same as any JavaScript file.
Import Syntax in MDX
MDX uses standard JavaScript ES module imports. They go at the top of your file, before any content:
import { Button } from './components/Button'
import Layout from './layouts/DocLayout'
import { formatDate, capitalize } from './utils/helpers'
# My Document
Content starts after imports...
<Button>Click me</Button>Import Rules in MDX
- Imports must be at the top of the file (or after frontmatter)
- Standard ES module syntax — nothing MDX-specific
- Relative paths resolve from the MDX file's location
- You can import
.js,.jsx,.ts,.tsx,.json, and other supported file types
import { Alert } from '../components/Alert'
import theme from '../config/theme.json'
{/* Imports can come after frontmatter but before content */}
# Page Title
<Alert>This uses the imported component</Alert>Importing from Local Files
Relative paths start with ./ (same directory) or ../ (parent directory):
Component Imports
{/* Same directory */}
import { Card } from './Card'
{/* Parent directory */}
import { Header } from '../components/Header'
{/* Deeply nested paths */}
import { DataTable } from '../../shared/components/tables/DataTable'
{/* Index files - import from directory name */}
import { Sidebar } from './components/Sidebar'
{/* This resolves to ./components/Sidebar/index.js */}Utility and Helper Imports
import { formatCurrency, formatDate } from '../utils/formatters'
import { validateEmail } from '../utils/validators'
import { API_BASE_URL, MAX_RETRIES } from '../constants'
# Pricing
Our plans start at {formatCurrency(9.99, 'USD')}.
Last updated: {formatDate(new Date(), 'MMMM dd, yyyy')}Data File Imports
Style Imports
import './styles/page.css'
import styles from './ArticlePage.module.css'
<div className={styles.container}>
<article className={styles.article}>
Content here...
</article>
</div>Importing from npm Packages
Anything in your node_modules is fair game:
Popular UI Libraries
{/* Material UI */}
import { Button, TextField, Card } from '@mui/material'
import { ThemeProvider } from '@mui/material/styles'
{/* Chakra UI */}
import { Box, Flex, Text, Badge } from '@chakra-ui/react'
{/* Headless UI */}
import { Disclosure, Transition } from '@headlessui/react'
{/* Radix UI */}
import * as Accordion from '@radix-ui/react-accordion'Utility Libraries
Syntax Highlighting and Code Libraries
Named vs Default Imports
You need to know which kind a module exports to import it correctly.
Default Imports
A module can have one default export. You can name it whatever you want when importing:
{/* The module exports a default */}
{/* export default function Layout() { ... } */}
import Layout from './components/Layout'
import MyLayout from './components/Layout' {/* Same thing, different name */}
import Whatever from './components/Layout' {/* Also valid */}Named Imports
Named exports must be imported by their exact name (or aliased with as):
{/* The module has named exports */}
{/* export function Button() { ... } */}
{/* export function Card() { ... } */}
{/* export const theme = { ... } */}
import { Button, Card, theme } from './components/ui'
{/* Renaming with 'as' */}
import { Button as PrimaryButton } from './components/ui'
import { Button as BaseButton } from './base/Button'Combining Default and Named Imports
{/* Module with both default and named exports */}
import React, { useState, useEffect, useCallback } from 'react'
import Layout, { Sidebar, Footer } from './components/Layout'Namespace Imports
Import everything as a single object:
import * as Icons from 'react-icons/fi'
import * as utils from '../utils'
{/* Access via dot notation */}
<Icons.FiHome /> Home
<Icons.FiSettings /> Settings
{utils.formatDate(new Date())}Dynamic Imports
Load components on demand instead of upfront. Great for heavy stuff like charts or editors that not every visitor needs.
React.lazy with Suspense
Conditional Dynamic Imports
Sometimes you only want to load something client-side (like a map library that needs window):
Next.js Dynamic Import Pattern
Import Organization Best Practices
Recommended Import Order
Keep imports consistent. Group them like this:
{/* 1. React and core libraries */}
import React, { useState, useEffect } from 'react'
{/* 2. Third-party packages */}
import { motion } from 'framer-motion'
import { format } from 'date-fns'
{/* 3. Internal shared components */}
import { Button, Card, Badge } from '@/components/ui'
import { Layout } from '@/components/Layout'
{/* 4. Local/relative components */}
import { CustomWidget } from './CustomWidget'
import { helpers } from './utils'
{/* 5. Styles */}
import './page.css'
{/* 6. Data/constants */}
import siteConfig from '../config/site'
# Page Content Starts HereGrouping Related Imports
{/* Group by functionality */}
import { Input, Select, Checkbox, RadioGroup } from '@/components/form'
import { Table, Pagination, SortHeader } from '@/components/data'
import { Modal, Drawer, Tooltip } from '@/components/overlay'Path Aliases
Set up aliases to avoid ugly relative path chains:
{/* Without aliases - hard to read */}
import { Button } from '../../../../components/shared/ui/Button'
{/* With aliases - clean and clear */}
import { Button } from '@/components/ui/Button'
import { useAuth } from '@/hooks/useAuth'
import { config } from '@/config'Configure aliases in tsconfig.json or your bundler config:
Practical Tips
<div className="tips">
Tip 1: Only import what you use. Tree-shaking works better with named imports than import *.
Tip 2: Barrel files (index.ts) give you clean public APIs for component directories, but watch out for bundle size.
Tip 3: Prefer named imports over namespace imports (* as) for better tree-shaking.
Tip 4: Use dynamic imports for heavy components not needed on initial load (charts, editors, maps).
Tip 5: If you use the same components in many MDX files, configure them as global components in your MDX provider instead of importing everywhere.
</div>
Common Pitfalls
- Circular imports — File A imports from File B which imports from File A. Restructure to break the cycle.
- Missing file extensions — Some bundlers need explicit extensions (
.js,.jsx). Check your config. - Wrong relative path — Relative paths resolve from the current file, not the project root. Use aliases to avoid confusion.
- Import order causing issues — CSS import order matters for specificity. Side-effect imports run in the order they appear.
- Importing server-only code in MDX — Components that use Node.js APIs (
fs,path) will break in the browser. - Forgetting to install packages —
import X from 'package'fails if the package isn't innode_modules. Run the install first.
Summary
Imports in MDX follow standard ES module patterns — nothing special to learn. You've got access to the entire npm ecosystem and your local components. Keep your imports organized, use path aliases for deep directories, and reach for dynamic imports when you've got heavy components that not everyone needs. That's it.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Importing Components in MDX.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this MDX Tutorial topic.
Search Terms
mdx-tutorial, mdx tutorial, mdx, tutorial, jsx, importing, components, importing components in mdx
Related MDX Tutorial Topics