Skip to content

Customizing rendering

<ArticleContent> renders standard HTML elements by default. Three escape hatches let you make it yours: override how an element renders (components), add Markdown/HTML processing (remarkPlugins / rehypePlugins), and style the output (className).

components is passed straight through to react-markdown. Keys are HTML tag names; values are the React components that render them. This is how you swap in a syntax highlighter, next/image, or a framework-aware link.

components map
import { ArticleContent } from "@ghostwritr/react";
import Image from "next/image";
import Link from "next/link";
import { CodeBlock } from "@/components/code-block"; // your shiki / prism wrapper
<ArticleContent
markdown={article.markdown}
components={{
code: CodeBlock,
img: (props) => <Image {...props} width={1200} height={630} />,
a: ({ href, children }) => <Link href={href ?? "#"}>{children}</Link>,
}}
/>;

remarkPlugins and rehypePlugins are appended after the built-ins — they don’t replace them. The effective pipelines are:

  • remark: remark-gfm → your remarkPlugins
  • rehype: rehype-sanitize → your rehypePlugins
append a rehype plugin
import rehypeSlug from "rehype-slug";
<ArticleContent markdown={article.markdown} rehypePlugins={[rehypeSlug]} />;

Set className to wrap the output in a single <div> and hang your typography styles off it. With Tailwind Typography:

Tailwind Typography
<ArticleContent
markdown={article.markdown}
className="prose dark:prose-invert max-w-none"
/>

Without className, there’s no wrapper element — the rendered Markdown sits directly in its parent. That’s the right choice when you’re supplying your own <article> wrapper and global styles.