DatoCMS Content Delivery API Skill
You are an expert at querying the DatoCMS Content Delivery API (CDA) using
. The CDA is a
read-only GraphQL API — it has no mutations. All content changes go through the CMA (Content Management API). Follow these steps in order. Do not skip steps.
Step 1: Detect Context
If the project context is already established in this conversation (client
package, token variable, framework, type generation setup), skip broad
detection below. Re-inspect only when a question cannot be answered from
prior context.
Silently examine the project to determine setup and configuration.
-
- If not installed, recommend:
npm install @datocms/cda-client
-
Search for existing
or
imports to understand how the project already uses the CDA client.
-
Check
,
, or similar files for a DatoCMS API token. Look for variable names like:
NEXT_PUBLIC_DATOCMS_CDA_TOKEN
-
Check the framework context (Next.js, Astro, Remix, Nuxt, SvelteKit, etc.) to determine whether queries run on the server or client. CDA queries work in both environments, but tokens should not be exposed to the browser unless the project intentionally uses a public read-only token.
-
Check for existing type generation setup:
- gql.tada: Look for in dependencies and an call (typically in )
- graphql-codegen: Look for in devDependencies and a file
- This detection is for context only — use it to write queries that match the project's existing setup (e.g., using the project's function instead of plain strings). Do not proactively suggest setting up type generation.
Important: The CDA needs a
read-only API token (or a full-access CMA token, which also works). If you see a token named
used for CMA operations, the user may need a separate read-only token for the CDA, or they can reuse the CMA token if appropriate.
Step 2: Understand the Task
Classify the user's task into one or more categories:
| Category | Examples |
|---|
| Basic querying | Fetch records by slug/ID, query single-instance models, list collections |
| Filtering | Filter by field values, AND/OR logic, meta field filters, deep filtering |
| Pagination & ordering | Paginate large collections, sort results, tree/hierarchical queries |
| Localization | Query localized fields, fallback locales, all-locale values |
| Modular content | Query block fields with GraphQL fragments, nested blocks |
| Structured text | Query DAST value/blocks/links, render with framework components |
| Images & media | Responsive images, imgix transforms, placeholders, focal points, video |
| SEO & meta | , favicons, , Open Graph tags |
| Draft/preview & caching | Draft mode, strict mode, cache tags, CDN invalidation, Content Link |
| Type generation | Set up gql.tada, configure graphql-codegen, generate schema types, typed queries |
If the user's request is clear, skip clarifying questions and proceed directly.
Step 3: Load References
Based on the task classification, read the appropriate reference files from the
directory next to this skill file.
Always load the core client reference. Only load what is relevant — do not load everything.
Always load:
references/client-and-config.md
— Client setup, options, error handling, limits, scalars
Load per category:
| Task category | Reference file |
|---|
| Basic querying (records, collections, meta) | references/querying-basics.md
|
| Filtering (field filters, AND/OR, deep filtering, uploads) | |
| Pagination & ordering (first/skip, auto-pagination, trees) | references/pagination-and-ordering.md
|
| Localization | references/localization.md
|
| Modular content (blocks, fragments) | references/modular-content.md
|
| Structured text (DAST, rendering) | references/structured-text.md
|
| Images & media (responsiveImage, video) | references/images-and-videos.md
|
| SEO & meta tags | references/seo-and-meta.md
|
| Draft/preview, caching, environments, Content Link | references/draft-caching-environments.md
|
| Type generation (gql.tada, graphql-codegen, schema types) | references/type-generation.md
|
Load cross-cutting references when needed:
- If filtering localized fields → also load
references/localization.md
- If querying modular content inside structured text → also load
references/modular-content.md
- If querying images inside blocks → also load
references/images-and-videos.md
- If paginating a large filtered collection → also load
references/pagination-and-ordering.md
- If the query involves complex nesting → also load
references/pagination-and-ordering.md
for complexity costs
Step 4: Generate Code
Write the code following these mandatory rules:
Client Usage
- Default to from , or the repo's existing wrapper around it (not raw )
- Use / when the framework needs integrated handling, request tagging, or custom request plumbing
- Use
executeQueryWithAutoPagination
when fetching more than 500 records
- Use only when you need response headers (e.g., cache tags)
- Store the API token in an environment variable — never hardcode it
GraphQL Queries
- Write queries as template literal strings (unless the project uses / )
- Use GraphQL variables for all dynamic values — never use string interpolation in queries
- Request only the fields you need — do not over-fetch
- Use DatoCMS custom scalars in variable declarations (e.g., , )
Structured Text
- Always query all relevant sub-fields (, , , ) when the structured text field uses them — omitting any causes silent data loss
Error Handling
- Catch from at appropriate boundaries
- Do not add custom retry logic — handles rate limits automatically
TypeScript
- Follow the TypeScript strictness rules: no , no unnecessary casts
- Let TypeScript infer types wherever possible
- Use for type-only imports
Step 5: Verify
Before presenting the final code:
- Token — Ensure the token comes from an environment variable and has read permissions
- Error handling — Ensure is caught at appropriate boundaries
- Pagination — If the collection could exceed 500 records, use
executeQueryWithAutoPagination
- Draft mode — If is used, ensure it is intentional (not accidentally showing unpublished content in production)
- — Recommend for stable schemas. If the schema is changing (migrations, new required fields), use
filter: { _isValid: { eq: true } }
instead to avoid re-validation errors
- Type safety — No type assertions () used to silence errors
- Imports — CDA client imports come from ; keep project-generated GraphQL helper imports when type generation is already wired
- Variables — All dynamic values use GraphQL variables, not string interpolation
- Structured text completeness — If querying structured text, all relevant sub-fields (, , , ) are included
- Fetch integration — If the solution uses framework-native , ensure CDA headers/init come from / instead of hand-rolled request wiring
- Type generation — If the project uses gql.tada or graphql-codegen, ensure queries use the project's function (not plain template literal strings) and that scalar mappings are configured
Cross-Skill Routing
This skill covers reading content via the GraphQL CDA. If the task involves any of the following, activate the companion skill:
| Condition | Route to |
|---|
| Mutating content, managing schema/uploads/webhooks, writing scripts (including querying records via REST for scripts) | datocms-cma |
| Setting up draft mode endpoints, Web Previews, Content Link, real-time subscriptions, or cache tags in a framework | datocms-frontend-integrations |
| Building a DatoCMS plugin | datocms-plugin-builder |