Content Management with MDX and Velite

Learn how to build a type-safe content management system using MDX and Velite

mdxvelitecontenttypescript

What is MDX?

MDX is a format that lets you write JSX directly in your markdown files. This means you can import and use React components within your content!

import { CustomComponent } from './components'

# My Blog Post

Here's some regular markdown content.

<CustomComponent>
  And here's a React component!
</CustomComponent>

Why Velite?

Velite is a build-time content processor that gives you:

  • Type safety with Zod schemas
  • Auto-generated TypeScript types for your content
  • Build-time validation to catch errors early
  • MDX support out of the box

Velite processes your content during the build step, so there's no runtime overhead!

Setting Up Velite

First, install the required packages:

npm install velite zod

Then create a velite.config.ts file:

import { defineConfig, defineCollection, s } from 'velite'

const posts = defineCollection({
  name: 'Post',
  pattern: 'blog/**/*.mdx',
  schema: s.object({
    title: s.string(),
    description: s.string(),
    date: s.isodate(),
    tags: s.array(s.string()).default([]),
    body: s.mdx(),
  }),
})

export default defineConfig({
  collections: { posts },
})

Using Your Content

Once Velite processes your content, you can import it with full type safety:

import { posts } from '.velite'

export default function BlogPage() {
  return (
    <div>
      {posts.map((post) => (
        <article key={post.title}>
          <h2>{post.title}</h2>
          <p>{post.description}</p>
          <time>{post.date}</time>
        </article>
      ))}
    </div>
  )
}

TypeScript will know the exact shape of your content, giving you autocomplete and type checking!

Custom MDX Components

You can provide custom components to all your MDX files:

export function useMDXComponents(components) {
  return {
    Callout: MyCalloutComponent,
    CodeBlock: MyCodeBlockComponent,
    ...components,
  }
}

Conclusion

MDX + Velite provides a powerful, type-safe way to manage content in your Next.js application. It combines the simplicity of markdown with the power of React components.