This recipe assumes your server has the d2 CLI installed.

Create a file src/components/D2.astro:

---
import { execSync } from 'node:child_process';

const {
  padding = 10,
  sketchy = true,
  theme = 100,
  code,
} = Astro.props;

// Generate the document SVG
let output = await execSync(`d2 - -`, {
    input: code,
    encoding: 'utf8',
    env: {
      D2_PAD: padding,
      D2_SKETCH: sketchy,
      D2_THEME: theme,
    }
  })
---

<Fragment set:html={output} />

I think the code here is pretty self-explanatory. A few callouts:

  1. This works by sending the diagram text (the code prop) to the d2 CLI for conversion to SVG.
  2. By calling d2 - -, we cause d2 to listen from stdin and print to stdout.
  3. Parameters are passed to d2 using environment variables.

Be aware this is dependent on being run in a Node execution context because it imports the node:child_process module. It’s also server-side only rendering for the same reasons.

Usage

To reference this in your MDX without imports, add it to the components option of the Content component in your page:

import D2 from '../../components/D2.astro';

// when rendering <Content />:
<Content components={{ D2 }} />

Then in your MDX:

<D2 code="x -> y" />

Renders as:

xy