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

react-markdown-remote

v2.0.0

Published

Fetch a markdown file from a URL and render it in React, with relative images and links resolved against the source document.

Readme

react-markdown-remote

npm types license

Fetch a markdown file from a URL and render it in React. Relative images and links resolve against that file, not against the page you dropped the component on.

This is the successor to react-markdown-to-html (2015). That package dumped marked HTML through dangerouslySetInnerHTML. This one does not. Parsing is react-markdown. The thing react-markdown does not do — load a document and rewrite its assets — is the whole API.

import { RemoteMarkdown } from "react-markdown-remote";
import "react-markdown-remote/styles.css"; // optional typography

<RemoteMarkdown src="https://github.com/acme/app/blob/main/docs/guide.md" />
npm install react-markdown-remote

Peer dependency: react >= 18.

Why this exists

react-markdown takes a string. You still have to fetch it, and then this happens:

![diagram](./images/flow.png)
[API](./api.md)

Those paths are relative to the markdown file. On GitHub they work. In your app they 404, because the browser resolves them against the current page. GitHub blob URLs also cannot be used as img src — you need raw.githubusercontent.com for images and github.com/.../blob/... for links.

| You have | Use | | --- | --- | | A markdown string already in memory | react-markdown | | A file at a URL, with ./ images and links | react-markdown-remote | | JSX inside markdown | MDX |

What src accepts

| src | Fetches from | ./shot.png becomes | | --- | --- | --- | | https://github.com/org/repo/blob/main/docs/guide.md | raw.githubusercontent.com/.../docs/guide.md | raw image URL under docs/ | | https://github.com/org/repo | README.md on HEAD | raw image at repo root | | https://github.com/org/repo/tree/main/docs | docs/README.md | raw image under docs/ | | https://gitlab.com/group/app/-/blob/main/README.md | GitLab /-/raw/ | GitLab raw image | | https://gist.github.com/user/id | gist.githubusercontent.com/.../raw | gist raw | | https://example.com/docs/guide.md | that URL | https://example.com/docs/shot.png | | /docs/README.md | same origin (browser) | same-origin relative to the file |

On GitHub and GitLab, a path that starts with / is the repo root, matching how those hosts render README files. On a generic URL it is the host root.

Branches with slashes: use the refs/heads/ form, e.g. .../blob/refs/heads/feature/foo/README.md.

Relative rewrite

import { resolveDocument, rewriteUrl } from "react-markdown-remote";

const doc = resolveDocument("https://github.com/acme/app/blob/main/docs/guide.md");
rewriteUrl("./shot.png", doc, "image");
// https://raw.githubusercontent.com/acme/app/main/docs/shot.png
rewriteUrl("./extra.md", doc, "link");
// https://github.com/acme/app/blob/main/docs/extra.md

javascript:, data:, vbscript:, and file: URLs are dropped. Absolute http(s) links are left alone. GitHub blob URLs used as images are converted to raw.

The component is a thin fetch + this rewrite + react-markdown. You can call loadMarkdown(src) on the server and render with your own pipeline.

API

<RemoteMarkdown
  src="https://github.com/org/repo/blob/main/README.md"
  loading={<p>Loading…</p>}
  error={(err) => <p>{err.message}</p>}
  onLoad={({ markdown, document }) => console.log(document.fetchUrl)}
  components={{ a: (props) => <a {...props} target="_blank" /> }}
/>

| Prop | Type | Default | Notes | | --- | --- | --- | --- | | src | string | required | Document URL | | fetch | typeof fetch | globalThis.fetch | Use a proxy for hosts without CORS. Keep src as the real document URL | | requestInit | RequestInit | — | Merged into the request (signal is owned by the component) | | gfm | boolean | true | remark-gfm (tables, task lists, strikethrough) | | loading | ReactNode | status text | null hides it | | error | ReactNode | (Error) => ReactNode | alert with message | null hides it | | onLoad | (result) => void | — | Markdown string + resolved document | | onError | (Error) => void | — | Not called for aborted fetches | | origin | string | window.location.href | Base for relative src |

All react-markdown options except children are forwarded (components, remarkPlugins, rehypePlugins, urlTransform, …). Your urlTransform runs after the relative rewrite, then defaultUrlTransform sanitizes.

Hooks and headless helpers:

import {
  useRemoteMarkdown,
  loadMarkdown,
  resolveDocument,
  rewriteUrl,
} from "react-markdown-remote";

"use client" is prepended to the build for Next.js App Router.

CORS

raw.githubusercontent.com sends Access-Control-Allow-Origin: *. Many other hosts do not. If the browser blocks the request, pass fetch that hits your own proxy, and leave src pointing at the real file so rewrite still has the right base.

Do not enable rehype-raw unless you sanitize. Untrusted markdown is safe by default because this package never uses dangerouslySetInnerHTML and does not parse raw HTML.

Demo

npm install
npm run demo

Opens http://localhost:5173 with a local fixture (relative image + link) and a GitHub README preset.

Migration from react-markdown-to-html

- import Markdown2HTML from "react-markdown-to-html"
- <Markdown2HTML src="README.md" />
+ import { RemoteMarkdown } from "react-markdown-remote"
+ <RemoteMarkdown src="https://github.com/org/repo/blob/main/README.md" />
  • React 18+ is required (createClass is gone)
  • jQuery, lodash, and marked are gone
  • Output is React elements, not HTML strings
  • A bare README.md only works if that file is served from the current origin

The old package name react-markdown-to-html is abandoned. Prefer npm deprecate on it.

License

ISC