Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why Content Collection considers the meta data ( title and description ) as part of the body? #489

Open
alamenai opened this issue Feb 7, 2025 · 1 comment

Comments

@alamenai
Copy link

alamenai commented Feb 7, 2025

Hi @sdorra ,

I have this content collection configuration:

import {
  createDefaultImport,
  defineCollection,
  defineConfig,
} from "@content-collections/core"

import { MDXContent } from "mdx/types"

// Collection for MDX files directly inside docs
const docs = defineCollection({
  name: "docs",
  directory: "docs",
  include: "*.mdx",
  exclude: "components/**/*.mdx", // Exclude files already handled by the components collection
  parser: "frontmatter",
  schema: (z) => ({
    title: z.string(),
    description: z.string(),
  }),
  transform: ({ _meta, title, description, ...post }) => {
    const mdx = createDefaultImport<MDXContent>(`@/docs/${_meta.filePath}`)
    return {
      title,
      description,
      ...post,
      _meta,
      mdx,
    }
  },
})

// Collection for components inside docs/components
const components = defineCollection({
  name: "components",
  directory: "docs/components",
  include: "*.mdx",
  parser: "frontmatter",
  schema: (z) => ({
    title: z.string(),
    description: z.string(),
  }),
  transform: ({ _meta, title, description, ...post }) => {
    const mdx = createDefaultImport<MDXContent>(
      `@/docs/components/${_meta.filePath}`
    )
    return {
      title,
      description,
      ...post,
      _meta,
      mdx,
    }
  },
})

export default defineConfig({
  collections: [components, docs],
})

I have this MDX file:

---
title: Month Slider
description: Intuitive component that allows users to seamlessly select and navigate through months using a sliding interface, ideal for calendars, scheduling, and financial tracking.
---

import { MonthSlider } from "@/components/vibrant/month-slider.tsx"

import { Badge } from "@/components/ui/badge.tsx"
import Link from "next/link"
import { Terminal } from "lucide-react"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { ComponentPreview } from "@/components/core/component-preview.tsx"
import { ComponentSource } from "@/components/core/component-source.tsx"

import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"

<h1 className="font-bold text-3xl"> Month Slider </h1>
<h2 className="text-slate-500 mt-1 text-lg">
  Intuitive component that allows users to seamlessly select and navigate
  through months using a sliding interface, ideal for calendars, scheduling, and
  financial tracking.
</h2>

<Tabs defaultValue="preview" className="mt-8">
  <TabsList>
    <TabsTrigger value="preview" className="w-32">
      Preview
    </TabsTrigger>
    <TabsTrigger value="source" className="w-32">
      Code
    </TabsTrigger>
  </TabsList>
  <TabsContent value="preview" className="pt-2">
    <ComponentPreview>
      <MonthSlider />
    </ComponentPreview>
  </TabsContent>
  <TabsContent value="source">
    <ComponentSource source="month-slider.tsx" />
  </TabsContent>
</Tabs>

I display the MDX file from this component:

"use client"

import { allComponents } from "@/.content-collections/generated"
import { Button } from "@/components/ui/button"
import { ArrowLeft, ArrowRight } from "lucide-react"
import { notFound, useParams, useRouter } from "next/navigation"

export const ComponentDoc = () => {
  const params = useParams()
  const router = useRouter()

  // Find the component based on the slug from the URL
  const currentIndex = allComponents.findIndex(
    (post) => post._meta.path === params.slug
  )
  const post = allComponents[currentIndex]

  // Handle case where component is not found
  if (!post) {
    return notFound()
  }

  // Navigate to the next component
  const goToNext = () => {
    const nextIndex = currentIndex + 1
    if (nextIndex < allComponents.length) {
      router.push(`/docs/components/${allComponents[nextIndex]._meta.path}`)
    }
  }

  // Navigate to the previous component
  const goToPrevious = () => {
    const prevIndex = currentIndex - 1
    if (prevIndex >= 0) {
      router.push(`/docs/components/${allComponents[prevIndex]._meta.path}`)
    }
  }

  return (
    <article>
      <post.mdx />
      <div className="w-full flex justify-between mt-5">
        <div>
          {currentIndex > 0 && (
            <Button
              variant="outline"
              className="rounded-full"
              onClick={goToPrevious}
            >
              <ArrowLeft />
              Previous
            </Button>
          )}
        </div>

        <div>
          {currentIndex < allComponents.length - 1 && (
            <Button
              variant="outline"
              className="rounded-full"
              onClick={goToNext}
            >
              Next
              <ArrowRight />
            </Button>
          )}
        </div>
      </div>
    </article>
  )
}

I noticed that the title and description are considered as a part of the body:

Image

@sdorra
Copy link
Owner

sdorra commented Feb 8, 2025

This is not a problem of Content Collections. You are using next-mdx to render your mdx, which seems not to remove the frontmatter. Please check the configuration section of the next-mdx-static-import, which configures two remark plugins to remove the frontmatter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants