npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@paragraphcms/parser-react

v0.4.0

Published

React renderer for Paragraph CMS content.

Downloads

23

Readme

@paragraphcms/parser-react

React renderer for Paragraph CMS content.

@paragraphcms/parser-react renders Paragraph CMS v1 content in React. It accepts full page objects or raw content, supports tiptap, markdown, and html, and ships with sensible defaults for styling, sanitization, and custom block rendering.

Quick Start

Install the renderer and its React peer dependencies:

npm install @paragraphcms/parser-react react react-dom

# Optional if you also fetch content with the official SDK
npm install @paragraphcms/client

Render a Paragraph page:

import { Client } from "@paragraphcms/client";
import { ParagraphContent } from "@paragraphcms/parser-react";

const client = new Client({
  apiKey: process.env.PARAGRAPH_API_KEY!,
});

const pages = await client.pages.list({
  slug: "home",
  language: "en",
  include_content: true,
  limit: 1,
});

const page = pages.data[0] ?? null;

export function PageContent() {
  if (!page?.content) {
    return null;
  }

  return <ParagraphContent page={page} />;
}

Render raw content directly:

import { ParagraphContent } from "@paragraphcms/parser-react";

export function MarketingBlurb() {
  return (
    <ParagraphContent
      content="# Hello from Paragraph"
      contentFormat="markdown"
    />
  );
}

Table of Contents

Requirements

  • react ^18.2.0 || ^19.0.0
  • react-dom ^18.2.0 || ^19.0.0

Features

  • Supports Paragraph CMS tiptap, plus direct markdown and html input.
  • Accepts either a full page object or raw content.
  • Tailwind-friendly default class names with an unstyled escape hatch.
  • Slot-level component overrides for links, images, tables, custom blocks, and task lists.
  • Built-in markdown parsing and HTML sanitization.
  • Paragraph-specific Tiptap support for faq, collapsible, hydrated images, tables, and task lists.

Installation

Install from npm:

npm install @paragraphcms/parser-react react react-dom

# Alternative package managers
pnpm add @paragraphcms/parser-react react react-dom
yarn add @paragraphcms/parser-react react react-dom

If you also fetch content from Paragraph CMS, install the official client separately:

npm install @paragraphcms/client

Rendering a Page

ParagraphContent accepts a page object with content and optional content_format:

import {
  ParagraphContent,
  type ParagraphRenderablePage,
} from "@paragraphcms/parser-react";

export function Article({
  page,
}: {
  page: ParagraphRenderablePage | null;
}) {
  return <ParagraphContent page={page} />;
}

If you fetch from the Paragraph API, make sure the payload actually includes content. For list endpoints, that means setting include_content: true. Detail endpoints already return the full page.

Rendering Raw Content

You can render content without a page wrapper by passing content and, optionally, contentFormat:

<ParagraphContent
  content="<h1>Hello</h1><p>Rendered as HTML</p>"
  contentFormat="html"
/>

Supported content formats:

  • tiptap
  • markdown
  • html

If contentFormat is omitted, the renderer infers it automatically:

  • Arrays are treated as tiptap.
  • Strings are checked for HTML tags and otherwise treated as markdown.

Rendering Options

The main component props look like this:

type ParagraphContentProps<TFields = Record<string, unknown>> =
  ParagraphRenderOptions & {
    as?: ElementType<HTMLAttributes<HTMLElement>>;
    className?: string;
    page?: ParagraphRenderablePage<TFields> | null;
    content?: ParagraphPageContent | null;
    contentFormat?: ParagraphContentFormat | null;
  };

Useful options:

  • as changes the root element. The default is article.
  • className applies to the root wrapper.
  • classNames overrides slot-level classes.
  • components replaces rendered elements with custom React components.
  • markedOptions customizes markdown parsing.
  • sanitizeOptions customizes HTML sanitization.
  • unstyled disables the built-in default classes.

Styling

The renderer ships with default class names designed to work well in Tailwind-based apps. You can extend or replace them slot by slot:

<ParagraphContent
  page={page}
  classNames={{
    root: "prose prose-slate max-w-none",
    h1: "font-serif text-5xl tracking-tight",
    h2: "mt-12 text-3xl font-semibold",
    img: "rounded-[2rem] border-0 shadow-2xl",
    faq: "not-prose rounded-[2rem] border border-slate-200 bg-white p-4",
    collapsible: "rounded-2xl border border-slate-200 bg-slate-50 p-2",
  }}
/>

If you want a zero-base render and plan to style everything yourself:

<ParagraphContent page={page} unstyled />

Overriding Components

Use components to replace any rendered slot with your own React component:

import Link from "next/link";

<ParagraphContent
  page={page}
  components={{
    a: ({ href, children, ...props }) => (
      <Link href={href ?? "#"} {...props}>
        {children}
      </Link>
    ),
    img: (props) => <img {...props} loading="eager" />,
    faq: ({ children, ...props }) => (
      <section {...props} data-ui="marketing-faq">
        {children}
      </section>
    ),
  }}
/>

Available slots:

  • root
  • p, h1, h2, h3, h4, h5, h6
  • a, strong, em, u, s
  • blockquote, code, pre
  • ul, ol, li, hr, br
  • img, figure, figcaption
  • tableWrapper, table, thead, tbody, tr, th, td
  • faq, collapsible, summary, collapsibleContent
  • taskList, taskItem, taskCheckbox

Lower-level Rendering

If you want rendered React nodes without the root wrapper, use renderParagraphContent() directly:

import { renderParagraphContent } from "@paragraphcms/parser-react";

const nodes = renderParagraphContent({
  content: "# Hello",
  contentFormat: "markdown",
  unstyled: true,
});

This is useful when you want to place rendered content inside your own layout component tree.

Exported Helpers and Types

The package exports:

  • ParagraphContent
  • renderParagraphContent
  • defaultParagraphClassNames
  • defaultParagraphMarkedOptions
  • defaultParagraphSanitizeOptions

It also exports the core type surface, including:

  • ParagraphContentProps
  • ParagraphRenderOptions
  • ParagraphContentFormat
  • ParagraphPageContent
  • ParagraphRenderablePage
  • ParagraphPage
  • ParagraphPageSummary
  • ParagraphComponents
  • ParagraphClassNames
  • ParagraphTiptapNode

Notes

  • ParagraphContent returns null if content is missing.
  • If you fetch page lists from the API, include content explicitly with include_content: true.
  • Tiptap images returned by Paragraph CMS are hydrated with a public src; alt is rendered on <img> and caption as <figcaption>.
  • Markdown and HTML input are sanitized before rendering. You can customize that behavior with sanitizeOptions.

License

MIT