Documentation

Blog and Static Pages

Learn how to use Content Collections for managing blog posts and static MDX content in your directory website.

Dirstarter uses Content Collections for managing blog posts and static MDX content. This system provides a type-safe way to handle markdown content with frontmatter validation and MDX support.

Configuration

The core configuration is defined in content-collections.ts:

content-collections.ts
import { defineCollection, defineConfig } from "@content-collections/core"
import { type Options, compileMDX } from "@content-collections/mdx"
import rehypeAutolinkHeadings from "rehype-autolink-headings"
import rehypeSlug from "rehype-slug"
 
const mdxOptions: Options = {
  rehypePlugins: [rehypeSlug, rehypeAutolinkHeadings],
}
 
const posts = defineCollection({
  name: "posts",
  directory: "content/posts",
  include: "**/*.md",
  schema: z => ({
    title: z.string(),
    description: z.string(),
    image: z.string().optional(),
    publishedAt: z.string(),
    updatedAt: z.string().optional(),
    author: z
      .object({
        name: z.string(),
        image: z.string(),
        twitterHandle: z.string(),
      })
      .optional(),
  }),
  transform: async (data, context) => {
    const content = await compileMDX(context, data, mdxOptions)
    return { ...data, content }
  },
})
 
export default defineConfig({
  collections: [posts],
})

Blog Post Structure

Blog posts are stored in content/posts/ directory as MDX files. Each post requires specific frontmatter fields:

content/posts/example.md
---
title: "The Rise of Edge Computing in Modern Web Development"
description: "Explore how edge computing is revolutionizing web development..."
image: "/content/example.webp"
publishedAt: 2025-03-29
author:
  name: John Doe
  image: "/authors/john-doe.webp"
  twitterHandle: "john-doe"
---

Adding New Content Collections

To add a new content collection for static MDX content:

Define a new collection in content-collections.ts:

content-collections.ts
const docs = defineCollection({
  name: "docs",
  directory: "content/docs",
  include: "**/*.md",
  schema: z => ({
    title: z.string(),
    description: z.string(),
    category: z.string(),
  }),
  transform: async (data, context) => {
    const content = await compileMDX(context, data, mdxOptions)
    return { ...data, content }
  },
})
 
export default defineConfig({
  collections: [posts, docs],
})

Create corresponding directory structure:

content/
  ├── posts/     # Blog posts
  └── docs/      # Documentation pages

Access the content in your components:

app/blog/page.tsx
import { allDocs } from "content-collections"
 
export default function DocsPage() {
  return (
    <div>
      {allDocs.map(doc => (
        <article key={doc.slug}>
          <h2>{doc.title}</h2>
          <p>{doc.description}</p>
          {/* Render doc.content */}
        </article>
      ))}
    </div>
  )
}
Edit on GitHub

Last updated on

On this page