notebook-mdx

Notebook Directives

Use directive syntax to embed Jupyter notebooks in your MDX content

Notebook Directives

The remarkNotebookDirective plugin enables you to embed Jupyter notebooks using a clean directive syntax that integrates seamlessly with the remark/rehype ecosystem.

Installation

First, ensure you have the required dependencies:

npm install notebook-mdx remark-directive

Basic Setup

Configure your MDX pipeline to use both remark-directive and remarkNotebookDirective:

import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkDirective from 'remark-directive';
import { remarkNotebookDirective } from 'notebook-mdx';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';

const processor = unified()
  .use(remarkParse)
  .use(remarkDirective) // Must come before remarkNotebookDirective
  .use(remarkNotebookDirective)
  .use(remarkRehype)
  .use(rehypeStringify);

Next.js Configuration

For Next.js projects using Fumadocs or similar:

// source.config.ts
import { defineConfig } from 'fumadocs-mdx/config';
import remarkDirective from 'remark-directive';
import { remarkNotebookDirective } from 'notebook-mdx';

export default defineConfig({
  mdxOptions: {
    remarkPlugins: [
      remarkDirective,
      [remarkNotebookDirective, { 
        componentName: "NotebookLoader" 
      }]
    ]
  }
});

Syntax

Container Directive (with caption)

:::notebook{file="./example.ipynb" cells="1-5" showCellNumbers}
This is an optional caption that appears below the notebook
:::

Leaf Directive (no caption)

::notebook{file="./example.ipynb" hideCode showOutputs}

Options

All options are passed as attributes in the directive:

OptionTypeDescription
filestringRequired. Path to the .ipynb file (relative to current file)
cellsstringCell range to display (e.g., "1-5", "2,4,6")
hideCodebooleanHide code cells, show only outputs
showOutputsbooleanShow only outputs (alias for hideCode)
showCellNumbersbooleanDisplay cell execution numbers
showLanguageIndicatorsbooleanShow language badges on code cells
themestringSyntax highlighting theme
classNamestringAdditional CSS classes
widthstringCustom width (CSS value)
heightstringCustom height (CSS value)
interactivebooleanEnable interactive features (if supported)

Boolean Attributes

Boolean attributes can be used in several ways:

<!-- All equivalent ways to set boolean true -->
::notebook{file="./example.ipynb" hideCode}
::notebook{file="./example.ipynb" hideCode="true"}
::notebook{file="./example.ipynb" hideCode=""}

<!-- Set boolean false -->
::notebook{file="./example.ipynb" hideCode="false"}

Examples

Basic Notebook Embedding

::notebook{file="./data-analysis.ipynb"}

Show Only Specific Cells

:::notebook{file="./tutorial.ipynb" cells="1-3,7,10-12"}
Introduction to machine learning concepts
:::

Hide Code, Show Only Outputs

::notebook{file="./visualization.ipynb" hideCode showCellNumbers}

Custom Styling

:::notebook{file="./demo.ipynb" className="my-notebook" theme="github-dark"}
Custom styled notebook with dark theme
:::

Plugin Options

Configure the plugin behavior when initializing:

import { remarkNotebookDirective } from 'notebook-mdx';

// With custom options
.use(remarkNotebookDirective, {
  baseDir: './notebooks',        // Base directory for notebook files
  componentName: 'MyNotebook'    // Custom component name
})

Available Plugin Options

OptionTypeDefaultDescription
baseDirstringFile directoryBase directory for resolving relative notebook paths
componentNamestring"NotebookLoader"Name of the component to render notebooks

Error Handling

The plugin provides helpful error messages for common issues:

<!-- Missing file attribute -->
::notebook{cells="1-5"}
<!-- Error: Unexpected missing `file` attribute on `notebook` directive -->

<!-- Invalid syntax -->
:notebook{file="./example.ipynb"}
<!-- Error: Unexpected `:notebook` text directive, use two colons for a leaf directive -->

<!-- File not found -->
::notebook{file="./missing.ipynb"}
<!-- Error: Failed to process notebook file "./missing.ipynb": ENOENT -->

Auto-Generated Components

The directive syntax automatically generates the appropriate component structure. No manual imports needed - everything is handled by the remark plugin!

Why Use Directives?

The directive syntax provides several advantages:

  • Clean syntax: No need to import components manually
  • Consistent: Works the same way across all MDX files
  • Flexible: Easy to add options and customize behavior
  • Maintainable: Changes to the plugin affect all notebooks automatically
  • Type-safe: Full TypeScript support with proper error checking

Get started with the directive syntax today for the cleanest notebook embedding experience!