Skip to content

New: AI agent integration via Model Context Protocol (MCP).Learn more

Creating content types

Storyblok provides a UI for creating content types. However, we do not and should not use that since we manage the types in Terraform. Modifying content types through the UI will result in a mismatch in the Terraform state and break the deploy pipeline.

Content types are defined as Terraform resources in backend/configuration/storyblok/. Each component gets its own .tf file:

resource "storyblok_component" "hero" {
name = "hero"
space_id = var.storyblok_space_id
is_root = false
is_nestable = true
schema = {
title = {
position = 0
translatable = true
display_name = "Title"
required = true
type = "text"
}
image = {
position = 5
translatable = true
display_name = "Image"
required = true
type = "asset"
filetypes = ["images"]
}
}
}

To add a new content type:

  1. Create a new .tf file in backend/configuration/storyblok/ (e.g., component_banner.tf)
  2. Define the storyblok_component resource with the fields your content editors need
  3. Push the changes through a PR

When the changes are merged, the CI/CD pipeline deploys them to the Storyblok environment. Your changes will not be available in Storyblok during the PR preview stage since Terraform runs on merge.

The TypeScript definitions for Storyblok components ship with the framework: the @evolve-framework/storyblok package bundles a storyblok.types.d.ts with the component types used by the CMS service. There is no per-project Storyblok type generation step.

The CMS service does have its own codegen for GraphQL and events:

Terminal window
pnpm codegen

In backend/services/cms-storyblok this runs graphql-codegen for the GraphQL subgraph types and codegen.types.ts, which uses writeZodTypes from @evolve-framework/json-schema-to-zod to generate Zod schemas for platform events into src/generated/events.ts.

Storyblok distinguishes between root content types and nestable components:

  • Root content types (is_root = true): can be created as standalone stories. Use these for pages (content pages, catalog pages) and site-level content (header, footer).
  • Nestable components (is_nestable = true): can only be used inside other content types. Use these for reusable blocks (hero, teaser, FAQ item).

A component can be both root and nestable if needed, but in practice you typically choose one.