Developer
Get Support
Sign in
Get Support
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
Sign in
DOCUMENTATION
Cloud
Data Center
Resources
Sign in
UI Kit components
Jira UI Kit components
UI Kit hooks
Forge bridge APIs
Jira bridge APIs
Confluence bridge APIs
Dashboard bridge APIs (EAP)
Upgrade UI Kit versions
Last updated Jan 19, 2026

ADF renderer

To add the AdfRenderer component to your app:

1
2
import { AdfRenderer } from "@forge/react";

Description

The AdfRenderer component provides a way to render a valid ADF document, using the same renderer that Atlassian uses internally to render ADF content in Confluence pages, Jira work items, and so on. It allows you to replace node types that are unsupported in the context of a Forge app with replacement content, or remove them entirely. See Atlassian Document Format for information on valid nodes.

This component uses @atlaskit/renderer under the hood.

Visit Renderer editor for a comprehensive list of different ADF document examples.

Accessibility considerations

When using the replaceUnsupportedNode prop you will need to ensure that any content is replaced with accessible content. This content needs to be clear to the user it has been replaced. Including an explanation as to why the content is replaced can also be useful. Read more about Readable content (as per WCAG success criterion)

This helps users who use:

  • Screen readers
  • Braille display
  • Text-to-speech technology

Props

See @atlaskit/renderer for the full list of props supported by the underlying component.

Unsupported node types

Node typeSupportDetails
mediaPartialOnly supports media hosted by Atlassian when used in a Confluence macro module. You can identify Atlassian hosted `media` nodes as they have an attrs.id property, instead of attrs.url
emojiPartialOnly standard Unicode emoji are supported, not custom user-provided emoji

bodiedExtension

NoneAll types of Forge macros are supported, except for Forge bodied macros; see Rendering a UI Kit bodied macro for the new EAP feature. However, core Confluence macros and Connect macros are not supported.

Examples

Rendering a UI Kit bodied macro

The AdfRenderer component now supports rendering embedded Forge Custom UI and UI Kit apps as an Early Access Program (EAP). To start testing this feature, sign up using this form.

By signing up for this Early Access Program (“EAP”), you acknowledge that use of the Forge embedded macros is governed by the Atlassian Developer Terms. Forge embedded macros are considered “Early Access Materials”, as set forth in Section 12 of the Atlassian Developer Terms and is subject to applicable terms, conditions, and disclaimers.

APIs and features under EAP are unsupported and subject to change without notice. APIs and features under EAP are not recommended for use in production environments.

For more details, see Forge EAP, Preview, and GA.

This demonstrates how to render the contents of a UI Kit bodied macro, including bodied macros that contain embedded UI Kit or Custom UI Forge apps. For Custom UI bodied macros, see createAdfRendererIframeProps.

Prerequisites:

  • Your app must be a Confluence bodied macro with layout:bodied enabled in the macro module properties of the manifest file.

  • This approach is for UI Kit apps only. For Custom UI, use view.createAdfRendererIframeProps instead.

Screenshot showing a UI Kit bodied macro with "Hello world!" text above and below the rendered macro body content

1
2
import React from "react";
import ForgeReconciler, {
  Text,
  useProductContext,
  AdfRenderer,
} from "@forge/react";

const App = () => {
  const context = useProductContext();
  const macroBody = context?.extension?.macro?.body;
  return (
    <>
      <Text>Hello world!</Text>
      <Text>Macro body below</Text>
      {macroBody ? (
        <AdfRenderer document={macroBody} />
      ) : (
        <Text>loading macro content...</Text>
      )}
      <Text>Macro body above</Text>
    </>
  );
};
ForgeReconciler.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

If the UI Kit bodied macro contains multiple Forge embedded macro apps, you can optionally split it up and pass it to multiple <AdfRenderer document={macroBody} /> instances.

See limitations and supported bridge methods for rendering embedded UI Kit or Custom UI Forge apps.

Basic text rendering

This demonstrates how a simple ADF document is rendered.

Example image of a rendered valid basic ADF document

1
2
import { AdfRenderer } from "@forge/react";

export const AdfRendererBasicExample = () => {
  const simpleDocumentToRender = {
    type: "doc",
    version: 1,
    content: [
      {
        type: "paragraph",
        content: [
          {
            type: "text",
            text: "This is a simple text example",
          },
        ],
      },
    ],
  };

  return <AdfRenderer document={simpleDocumentToRender} />;
};

Rendering unsupported content

This demonstrates how unsupported content might render by default, without any explicit replacement logic defined.

Example image of a rendered valid ADF document with unsupported content

1
2
import { AdfRenderer } from "@forge/react";

export const AdfRendererUnsupportedExample = () => {
  const simpleDocumentToRender = {
    type: "doc",
    version: 1,
    content: [
      {
        type: "paragraph",
        content: [
          {
            type: "emoji",
            attrs: {
              shortName: ":custom-emoji-hello:",
              id: "1e35b00f-cb17-4d28-91a5-ad38700715ae",
              text: ":hello!:",
            },
          },
        ],
      },
    ],
  };

  return <AdfRenderer document={simpleDocumentToRender} />;
};

Replacing unsupported content

This demonstrates a simple replacement function that just replaces unsupported content with a paragraph.

Example image of a rendered valid ADF document with unsupported content replaced

1
2
import { AdfRenderer } from "@forge/react";

export const AdfRendererUnsupportedContentExample = () => {
  const replaceUnsupportedNode = (node) => {
    return {
      type: "paragraph",
      content: [
        {
          type: "text",
          text: `Unsupported content: ${node.type}`,
        },
      ],
    };
  };

  const simpleDocumentToRender = {
    type: "doc",
    version: 1,
    content: [
      {
        type: "paragraph",
        content: [
          {
            type: "emoji",
            attrs: {
              shortName: ":custom-emoji-hello:",
              id: "1e35b00f-cb17-4d28-91a5-ad38700715ae",
              text: ":hello!:",
            },
          },
        ],
      },
    ],
  };

  return (
    <AdfRenderer
      document={simpleDocumentToRender}
      replaceUnsupportedNode={replaceUnsupportedNode}
    />
  );
};

Replacing multiple content types

This demonstrates a more complex replacement function that either replaces content, removes it, and or leaves it as-is, depending on the node type.

Example image of a rendered valid ADF document with unsupported content replaced

1
2
import { AdfRenderer } from "@forge/react";

export const AdfRendererMultipleContentTypesExample = () => {
  const replaceUnsupportedNode = (node) => {
    if (node.type.toLowerCase().includes("extension")) {
      // Show a message for all extension node types
      return {
        type: "paragraph",
        content: [
          {
            type: "text",
            text: "Unsupported macro",
          },
        ],
      };
    } else if (node.type === "emoji") {
      // Show the emoji's default textual representation as-is
      return undefined;
    }

    // Hide everything else
    return false;
  };

  const simpleDocumentToRender = {
    type: "doc",
    version: 1,
    content: [
      {
        type: "paragraph",
        content: [
          {
            type: "emoji",
            attrs: {
              shortName: ":custom-emoji-hello:",
              id: "1e35b00f-cb17-4d28-91a5-ad38700715ae",
              text: ":hello!:",
            },
          },
          {
            type: "bodiedExtension",
            attrs: {
              extensionType: "com.atlassian.fabric",
              extensionKey: "clock",
            },
            content: [
              {
                type: "paragraph",
                content: [
                  {
                    type: "text",
                    text: "This is the default content of the extension",
                  },
                ],
              },
            ],
          },
        ],
      },
    ],
  };

  return (
    <AdfRenderer
      document={simpleDocumentToRender}
      replaceUnsupportedNode={replaceUnsupportedNode}
    />
  );
};

Rate this page: