---
title: Next.js
description: Integrate Content Collections into your Next.js app
linkText: Quickstart Next.js
category: frameworks
---

<div className="steps">
<div className="step">

Install required packages:

We have to install the following packages:

- `@content-collections/core`
- `@content-collections/next`

```package-install
npm i @content-collections/core @content-collections/next -D
```

</div>
<div className="step">

Adjust your `tsconfig.json`:

```json
{
  "compilerOptions": {
    // ...
    "paths": {
      "@/*": ["./*"],
      "content-collections": ["./.content-collections/generated"]
    }
  }
}
```

We require a path alias for the generated files.
This is necessary because we will generate the files in the `.content-collections/generated` folder.

</div>
<div className="step">

Modify your Next.js configuration:

<Tabs groupId="typof-next-config" items={["next.config.mjs", "next.config.js", "next.config.ts"]} persist>
<Tab value="next.config.mjs">

```js
import { withContentCollections } from "@content-collections/next";

/** @type {import('next').NextConfig} */
const nextConfig = {
  // your next.js config
};

// withContentCollections must be the outermost plugin
export default withContentCollections(nextConfig);
```

</Tab>
<Tab value="next.config.js">

```js
const { withContentCollections } = require("@content-collections/next");

/** @type {import('next').NextConfig} */
const nextConfig = {
  // your next.js config
};

// withContentCollections must be the outermost plugin
module.exports = withContentCollections(nextConfig);
```

</Tab>
<Tab value="next.config.ts">

```ts
import type { NextConfig } from "next";
import { withContentCollections } from "@content-collections/next";

const nextConfig: NextConfig = {
  /* config options here */
};

// withContentCollections must be the outermost plugin
export default withContentCollections(nextConfig);
```

</Tab>
</Tabs>

This will add content collections to the build of your next.js app.
For more details on the Next.js adapter, refer to the [documentation](/docs/adapter/next).

</div>
<div className="step">

Add the new `.content-collections` directory to your project's `.gitignore` file — the files in this directory are always regenerated and can be safely ignored by Git.

```
.content-collections
```

</div>
<div className="step">

Create a `content-collections.ts` file at the root of your project:

```ts
import { defineCollection, defineConfig } from "@content-collections/core";

const posts = defineCollection({
  name: "posts",
  directory: "src/posts",
  include: "**/*.md",
  schema: (z) => ({
    title: z.string(),
    summary: z.string(),
  }),
});

export default defineConfig({
  collections: [posts],
});
```

This file defines a collection named `posts` in the `src/posts` folder.
The collection will include all markdown files (`**/*.md`) and the schema will validate the `title` and `summary` fields.

For more information about the configuration have a look at the [documentation](/docs/configuration).

</div>
<div className="step">

Create your content files (e.g.: `src/posts/hello-world.md`):

```md
---
title: "Hello world"
summary: "This is my first post!"
---

# Hello world

This is my first post!
... rest of the content
```

You can create unlimited content files.
These files will be validated against the schema defined in the `content-collections.ts` file.
If the files are valid, they will be automatically added to the `posts` collection.

</div>
<div className="step">

Usage in your code:

```tsx
import { allPosts } from "content-collections";

export default function Posts() {
  return (
    <ul>
      {allPosts.map((post) => (
        <li key={post._meta.path}>
          <a href={`/posts/${post._meta.path}`}>
            <h3>{post.title}</h3>
            <p>{post.summary}</p>
          </a>
        </li>
      ))}
    </ul>
  );
}
```

Now you can just import the `allPosts` collection and use it in your code.
The `allPosts` collection will contain all posts that are valid.
The `post` object will contain the `title`, `summary` and `content` fields as well as some meta information in the `_meta` field.

</div>
</div>
