Theme Astro

12/20/2025

Automatically handle your image embedding in MarkDoc

markdoc image embedding in Astro

Automatically handle your image embedding in MarkDoc

Nodes are elements that Markdoc inherits from Markdown, specifically the CommonMark specification. Markdoc nodes enable you to customize how your document renders without using any custom syntax—it consists entirely of Markdown. Customizing nodes lets you extend your implementation incrementally.

How is this achieved? #

The markdoc integration has been installed, and /markdoc.config.mjs has been created in the root directory.

//markdoc.config.mjs
import { defineMarkdocConfig, nodes, component } from '@astrojs/markdoc/config';

export default defineMarkdocConfig({
      nodes: {
            ...
            image: {
                  ...nodes.image, 
                  render: component('./src/components/markdoc/MarkdocImage.astro'),
            },
      },

Create src\components\markdoc\MarkdocImage.astro

//src\components\markdoc\MarkdocImage.astro
---
import type { ImageMetadata } from "astro";
import { Image } from "astro:assets";

interface Props {
  src: ImageMetadata | string;
  alt: string;
}

const { src, alt } = Astro.props;

const modes = ["full", "min"];
const parts = alt.split("|").map((s) => s.trim());
let mode = "";
let description = "";

if (parts.length > 1 && modes.includes(parts[0].toLowerCase())) {
  mode = parts[0].toLowerCase();
  description = parts.slice(1).join("|");
} else if (modes.includes(alt.trim().toLowerCase())) {
  mode = alt.trim().toLowerCase();
  description = "";
} else {
  mode = "default";
  description = alt;
}

let widthClass = "w-full";
if (mode === "full") {
  widthClass = "w-screen max-w-none relative left-1/2 -translate-x-1/2";
} else if (mode === "min") {
  widthClass = "w-full sm:max-w-[50%] mx-auto";
}
---

<figure class={`my-8 ${mode === "full" ? "" : "overflow-visible"}`}>
  {
    typeof src === "string" ? (
      <img
        src={src}
        alt={description || "image"}
        class={`block h-auto rounded-3xl ${widthClass}`}
      />
    ) : (
      <Image
        src={src}
        alt={description || "image"}
        class={`block h-auto rounded-3xl ${widthClass}`}
      />
    )
  }
  {
    description && (
      <figcaption class="mt-2 text-sm text-center opacity-75 not-prose font-bold">
        {description}
      </figcaption>
    )
  }
</figure>

Example #

This is a min-width image
This is a min-width image

This is a default-width image
This is a default-width image

This is a full-width image
This is a full-width image