Menu
Site code reference
Reading CMS content in code
How a page reads CMS collections with getLiveCollection and getLiveEntry, what it must declare, and how to handle missing items and fields.
CMS collections aren't files. A page reads them with Astro's live-collection functions, imported from astro:content. Every collection is declared for you; you never write src/live.config.ts.
A listing page
---
// src/pages/blog.astro
export const prerender = false
import Base from '../layouts/Base.astro'
import { getLiveCollection } from 'astro:content'
const { entries: posts = [] } = await getLiveCollection('blogPost', {
sort: 'publishedAt',
order: 'desc',
limit: 10,
})
---
<Base>
<ul class="mx-auto flex max-w-3xl flex-col gap-6 px-6 py-16">
{posts.map((post) => (
<li>
<a href={`/blog/${post.data.slug}`} class="font-display text-2xl text-ink-900 hover:text-accent-600">
{post.data.title ?? 'Untitled'}
</a>
</li>
))}
</ul>
</Base>
Each entry is { id, data }; data holds the item's fields.
An item page
Item pages have no getStaticPaths():
---
// src/pages/blog/[slug].astro
export const prerender = false
import Base from '../../layouts/Base.astro'
import { getLiveEntry } from 'astro:content'
import Markdown from '@starjay/design-system/components/cms/Markdown.astro'
const { entry } = await getLiveEntry('blogPost', { slug: Astro.params.slug })
if (!entry) return new Response(null, { status: 404 })
const post = entry.data
---
<Base>
<article class="mx-auto max-w-2xl px-6 py-16">
<h1 class="font-display text-4xl text-ink-900">{post.title}</h1>
{post.body && <Markdown value={post.body} class="mt-8 text-lg text-ink-700" />}
</article>
</Base>
Look an item up by { slug } when its collection has a slug field. Otherwise look it up by id: getLiveEntry('blogPost', Astro.params.id).
Query options
All options are optional.
| Option | What it does |
|---|---|
where |
Field → value, or an operator object: $eq, $ne, $gt, $gte, $lt, $lte, $in, $contains, $all, $exists |
search |
Text search |
sort |
A field to sort by |
order |
'asc' or 'desc' |
limit, offset |
Paging |
expand |
Reference fields to replace with the item they point to |
const { entries: featured = [] } = await getLiveCollection('product', {
where: { category: 'chairs', price: { $lte: 500 } },
expand: ['designer'],
})
Which fields can be queried
where, search and sort work only on short top-level fields: text, slugs, numbers, dates, true/false, choices, links, images, references, and plain lists of those. Long text, Markdown and grouped fields (objects, mixed lists) can't be queried. Read the items, then use those fields in the page.
Why every field may be missing
A draft item may be incomplete. A published item doesn't have a field that was added, or made required, after it was published. Guard every field: {post.data.subtitle && <p>{post.data.subtitle}</p>}.
How these pages behave
Pages that read collections render on request. The live site caches them until the content changes. A page that must differ for each visitor (because it reads cookies or request headers) calls Astro.cache.set(false).
A collection needs at least one item before its item page has anything to show. Listings show only published items on the live site; see CMS pages on the live site.