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

Importing Functions

import { 
  defineCollection, 
  getCollection, 
  getEntry, 
  getEntries,
  reference 
} from 'astro:content';

defineCollection

Define a content collection schema in your src/content/config.ts file.
defineCollection(config: CollectionConfig): CollectionConfig
config
object
required
Collection configuration object.
config.type
'content' | 'data'
The type of collection. Use 'content' for Markdown/MDX files with frontmatter, or 'data' for JSON/YAML data files.Default: 'content'
config.schema
ZodSchema
A Zod schema to validate frontmatter or data.
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(),
  }),
});
config.loader
Loader
A loader function for loading collection data. Used with the Content Layer API.
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';

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

Example

// 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.
getCollection(
  collection: string,
  filter?: (entry: CollectionEntry) => boolean
): Promise<CollectionEntry[]>
collection
string
required
The name of the collection to query.
filter
(entry: CollectionEntry) => boolean
Optional filter function to select specific entries.
const publishedPosts = await getCollection('blog', (entry) => {
  return entry.data.draft !== true;
});
return
Promise<CollectionEntry[]>
An array of collection entries with the following properties:
id
string
Unique identifier for the entry (filename without extension).
slug
string
URL-friendly slug for the entry.
collection
string
The name of the collection this entry belongs to.
data
object
Parsed and validated frontmatter data matching your schema.
body
string
Raw Markdown/MDX content (content collections only).
render
() => Promise<RenderResult>
Function to render the content (content collections only).

Example

// 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.
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>
collection
string
required
The name of the collection.
id
string
required
The entry ID (filename without extension).
return
Promise<CollectionEntry | undefined>
A single collection entry, or undefined if not found.

Example

// 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.
getEntries(
  entries: { collection: string; id: string }[]
): Promise<CollectionEntry[]>
entries
array
required
Array of entry references.
return
Promise<CollectionEntry[]>
Array of matching collection entries.

Example

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.
reference(collection: string): ZodSchema
collection
string
required
The name of the collection to reference.
return
ZodSchema
A Zod schema that validates references to the specified collection.

Example

// 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 };
---
// 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.
const entry = await getEntry('blog', 'my-post');
const { Content, headings, remarkPluginFrontmatter } = await entry.render();
Content
AstroComponent
An Astro component containing the rendered content.
<Content />
headings
MarkdownHeading[]
Array of headings extracted from the content.
type MarkdownHeading = {
  depth: number;
  slug: string;
  text: string;
};
remarkPluginFrontmatter
Record<string, any>
Frontmatter data modified or injected by remark/rehype plugins.

Example

---
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>

Build docs developers (and LLMs) love