Transform your MDX content into typed, JSON-powered data with flexible schema validation.
npm install mdxlayermdxlayerTransform your .mdx content into strongly typed, structured JSON and TypeScript declarations with minimal config. Built for performance, flexibility, and DX.
- š§ Validates frontmatter with Tyne
- ā” Generates structured .json and .d.ts from .mdx content
- š Add computed fields with resolvedFields
- š Language-based content grouping (en, es, all)
- š Watch mode for development
- ā
Type-safe at every level
- š¦ Simple CLI: mdxlayer build & mdxlayer dev
- Node.js 18+ (ESM only)
- mdxlayer installed globally or locally
- MDX files must follow this rule: no spaces in filenames
ā
about.mdx
ā about me.mdx
``bash`
pnpm add -D mdxlayeror
npm install -D mdxlayeror
yarn add -D mdxlayer
Create a mdxlayer.config.ts file:
`ts
import { defineConfig } from 'mdxlayer';
import { t } from 'tyne';
const ArticleSchema = t.object({
title: t.string(),
category: t.string(),
subcategory: t.string(),
publishedTime: t.string(),
modifiedTime: t.string(),
description: t.string(),
authors: t.array(t.string()),
avatar: t.string(),
cover: t.string(),
coverAlt: t.string(),
check: t.boolean(),
lang: t.string(),
tags: t.array(t.string()),
});
export default defineConfig({
docType: 'Articles',
contentDir: 'content',
frontmatterSchema: ArticleSchema,
resolvedFields: {
title_: { resolve: (doc) => doc.title, type: t.string() },
slug: {
resolve: (doc) => doc.file.replace(/\.mdx$/, ''),
type: t.string(),
},
},
});
`
Update your tsconfig.json:
`json`
{
"compilerOptions": {
"paths": {
"mdxlayer/generated": ["./.mdxlayer/generated"]
}
},
"include": ["./.mdxlayer/generated"]
}
File`mdx
---
title: 'What Makes MDX Powerful'
category: 'tech'
subcategory: 'markdown'
publishedTime: '01-04-2025'
modifiedTime: '01-04-2025'
description: 'A deep dive into what makes MDX a game-changer for modern content.'
authors: ['Estarlincito']
avatar: '/assets/avatar.jpeg'
cover: '/covers/mdx.png'
coverAlt: 'MDX visual cover'
check: true
lang: 'en'
tags: ['mdx', 'content', 'markdown']
---
Hello!
> Lorem ipsum dolor sit amet, consectetur adipiscing elit.
> _"MDX is where content meets interactivity."_
> ā Anonymous
`
`ts
import { esArticles, enArticles, allArticles } from 'mdxlayer/generated';
console.log(esArticles);
console.log(enArticles);
console.log(allArticles);
`
`bash
pnpm mdxlayer buildGenerate static JSON and index.d.ts
pnpm mdxlayer dev
pnpm mdxlayer build --config docs.config.js
mdxlayer build --config docs.config.js --out docs-content
and output to docs-content/š Folder Structure
`
content/
āāā what-makes-mdx-powerful.mdx
`š Output Structure
`
.mdxlayer/
āāā cache/
ā āāā compiled-config.js
ā āāā compiled-config.js.map
ā āāā data.json
āāā generated/
ā āāā Articles/
ā ā āāā what-makes-mdx-powerful.json
ā āāā types.d.ts
ā āāā index.d.ts
ā āāā index.js
āāā package.json
`Plugins
next-mdxlayerš¦ Installation
`bash
pnpm add -D next-mdxlayer
or
npm install -D next-mdxlayer
or
yarn add -D next-mdxlayer
`āļø Configuration
`ts
import { withMdxlayer } from 'next-mdxlayer';/* @type {import('next').NextConfig} /
const nextConfig = {
reactStrictMode: true,
pageExtensions: ['js', 'ts', 'jsx', 'tsx', 'mdx'],
experimental: {
serverActions: true,
},
};
export default withMdxlayer(nextConfig);
``ts
import { useMDXComponent } from 'next-mdxlayer/hook';
import { allServices } from 'mdxlayer/generated';
import MyAudioComponent from './audio'
import MyIntroComponent from './intro'
export default function MyPage() {
const MDXComponent = useMDXComponent(allServices[0]._body.code);
return (
components={{
a: (props) => ,
img: (props) =>
,
Audio: MyAudioComponent,
Introduction: MyIntroComponent,
}}
/>
);
}
`š© API
$3
Accepts the following shape:
`ts
interface Config {
name: string;
contentDir: string;
frontmatterSchema: TyneType;
resolvedFields?: Record<
string,
{ resolve: (doc: Doc) => any | Promise }
>;
}
`$3
`ts
interface Doc {
_filePath: string;
_id: string;
_body: { raw: string; code: string };
// + fields from your frontmatterSchema
}
``This project is licensed under the MIT License ā see the LICENSE file for details.
Author: Estarlin R (estarlincito.com)