Rendering articles
The loader compiles each article’s Markdown at build time, so rendering is the standard Astro collection flow: render(entry) returns a Content component you drop into the page. You don’t run a Markdown renderer yourself.
render(entry) → <Content />
Section titled “render(entry) → <Content />”---import { getCollection, render } from "astro:content";
export const getStaticPaths = async () => (await getCollection("articles")).map((p) => ({ params: { slug: p.id }, props: { p } }));
const { p } = Astro.props;const { Content } = await render(p);---<h1>{p.data.title}</h1><Content />render is imported from astro:content and called with the whole entry. It reads entry.rendered (the compiled body) — not entry.data — and gives you back Content, plus headings for a table of contents if you want one.
The body is pre-compiled, not in entry.data
Section titled “The body is pre-compiled, not in entry.data”The Markdown lives in two places on the entry, never in entry.data:
entry.body— the raw Markdown source string.entry.rendered— the compiled output that<Content />renders.
So entry.data is metadata only (title, author, tags, timestamps, image). Reach for entry.body only if you need the raw source — for a reading-time estimate, an excerpt, or a search index. For display, use <Content />.
Head tags come from entry.data
Section titled “Head tags come from entry.data”The <head> is driven by the metadata fields, separate from the body. Set the title, description, and canonical from entry.data in the same page:
---import { getCollection, render } from "astro:content";
export const getStaticPaths = async () => (await getCollection("articles")).map((p) => ({ params: { slug: p.id }, props: { p } }));
const { p } = Astro.props;const { Content } = await render(p);const { title, seoTitle, seoDescription, canonicalUrl, image, updatedAt } = p.data;const canonical = canonicalUrl ?? new URL(p.id, Astro.site).href;---<head> <title>{seoTitle}</title> <meta name="description" content={seoDescription ?? ""} /> <link rel="canonical" href={canonical} /> {image && <meta property="og:image" content={image.url} />} <meta property="article:modified_time" content={updatedAt.toISOString()} /></head><article> <h1>{title}</h1> <Content /></article>seoTitle already falls back to title server-side, so it’s always a string. seoDescription, canonicalUrl, and image can be null — guard them. The timestamps are Date objects, so call .toISOString() (or .toLocaleDateString() for display) directly.
Where to go next
Section titled “Where to go next”- SEO & JSON-LD — emit a
<script type="application/ld+json">graph fromentry.data. - Collection schema — every field on
entry.data.