Skip to content

contentful

@evolve-framework/contentful ยท v1.0.0

The Contentful CMS for Evolve: a module that serves the shared content contract (pages, content blocks, menus and the site) from a Contentful space, so a storefront reads content the same way whichever CMS is behind it.

When to use

Use it when Contentful is your CMS. It runs next to a commerce engine, often in the same service as the catalog, and its webhook publishes content-modified events when editors publish. Add your own content types as blocks next to the built-in ones. Use @evolve-framework/storyblok or @evolve-framework/payload instead for those CMSes.

Get started

  1. Install the package with the peer dependencies it needs. It comes from the Evolve registry, which needs a one-time sign-in.

    pnpm add @evolve-framework/contentful @evolve-framework/core fastify graphql graphql-yoga zod
    Requirements7
    @evolve-framework/core>= 1.0.0 < 2.0.0
    @types/node>=22optional
    fastify>= 5.12.1 < 6.0.0
    graphql>= 16.0.0 < 17.0.0
    graphql-yoga>= 5.21.3 < 6.0.0
    msw^2.14.6 || ^3.0.1optional
    zod>= 4.4.0 < 5.0.0

For example:

import { ContentfulModule } from "@evolve-framework/contentful";
import { NoopPublisher } from "@evolve-framework/core/messaging";
const cms = new ContentfulModule({
config: {
spaceId: process.env.CONTENTFUL_SPACE_ID!,
environment: process.env.CONTENTFUL_ENVIRONMENT ?? "master",
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN!,
previewToken: process.env.CONTENTFUL_PREVIEW_TOKEN!,
managementToken: process.env.CONTENTFUL_MANAGEMENT_API_ACCESS_TOKEN!,
},
// Where content-modified events go; a cloud adapter's publisher in production
messagePublisher: new NoopPublisher(),
// The signing secret of the space's webhook request verification
webhookSecret: process.env.CONTENTFUL_WEBHOOK_SECRET!,
});

Modules

ContentfulModule

Module wiring Contentful resolvers, typedefs and webhook into a Domain Service.

Pass either a pre-built clients bundle (from createContentfulClients) or a config object; the module will build its own clients from config during init().

Only one ContentfulModule instance per process is supported โ€” clients and the mapper registry are held as module-scope singletons.

import { ContentfulModule } from "@evolve-framework/contentful";
new ContentfulModule(options: ContentfulModuleOptions)
OptionTypeDescription
messagePublisherMessagePublisher

Publisher used to emit content-modified events from the webhook. Pass a messagePublisher from a cloud adapter (e.g. new SqsPublisher(...)) or a NoopPublisher to disable publishing.

webhookSecretstring

The signing secret of the space's webhook request verification, under Settings > Webhooks > Settings in Contentful. A delivery without a valid signature is refused with a 401.

webhookPath?string

URL path the webhook is registered on. Defaults to "/webhook".

blocks?ContentBlockDef[]

The complete set of content blocks the module serves. Defaults to the built-in contentBlocks; spread it to add or replace, e.g. blocks: [...contentBlocks, myBlock] (a block whose id matches a built-in replaces it). Each block's mapper is registered and its SDL fragment merged into the served schema.

mappers?((registry: MapperRegistry) => void)

Optional callback invoked with the pre-populated MapperRegistry. Use it to add or override mappers for custom Contentful content types.

articlesPerProduct?number

How many articles a product shows at most. Defaults to 4.

siteRevalidation?SiteRevalidationOptions

The sites whose caches a publish purges: their revalidate URLs and the secret they share with this service. The locales purged are the space's. Without it the webhook purges only this service's caches.

clients?ContentfulClients

Clients the module uses as they are, typically from createContentfulClients. Pass either this or config.

config?ContentfulConfig

Settings the module builds its own clients from with createContentfulClients during init(). Pass either this or clients.

ContentBlockDef8The fields of blocks.
FieldTypeDescription
idstring

Contentful sys.contentType.sys.id, e.g. "promo_list".

typenamestring

Output GraphQL typename, e.g. "PromoList".

typeDefs?string

SDL for a block the shared contract does not already describe. Built-in blocks leave this unset: their output type and union membership are part of the contract every CMS package serves, so they live in schemas. A project's own block declares both here, and the fragment is merged over the generated schema.

terraform?string

Terraform provisioning the content type in Contentful.

groups?string[]

Groups this block is a member of (which slots it can fill).

slots?Record<string, Slot>

Slots this block exposes (what it can contain).

mapper?ContentBlockMapper

Maps a Contentful entry to the block's GraphQL type, for blocks dispatched through the mapper registry (body/column blocks). Omitted for blocks whose mapping lives elsewhere โ€” e.g. pages (see pageMapper) or links (mapped by the link registry).

pageMapper?PageMapper

Maps an entry of this page type onto its GraphQL page. Set only on page types; mapPage dispatches an entry to it on its content type.

ContentfulClients5The fields of clients.
FieldTypeDescription
clientContentfulClientApi<undefined>
previewClientContentfulClientApi<undefined>
managementClientPlainClientAPI
spaceIdstring
environmentstring
ContentfulConfig5The fields of config.
FieldTypeDescription
spaceIdstring
environmentstring
accessTokenstring
previewTokenstring
managementTokenstring

Extends AbstractModule<ContentfulLoaderContext>.

Testing

Test helpers in /testing. What they are for

Commands

Installing this package adds these commands to the evolve CLI.

  • evolve eject: Eject built-in blocks into your project so you own them
  • evolve field-tabs: Put every content type's fields on the Content, SEO and Settings tabs
  • evolve tf-export: Export the built-in content blocks' Terraform to disk

Entry points

@evolve-framework/contentfulContentfulModule, the built-in content blocks and defineContentBlock for your own, the Contentful clients and configuration, and catalog page sync.52 exports
@evolve-framework/contentful/graphql/contextThe request context the module's resolvers expect.3 exports
@evolve-framework/contentful/graphql/typesThe generated GraphQL types of the content contract.236 exports
@evolve-framework/contentful/cftypesGenerated TypeScript types of the Contentful content types the module provisions.113 exports
@evolve-framework/contentful/testingA test context, a mocked Contentful API and a test executor.4 exports