Skip to content

bisw4sh/mdx-blogs

Repository files navigation

Blog website with mdx

Getting Started

Install dependencies:

  1. Terminal 1
pnpm i && pnpm dev
  1. Terminal 2
cd backend && pnpm i && pnpm dev

Understanding the use of mdx with toolset

  1. We need to configure @mdx-js/rollup , this could be different for different toolset(i'm using vite; which uses rollup for production build).
//vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import mdx from "@mdx-js/rollup";

export default defineConfig(async () => {
  return {
    plugins: [react(), mdx()],
  };
});
  1. We need the provider of MDX to wrap the app to apply the imported *.mdx
//App.ts
import { MDXProvider } from "@mdx-js/react";

function App() {
  return (
    <>
      <MDXProvider>
        <TestMarkdown />
      </MDXProvider>
    </>
  );
}

export default App;

Note: This doesnot support code higlighting and table; we need rehype-highlight, remark-gfm respectively for that

  1. Add remark-gfm, (Github flavored markdown) .
//vite.config.ts
import remarkGfm from "remark-gfm";

export default defineConfig(async () => {
  return {
    plugins: [
      react(),
      mdx({
        remarkPlugins: [remarkGfm],
      }),
    ],
  };
});
  1. Now to add code block syntax highlighting, it could be done in 2 ways; runtime and compile time.
  • Compile time : we need rehype guide.

  • Run time : react-syntax-highlighter

  • For react-syntax-highlighter

interface CodeProps {
  className?: string;
  children?: React.ReactNode;
}

// Custom syntax highlighting component
function CodeBlock({ className, children, ...props }: CodeProps) {
  const match = /language-(\w+)/.exec(className || "");
  return match ? (
    <SyntaxHighlighter
      language={match[1]}
      PreTag="div"
      {...props}
      style={atelierCaveDark}
      showLineNumbers
    >
      {String(children).trim()}
    </SyntaxHighlighter>
  ) : (
    <code className={className} {...props}>
      {children}
    </code>
  );
}
<BlogComponent components={{ code: CodeBlock }} />

Above guide is to have syntax highlighting(runtime), gfm, mdx in react.

MDX from node.js (remote location)

  • We need to evaluate the markdown at runtime, could be done with showdown in nodejs backend. We could also use mdx-bundler by Kent C. Dodds. We can now use same files for frontend & backend.

  • Backend

const filePath = path.join(
  __dirname,
  "public",
  "mdx-files",
  `${req.params.slug}.mdx`
);
const mdxContent = readFileSync(filePath, "utf-8");

const { code, frontmatter } = await bundleMDX({
  source: mdxContent,
  mdxOptions(options) {
    options.remarkPlugins = [...(options.remarkPlugins ?? []), remarkGfm];
    options.development = false;
    return options;
  },
});

res.json({ code, frontmatter });
  • Frontend
const MDXContent = useMemo(() => {
  if (fetchedPost?.code) {
    try {
      // This evaluates the code and returns a React component
      return getMDXComponent(fetchedPost.code);
    } catch (error) {
      console.error("Error creating MDX component:", error);
      return null;
    }
  }
  return null;
}, [fetchedPost]);
<MDXContent components={{ code: CodeBlock }} />