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

# Content Collections API

> API reference for Astro's Content Collections system

Astro's Content Collections API provides type-safe content management for your Markdown, MDX, and JSON files.

## Importing Functions

```typescript theme={null}
import { 
  defineCollection, 
  getCollection, 
  getEntry, 
  getEntries,
  reference 
} from 'astro:content';
```

## defineCollection

Define a content collection schema in your `src/content/config.ts` file.

```typescript theme={null}
defineCollection(config: CollectionConfig): CollectionConfig
```

<ParamField path="config" type="object" required>
  Collection configuration object.

  <ParamField path="config.type" type="'content' | 'data'">
    The type of collection. Use `'content'` for Markdown/MDX files with frontmatter, or `'data'` for JSON/YAML data files.

    **Default:** `'content'`
  </ParamField>

  <ParamField path="config.schema" type="ZodSchema">
    A Zod schema to validate frontmatter or data.

    ```typescript theme={null}
    import { defineCollection, z } from 'astro:content';

    const blog = defineCollection({
      type: 'content',
      schema: z.object({
        title: z.string(),
        description: z.string(),
        pubDate: z.date(),
        tags: z.array(z.string()).optional(),
      }),
    });
    ```
  </ParamField>

  <ParamField path="config.loader" type="Loader">
    A loader function for loading collection data. Used with the Content Layer API.

    ```typescript theme={null}
    import { defineCollection } from 'astro:content';
    import { glob } from 'astro/loaders';

    const blog = defineCollection({
      loader: glob({ pattern: '**/*.md', base: './src/data/blog' }),
    });
    ```
  </ParamField>
</ParamField>

### Example

```typescript theme={null}
// src/content/config.ts
import { defineCollection, z } from 'astro:content';

const blog = defineCollection({
  type: 'content',
  schema: z.object({
    title: z.string(),
    description: z.string(),
    pubDate: z.coerce.date(),
    updatedDate: z.coerce.date().optional(),
    heroImage: z.string().optional(),
  }),
});

const newsletter = defineCollection({
  type: 'data',
  schema: z.object({
    title: z.string(),
    date: z.date(),
  }),
});

export const collections = { blog, newsletter };
```

## getCollection

Retrieve all entries from a collection, optionally filtered.

```typescript theme={null}
getCollection(
  collection: string,
  filter?: (entry: CollectionEntry) => boolean
): Promise<CollectionEntry[]>
```

<ParamField path="collection" type="string" required>
  The name of the collection to query.
</ParamField>

<ParamField path="filter" type="(entry: CollectionEntry) => boolean">
  Optional filter function to select specific entries.

  ```typescript theme={null}
  const publishedPosts = await getCollection('blog', (entry) => {
    return entry.data.draft !== true;
  });
  ```
</ParamField>

<ResponseField name="return" type="Promise<CollectionEntry[]>">
  An array of collection entries with the following properties:

  <ResponseField name="id" type="string">
    Unique identifier for the entry (filename without extension).
  </ResponseField>

  <ResponseField name="slug" type="string">
    URL-friendly slug for the entry.
  </ResponseField>

  <ResponseField name="collection" type="string">
    The name of the collection this entry belongs to.
  </ResponseField>

  <ResponseField name="data" type="object">
    Parsed and validated frontmatter data matching your schema.
  </ResponseField>

  <ResponseField name="body" type="string">
    Raw Markdown/MDX content (content collections only).
  </ResponseField>

  <ResponseField name="render" type="() => Promise<RenderResult>">
    Function to render the content (content collections only).
  </ResponseField>
</ResponseField>

### Example

```typescript theme={null}
// src/pages/blog/index.astro
import { getCollection } from 'astro:content';

// Get all blog posts
const allPosts = await getCollection('blog');

// Get only published posts
const publishedPosts = await getCollection('blog', ({ data }) => {
  return data.draft !== true;
});

// Sort by date
const sortedPosts = allPosts.sort(
  (a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
);
```

## getEntry

Retrieve a single entry from a collection.

```typescript theme={null}
getEntry(collection: string, id: string): Promise<CollectionEntry | undefined>
getEntry(entry: { collection: string; id: string }): Promise<CollectionEntry | undefined>
getEntry(entry: { collection: string; slug: string }): Promise<CollectionEntry | undefined>
```

<ParamField path="collection" type="string" required>
  The name of the collection.
</ParamField>

<ParamField path="id" type="string" required>
  The entry ID (filename without extension).
</ParamField>

<ResponseField name="return" type="Promise<CollectionEntry | undefined>">
  A single collection entry, or `undefined` if not found.
</ResponseField>

### Example

```typescript theme={null}
// src/pages/blog/[...slug].astro
import { getEntry } from 'astro:content';

const entry = await getEntry('blog', Astro.params.slug);

if (!entry) {
  return Astro.redirect('/404');
}

const { Content } = await entry.render();
```

## getEntries

Retrieve multiple entries by reference.

```typescript theme={null}
getEntries(
  entries: { collection: string; id: string }[]
): Promise<CollectionEntry[]>
```

<ParamField path="entries" type="array" required>
  Array of entry references.
</ParamField>

<ResponseField name="return" type="Promise<CollectionEntry[]>">
  Array of matching collection entries.
</ResponseField>

### Example

```typescript theme={null}
import { getEntries } from 'astro:content';

const post = await getEntry('blog', 'welcome');
const relatedPosts = await getEntries(post.data.relatedPosts);
```

## reference

Create a reference to entries in another collection.

```typescript theme={null}
reference(collection: string): ZodSchema
```

<ParamField path="collection" type="string" required>
  The name of the collection to reference.
</ParamField>

<ResponseField name="return" type="ZodSchema">
  A Zod schema that validates references to the specified collection.
</ResponseField>

### Example

```typescript theme={null}
// src/content/config.ts
import { defineCollection, z, reference } from 'astro:content';

const blog = defineCollection({
  type: 'content',
  schema: z.object({
    title: z.string(),
    relatedPosts: z.array(reference('blog')).optional(),
    author: reference('authors'),
  }),
});

const authors = defineCollection({
  type: 'data',
  schema: z.object({
    name: z.string(),
    bio: z.string(),
  }),
});

export const collections = { blog, authors };
```

```astro theme={null}
---
// src/pages/blog/[slug].astro
import { getEntry } from 'astro:content';

const post = await getEntry('blog', Astro.params.slug);
const author = await getEntry(post.data.author);
---

<h1>{post.data.title}</h1>
<p>By {author.data.name}</p>
```

## Rendering Content

Call `render()` on a content entry to get renderable content.

```typescript theme={null}
const entry = await getEntry('blog', 'my-post');
const { Content, headings, remarkPluginFrontmatter } = await entry.render();
```

<ResponseField name="Content" type="AstroComponent">
  An Astro component containing the rendered content.

  ```astro theme={null}
  <Content />
  ```
</ResponseField>

<ResponseField name="headings" type="MarkdownHeading[]">
  Array of headings extracted from the content.

  ```typescript theme={null}
  type MarkdownHeading = {
    depth: number;
    slug: string;
    text: string;
  };
  ```
</ResponseField>

<ResponseField name="remarkPluginFrontmatter" type="Record<string, any>">
  Frontmatter data modified or injected by remark/rehype plugins.
</ResponseField>

### Example

```astro theme={null}
---
import { getEntry } from 'astro:content';

const entry = await getEntry('blog', Astro.params.slug);

if (!entry) {
  return Astro.redirect('/404');
}

const { Content, headings } = await entry.render();
---

<article>
  <h1>{entry.data.title}</h1>
  <Content />
  
  <aside>
    <h2>Table of Contents</h2>
    <ul>
      {headings.map(heading => (
        <li>
          <a href={`#${heading.slug}`}>{heading.text}</a>
        </li>
      ))}
    </ul>
  </aside>
</article>
```
