Markdownlayer is a content SDK that validates and transforms your content into type-safe JSON data you can easily import
into your application's pages. If you have used Contentlayer, this is built to replace it.
Explore the example projects, which you can clone to try out locally.
Read the blog for more insights.
- Live Reload: Automatically reloads on content changes.
- Fast and Incremental Builds: Efficiently builds only the changed content.
- Schema Validation: Design and validate schemas using
zod
. - TypeScript Support: Auto-generates TypeScript types based on definition schema.
- Remark Plugins: Includes Remark GFM, Admonitions, Reading Time, Emoji, and Slug by default.
- Markdoc Support: Integrates with Markdoc for advanced content processing.
- Git Integration: Tracks last update time and author based on Git, with the option to override via frontmatter.
- Turbopack Support: Compatible with Turbopack for faster builds.
- Image Support: Image references in frontmatter using custom image schema with support for
alt
.
- The content type is inferred from the extension hence markdown is processed correctly and not forced into MDX.
- Only local content.
- Only NextJs support.
- No JSON/YAML content as they can be loaded directly into the JS/TS code.
- Requires ESM because the whole unified/remark/rehype ecosystem moved to ESM-only.
These are in no particular order and depend on how much free time I have.
- Conversion of link elements from
a
to NextJS'sLink
component. - Conversion of image elements from
img
to NextJS'sImage
component. - Relative links in markdown content.
- Backward support for CJS by using dynamic imports.
- Collecting images and other files from markdown/MDX/Markdoc files.
To install Markdownlayer, use your preferred package manager:
npm install markdownlayer
# or
yarn add markdownlayer
# or
pnpm add markdownlayer
Here is a basic example of how to use Markdownlayer in your project:
import { defineConfig, z } from 'markdownlayer';
export default defineConfig({
contentDirPath: './src/content',
definitions: {
blog: {
schema: ({ body, slug }) =>
z.object({
title: z.string(),
slug: slug(),
body: body(),
}),
},
},
});