Wertarbyte Logo

Blog mit Markdown in Next.js

In diesem Artikel beschreibe ich, wie ich einen Blogbereich zu unserer bestehenden Next.js-Homepage hinzugefügt habe. Dabei nutze ich Markdown-Dateien (MDX) zur Verwaltung der Blogposts. Dies erlaubt eine einfache und flexible Art, Inhalte zu erstellen und zu bearbeiten.

Wertarbyte Logo

Genutzte Pakete

Um MDX-Dateien in unsere Next.js-Anwendung zu integrieren, habe ich die folgenden Pakete verwendet:

Konfiguration von Next.js für MDX

In der next-config.mjs habe ich withMDX hinzugefügt, um die MDX-Integration zu konfigurieren.

code-snippet.ts


import createMDX from '@next/mdx' /** * @type {import('next').NextConfig} */ const nextConfig = { ... pageExtensions: ['mdx', 'md', 'tsx', 'ts'], ... }; const withMDX = createMDX({ // Add markdown plugins here, as desired }); export default withMDX(nextConfig);

Einrichtung der MDX-Komponenten

Zuerst habe ich eine Datei mdx-component.tsx erstellt, um benutzerdefinierte MDX-Komponenten zu definieren.

code-snippet.ts


import type { MDXComponents } from "mdx/types"; export function useMDXComponents(components: MDXComponents): MDXComponents { return { ...components, }; }

Dienstprogramme für MDX

In der Datei mdxUtils.ts habe ich Funktionen zum Verwalten der MDX-Dateien erstellt. Diese Funktionen helfen dabei, den Pfad zu den Posts zu bekommen und alle MDX-Dateien im Verzeichnis posts zu finden.

code-snippet.ts


/** * Useful when you want to get the path to a specific file */ export const POSTS_PATH = path.join(process.cwd(), "posts"); /** * The list of all mdx files inside the POSTS_PATH directory */ export const postFilePaths = fs .readdirSync(POSTS_PATH) // Only include md(x) files .filter((path) => /\.mdx?$/.test(path));

Übersichtseite für die Blogposts

In der Datei app/posts/page.tsx habe ich eine Übersichtsseite erstellt, die alle gefundenen Markdown-Artikel als Karten auflistet und zum Weiterlesen verlinkt.

code-snippet.ts


import { postFilePaths, POSTS_PATH } from "../../utils/mdxUtils.ts"; interface Post { filePath: string; data: { title: string; description: string; image: string; author: string; date: string; }; content: string; } function getData(): { posts: Post[] } { const posts = postFilePaths.map((filePath) => { const source = fs.readFileSync(path.join(POSTS_PATH, filePath)); const { content, data } = matter(source); return { content, data, filePath, } as Post; }); return { posts }; } const Posts: React.FC = () => { const { posts } = getData(); return ( <> ... <Box sx={{ display: "grid", gap: 4, gridTemplateColumns: { md: "1fr 1fr 1fr", sm: "1fr 1fr", xs: "1fr", }, }} > {posts .sort( (a, b) => new Date(b.data.date).getTime() - new Date(a.data.date).getTime(), ) .map((post) => ( <Link key={post.filePath} as={`/posts/${post.filePath.replace(/\.mdx?$/, "")}`} href={`/posts/[slug]`} style={{ textDecoration: "none", }} > ... </Link> ))} </Box> ... </> ); }; export default Posts;

Rendering der einzelnen Blogposts

Schließlich wird jeder Blogpost über die Datei app/posts/[slug]/page.tsx gerendert.

code-snippet.ts


import { MDXRemote } from "next-mdx-remote/rsc"; import { POSTS_PATH } from "../../../utils/mdxUtils.ts"; import matter from "gray-matter"; import type { MDXRemoteProps } from "next-mdx-remote/rsc"; const components: MDXRemoteProps["components"] = { h1: (props) => <Typography variant="h1">{props.children}</Typography>, h2: (props) => <Typography variant="h2">{props.children}</Typography>, h3: (props) => <Typography variant="h3">{props.children}</Typography>, h4: (props) => <Typography variant="h4">{props.children}</Typography>, p: (props) => ( <Typography variant="body1" gutterBottom> {props.children} </Typography> ), }; const Posts: React.FC<{ params: { slug: string } }> = ({ params: { slug }, }) => { const postFilePath = path.join(POSTS_PATH, `${slug}.mdx`); const source = fs.readFileSync(postFilePath); const { data } = matter(source); return ( <> <Hero title={data.title} subtitle={data.description} image={data.image} /> <Block> <MDXRemote components={components} source={source} options={{ parseFrontmatter: true, }} /> </Block> </> ); }; export default Posts;

Fazit

Mit dieser Implementierung können wir neue Blogposts hinzufügen und verwalten, indem wir einfach neue MDX-Dateien im posts Verzeichnis erstellen. Das System ermöglicht es uns, die Inhalte klar strukturiert und ansprechend zu präsentieren. Next.js bietet dabei die notwendige Flexibilität und Leistung, um auch größere Mengen an Inhalten effizient zu verwalten.

Copyright © 2024 Wertarbyte GmbH