Simple and type-safe Markdown/MDX content management tool for Next.js App Router.
.
├── content
│ ├── author
│ ├── post
│ └── categories.yml
├── public
│ └── assets
├── src
│ ├── app
│ └── content
├── next.config.mjs
├── package.json
└── tsconfig.jsoncontent/author: Directory where author data are storedcontent/post: Directory where Markdown/MDX contents are storedcontent/categories.yml: Filepath where categories data is storedsrc/content/index.ts: Content definition file
You can change the location of stored content and data definitions as you like.
npm install @cieloazul310/registaand install peer dependencies.
npm install --save-dev @mdx-js/mdxIf you are using @next/mdx, the above process is not necessary as @mdx-js/loader already has @mdx-js/mdx as a dependency.
// src/content.index.ts
import * as path from "path";
import { z, defineMdx } from "@cieloazul310/regista";
export const post = defineMdx({
contentPath: path.resolve(process.cwd(), "content/post"),
basePath: "/post",
schema: {
author: z.string().optional(),
},
});
export type PostFrontmatter = z.infer<typeof post.schema>;
export type PostMetadata = z.infer<typeof post.metadataSchema>;// src/app/post/[...slug].tsx
import NextLink from "next/link";
import type { Metadata } from "next";
import { post } from "@/content";
export async function generateStaticParams() {
const allPosts = await post.getAll(); // => PostMetadata[]
return allPosts;
}
async function Page({ params }: { params: Promise<{ slug: string[] }> }) {
const { slug } = await params;
const item = await post.useMdx(slug);
if (!item) return null;
const { content, frontmatter, context } = item;
const { title, date, lastmod, author } = frontmatter;
const { older, newer } = context;
return (
<>
<article>
<header>
<h1>{title}</h1>
<small>
<time>{date.toDateString()}</time>
</small>
</header>
<section>{content}</section>
</article>
<nav>
{older && (
<div>
<p>Older post</p>
<NextLink href={older.href}>{older.frontmatter.title}</NextLink>
</div>
)}
{newer && (
<div>
<p>Newer post</p>
<NextLink href={newer.href}>{newer.frontmatter.title}</NextLink>
</div>
)}
</nav>
</>
);
}
export default Page;Dynamic Routes https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes
Default usage
https://cieloazul310.github.io/regista
With data example (without mdx)
https://regista-with-data.vercel.app
npm install --save-dev @mdx-js/mdxIf you are using @next/mdx, the above process is not necessary as @mdx-js/loader already has @mdx-js/mdx as a dependency.
const item = await post.useMdx(slug, {
components,
- options: {
- mdxOptions: {
- remarkPlugins: [],
- rehypePlugins: [],
- },
- },
+ mdxOptions: {
+ remarkPlugins: [],
+ rehypePlugins: [],
+ },
});