> ## Documentation Index
> Fetch the complete documentation index at: https://stackonfire.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Blog

> How Cascade handles blog

## Blog tool of choice

Cascade uses [Contentlayer](https://contentlayer.dev/) as its blog tool of choice. Contentlayer is a content management system that allows you to create, edit, and manage content in a structured way directly in your code.

<Tip>
  You can swap Contentlayer with any other CMS of your choice. You will have to
  change the way you fetch data and plug it into existing code.
</Tip>

## Setup with Cascade

Contentlayer offers thin API on top of your local filesystem. This allows you to write blogposts straight in your editor, you define the structure of your content in a simple configuration file and start writing your blog posts.

```ts theme={null}
// contentlayer.config.ts
import { defineDocumentType, makeSource } from "contentlayer/source-files";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import rehypePrettyCode from "rehype-pretty-code";
import rehypeSlug from "rehype-slug";

export const Post = defineDocumentType(() => ({
  name: "Post",
  filePathPattern: `blog/**/*.md`,
  contentType: "mdx",
  fields: {
    title: { type: "string", required: true },
    image: {
      type: "string",
      required: true,
    },
    description: { type: "string", required: true },
    date: { type: "date", required: true },
    published: {
      type: "boolean",
      required: true,
      default: false,
    },
  },
  computedFields: {
    slug: {
      type: "string",
      resolve: (post) => `/${post._raw.flattenedPath}`,
    },
    slugAsParams: {
      type: "string",
      resolve: (doc) => doc._raw.flattenedPath.split("/").slice(1).join("/"),
    },
  },
}));

export default makeSource({
  contentDirPath: "./content",
  documentTypes: [Post],
  mdx: {
    rehypePlugins: [
      rehypeSlug,
      [
        //@ts-expect-error would still work even though types are incorrect, need to fix this after contentlayer gets enough maintenenace
        rehypePrettyCode,
        {
          theme: "dracula",
          onVisitLine(node: { children: string | unknown[] }) {
            // Prevent lines from collapsing in `display: grid` mode, and allow empty
            // lines to be copy/pasted
            if (node.children.length === 0) {
              node.children = [{ type: "text", value: " " }];
            }
          },
          onVisitHighlightedLine(node: {
            properties: { className: string[] };
          }) {
            node.properties.className.push("line--highlighted");
          },
          onVisitHighlightedWord(node: {
            properties: { className: string[] };
          }) {
            node.properties.className = ["word--highlighted"];
          },
        },
      ],
      [
        rehypeAutolinkHeadings,
        {
          properties: {
            className: ["subheading-anchor"],
            ariaLabel: "Link to section",
          },
        },
      ],
    ],
  },
});
```
