datocms-cda
Query the DatoCMS Content Delivery API (CDA) — the read-only GraphQL API — using @datocms/cda-client. Use when users ask for GraphQL content reads: fetching posts/pages/projects, filtering by date/text/fields, sorting/order, pagination/load-more, text pattern matching via regex filters, localization and fallback locales, modular content fragments, Structured Text (DAST) with blocks/inline records, responsive images (srcset/blur-up/imgix), SEO metadata (_seoMetaTags, favicons, global SEO), video/Mux fields, draft or preview reads, environment-targeted reads, cache tags via rawExecuteQuery, and Content Link metadata for visual editing. Also use for CDA query type generation with gql.tada or GraphQL Code Generator.
Skill body
DatoCMS Content Delivery API Skill
Expert at querying DatoCMS CDA (read-only GraphQL) using @datocms/cda-client. Follow steps in order.
Step 1: Detect Context
If context already established, skip broad detection. Re-inspect only when needed.
Examine project setup:
-
Read
package.jsonfor@datocms/cda-client. Not installed?npm install @datocms/cda-client -
Find existing
executeQueryorrawExecuteQueryimports to understand usage patterns. - Check
.env,.env.localfor DatoCMS API token:DATOCMS_CDA_TOKENDATOCMS_READONLY_TOKENDATOCMS_API_TOKENNEXT_PUBLIC_DATOCMS_CDA_TOKEN
-
Check framework (Next.js, Astro, Remix, Nuxt, SvelteKit) to determine server vs client queries. Don’t expose tokens to browser unless using public read-only token.
- Check type generation setup:
- gql.tada:
gql.tadain dependencies +initGraphQLTadacall (typicallylib/datocms/graphql.ts) - graphql-codegen:
@graphql-codegen/cliin devDependencies +graphql.config.ts - Context only — match existing setup. Don’t suggest setting up type generation.
- gql.tada:
CDA only needs read-only token. If DATOCMS_API_TOKEN is also used for CMA, better suggesting a separate read-only token for CDA.
Step 2: Understand Task
Classify task:
| Category | Examples |
|---|---|
| Basic querying | Fetch by slug/ID, single-instance, list collections |
| Filtering | Field filters, AND/OR, meta filters, deep filtering |
| Pagination & ordering | Paginate, sort, tree/hierarchical |
| Localization | Localized fields, fallback, all-locale values |
| Modular content | Block fields with fragments, nested blocks |
| Structured text | DAST value/blocks/links, render |
| Images & media | Responsive images, imgix, placeholders, focal, video |
| SEO & meta | _seoMetaTags, favicons, globalSeo, OG tags |
| Draft/preview & caching | Draft mode, strict mode, cache tags, CDN, Content Link |
| Type generation | gql.tada, graphql-codegen, schema types, typed queries |
Clear request? Proceed directly.
Step 3: Load References
Read relevant references from references/. Always load core client reference, then only relevant files.
Always load:
references/client-and-config.md— client setup, options, error handling, limits, scalars
Load per category:
| Task | Reference |
|---|---|
| Basic (records, collections, meta) | references/querying-basics.md |
| Filtering (fields, AND/OR, deep, uploads) | references/filtering.md |
| Pagination & ordering (first/skip, auto, trees) | references/pagination-and-ordering.md |
| Localization | references/localization.md |
| Modular content (blocks, fragments) | references/modular-content.md |
| Structured text (DAST, render) | references/structured-text.md |
| Images & media (responsiveImage, video) | references/images-and-videos.md |
| SEO & meta | references/seo-and-meta.md |
| Draft/preview, cache, environments, Content Link | references/draft-caching-environments.md |
| Type generation (gql.tada, graphql-codegen, types) | references/type-generation.md |
| gql.tada fragment discipline (masking, composition, page query) | references/fragment-patterns.md |
Cross-cutting:
- Filtering localized →
references/localization.md - Structured text with modular content →
references/modular-content.md - Images in blocks →
references/images-and-videos.md - Paginating filtered collection →
references/pagination-and-ordering.md - Complex nesting →
references/pagination-and-ordering.mdfor complexity costs - Writing/extending fragments in a
gql.tadaproject →references/fragment-patterns.md
Step 4: Mandatory Rules to Generate Code
Client Usage
- Default:
executeQueryfrom@datocms/cda-client(or repo’s existing wrapper around it) - Use
buildRequestHeaders()/buildRequestInit()for frameworkfetchintegration, tagging, custom plumbing - Use
executeQueryWithAutoPaginationto fetch 500+ records - Use
rawExecuteQueryonly if response headers are needed (cache tags) - Store API token in env variable — never hardcode
GraphQL Queries
- Write as template literal strings (unless project uses
TypedDocumentNode/gql.tada) - Use GraphQL variables for all dynamic values — no string interpolation
- Request only needed fields — don’t over-fetch
- Use DatoCMS custom scalars in declarations (
$first: IntType,$id: ItemId) - Prepend template string with
/* GraphQL */(comment-tagged templates) for syntax highlighting
const query = /* GraphQL */ `query { ... }`
Structured Text
- Query all relevant sub-fields (
value,blocks,links,inlineBlocks) — omitting causes silent data loss
Error Handling
- Catch
ApiErrorfrom@datocms/cda-clientat appropriate boundaries - No custom retry logic —
autoRetryhandles rate limits
TypeScript
- Follow strictness: no
as unknown as, no unnecessaryas - Let TypeScript infer types
- Use
import type { ... }for type-only imports
Step 5: Verify
Before presenting final code:
- Token — env variable, read permissions
- Error handling —
ApiErrorcaught at boundaries - Pagination — 500+ records? use
executeQueryWithAutoPagination - Draft mode —
includeDraftsintentional (not exposing unpublished in prod) excludeInvalid— recommend for stable schemas. Changing schema? usefilter: { _isValid: { eq: true } }instead- Type safety — no
asto silence errors - Imports — CDA from
@datocms/cda-client; keep generated GraphQL helpers if type-gen wired - Variables — all dynamic via GraphQL variables, no interpolation
- Structured text — all relevant sub-fields included
- Fetch integration — framework-native
fetch? usebuildRequestHeaders()/buildRequestInit() - Type generation — gql.tada or graphql-codegen? use project’s
graphql()function, check scalar mappings - gql.tada fragment discipline — masked-by-default,
readFragment()at boundary, imports mirror spreads (seereferences/fragment-patterns.md)
Cross-Skill Routing
This skill covers reading via GraphQL CDA. Route to companion skill for:
| Condition | Route to |
|---|---|
| Mutating content, schema/uploads/webhooks, scripts (including REST queries) | datocms-cma |
| Draft mode endpoints, Web Previews, Content Link, subscriptions, cache tags | datocms-frontend-integrations |
| Building plugin | datocms-plugin |