Skip to main content
skill CX Codex

content-collection — Claude Code skill: use and install

This skill guides Astro content collections with typed schemas and query patterns. Use it for blogs, docs, changelogs, and other structured content.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add incluud/astro-agent-skills --skill content-collection -a claude-code
Open on GitHub

What content-collection does

The skill covers collection design, schema changes, and validation. It helps decide between build-time and live data, define required fields and references, and configure loaders with glob() or file(). Schemas use astro/zod, with optional image validation through image().

For reads, it uses getCollection(), getEntry(), and getEntries(). Dynamic routes can use entry.id, while rendered content goes through render(entry). After edits, the workflow includes npx astro sync and checking a real entry from each collection. Astro 6 and later require src/content.config.*; src/content/config.* is the old location.

What it helps with

  • design typed Astro content collections
  • load entries from local folders or data files
  • connect entries with reference()
  • migrate collections to the current Content Layer API
  • validate schemas after collection changes

Example prompts for the agent

  • Set up blog and author collections in src/content.config.ts with typed fields, references, and image validation.
  • Migrate this project from the legacy Astro content API and update its entry queries.
  • Check every collection after the edit, fix schema errors, then run npx astro sync.

How to install content-collection

1Skills CLI (Vercel)

npx skills add incluud/astro-agent-skills --skill content-collection -a claude-code

2Manually: put the files in place

~/.claude/skills/content-collection/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/content-collection/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about content-collection

How do I install content-collection in Claude Code?

Run npx skills add incluud/astro-agent-skills --skill content-collection -a claude-code, then check ~/.claude/skills/content-collection/SKILL.md.

What does content-collection do?

It helps create and refactor Astro collections by defining schemas, loading entries, linking records, and querying them with the current content APIs.

Which Astro API changes does it cover?

For Astro 6 and later, use src/content.config.*, entry.id, getEntry(), and render(entry). Each collection needs a loader, while legacy collection types should be removed.

Source text

SKILL.md · MIT
---
name: content-collection
description: Set up and evolve Astro content collections with typed schemas and reliable querying patterns.
---

# Astro Content Collections

Use this skill when creating or refactoring structured content in Astro, such as blogs, docs, changelogs, case studies, team data, or other schema-driven content.

If `astro-best-practices` is available, apply it alongside this skill for naming, accessibility, and performance defaults.

## Workflow

### 1. Decide whether the collection is build-time or live

Most content sites should use build-time collections in `src/content.config.*`. Only reach for live collections in `src/live.config.*` when the data truly needs request-time freshness.

Before coding, decide:

- which collections exist
- which fields are required
- which relationships need references
- whether assets such as images should be validated

Favor a schema that reflects how the site queries content, not just how frontmatter currently looks.

### 2. Define collections in `src/content.config.*`

Use the current Content Layer API. For build-time collections:

- define them in `src/content.config.ts` (or `.js` / `.mjs`)
- give every collection a `loader`
- import `z` from `astro/zod`
- do not use `type: 'content'` or `type: 'data'`

Example:

```ts
import { defineCollection, reference } from 'astro:content'
import { glob } from 'astro/loaders'
import { z } from 'astro/zod'

const blog = defineCollection({
  loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }),
  schema: ({ image }) => z.object({
    title: z.string(),
    description: z.string(),
    publishDate: z.coerce.date(),
    updatedDate: z.coerce.date().optional(),
    author: reference('authors'),
    cover: image().optional(),
    tags: z.array(z.string()).default([]),
    draft: z.boolean().default(false),
  }),
})

const authors = defineCollection({
  loader: glob({ base: './src/data/authors', pattern: '**/*.json' }),
  schema: z.object({
    name: z.string(),
    email: z.email().optional(),
    avatar: z.url().optional(),
  }),
})

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

Useful patterns:

- `glob()` for folders of local entries
- `file()` for a single JSON or other data file
- `z.enum(...)` for controlled values
- `z.coerce.date()` for frontmatter dates
- `reference('collection-name')` for relationships
- `schema: ({ image }) => ...` when image validation matters

### 3. Keep the collection shape current

For Astro 6 and newer:

- use `src/content.config.*`, not `src/content/config.*`
- use `entry.id` as the slug-like identifier in URLs and queries
- use `entry.filePath` only when you truly need the source path
- use `getEntry()` instead of legacy `getEntryBySlug()` or `getDataEntryById()`

Prefer a stable folder structure and predictable IDs. Avoid scattering content across route folders if it is logically a collection.

### 4. Query with intent

Use the content APIs that match the job:

- `getCollection()` for lists
- `getEntry()` for a single known entry
- `getEntries()` for arrays of references
- collection filters for draft/published splits

Example:

```astro
---
import { getCollection } from 'astro:content'

const posts = await getCollection('blog', ({ data }) => !data.draft)
---
```

When rendering entries, keep route generation and content rendering separate enough that each part remains easy to reason about.

### 5. Wire routes and rendering with the current API

For dynamic routes:

- build paths from collection IDs
- pass the entry through props cleanly
- render content with `render(entry)`

Example:

```astro
---
import { getCollection, render } from 'astro:content'

export async function getStaticPaths() {
  const posts = await getCollection('blog')
  return posts.map((post) => ({
    params: { slug: post.id },
    props: { post },
  }))
}

const { post } = Astro.props
const { Content } = await render(post)
---

<article>
  <h1>{post.data.title}</h1>
  <Content />
</article>
```

### 6. Sync and validate

After changing collections:

- run `npx astro sync` or the repo’s normal Astro workflow
- fix schema mismatches instead of weakening types
- validate at least one real entry per collection
- watch for warnings about missing loaders, legacy config paths, or deprecated imports

## Migration Guidance

When migrating from older content patterns:

1. move `src/content/config.ts` to `src/content.config.ts`
2. add a `loader` to every collection
3. remove any `type: 'content'` or `type: 'data'`
4. replace `import { defineCollection, z } from 'astro:content'` with `import { defineCollection } from 'astro:content'` and `import { z } from 'astro/zod'`
5. replace `post.slug` with `post.id`
6. replace `entry.render()` with `render(entry)`
7. replace `getEntryBySlug()` and `getDataEntryById()` with `getEntry()`

If the project is crossing Astro versions at the same time, verify version-sensitive content APIs in the current official Astro docs before finalizing.

© incluud · MIT · incluud/astro-agent-skills

Similar skills

All skills for Frontend and UI →

From the same set6

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor