Back to blog
v2026.06+ added

Content Collections in Astro 7

How to structure a bilingual blog with typed schemas and per-locale folders.

astrotypescriptblog

Astro Content Collections provide build-time validation and editor autocompletion.

Schema with Zod

In src/content/config.ts you define the contract for each article:

const blog = defineCollection({
  loader: glob({ pattern: "**/*.md", base: "./src/content/blog" }),
  schema: z.object({
    title: z.string(),
    publishedAt: z.coerce.date(),
    changeType: z.enum(["added", "fixed", "improved", "deprecated"]),
  }),
});

If frontmatter doesn’t match the schema, the build fails immediately.

Per-locale folders

For i18n without automatic translation, each locale gets its own folder:

content/blog/
├── es/
│   └── articulo.md
└── en/
    └── article.md

The entry id includes the path (es/articulo), enabling locale filtering in getCollection().

Rendering

Each entry exposes .render() to get the content component and heading metadata — ideal for tables of contents or internal links in future phases.