Next.js Discord

Discord Forum

Trouble stripping frontmatter from mdx

Answered
Gray-tailed Tattler posted this in #help-forum
Open in Discord
Gray-tailed TattlerOP
Here is my dynamic route page at /app/blog/[slug]/page.tsx. My mdx files are at the project root -> /markdown/
import fs from "node:fs";
import path from "node:path";
import matter from "gray-matter";
import { notFound } from "next/navigation";
import Container from "@/components/layout/container"

export const dynamicParams = false;

export function generateStaticParams() {
  const dir = path.join(process.cwd(), "markdown");
  return fs
    .readdirSync(dir)
    .filter((f) => f.endsWith(".mdx"))
    .map((f) => ({ slug: f.replace(/\.mdx$/, "") }));
}

export default async function Page({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;

  const filePath = path.join(process.cwd(), "markdown", `${slug}.mdx`);

  if (!fs.existsSync(filePath)) notFound();

  const raw = fs.readFileSync(filePath, "utf8");
  const { data } = matter(raw); // <-- frontmatter parsed here

  // Render MDX via import (frontmatter stays ignored by MDX, but we already extracted it)
  const { default: Post } = await import(`@/markdown/${slug}.mdx`);

  return (
    <section>
      <Container>
        <article className="prose mx-auto">
          <h1>{String(data.title ?? slug)}</h1>
          {data.date ? <p className="text-sm opacity-70">{String(data.date)}</p> : null}
          <Post />
        </article>
      </Container>

    </section>
  );
}

It renders everything but <Post /> also renders the frontmatter. I thought matter was stripping it but it looks like it's just reading it.
Answered by Gray-tailed Tattler
ah this works
  const raw = fs.readFileSync(filePath, "utf8");
  const { data, content } = matter(raw);

  return (
    <section className="py-14 sm:py-20">
      <Container>
        <article className="prose mx-auto">
          <h1>{String(data.title ?? slug)}</h1>
          {data.date ? <p className="text-sm opacity-70">{String(data.date)}</p> : null}
          <MDXRemote source={content} />
        </article>
      </Container>
    </section>
  );
View full answer

1 Reply

Gray-tailed TattlerOP
ah this works
  const raw = fs.readFileSync(filePath, "utf8");
  const { data, content } = matter(raw);

  return (
    <section className="py-14 sm:py-20">
      <Container>
        <article className="prose mx-auto">
          <h1>{String(data.title ?? slug)}</h1>
          {data.date ? <p className="text-sm opacity-70">{String(data.date)}</p> : null}
          <MDXRemote source={content} />
        </article>
      </Container>
    </section>
  );
Answer