JoyConf 2026 is back. Content Confidence. Human Connection. Save your spot!

Skill Issue: storyblok-model-content

Storyblok is the first headless CMS that works for developers & marketers alike.

Is your agent struggling to design Storyblok schemas? Does it guess at field types, duplicate a block that already exists under a slightly different name, or rename a field mid-task without noticing that three published stories still reference the old one?

enter trumpets…

Introducing storyblok-model-content!

A skill that helps an agent design and generate a content model based on Storyblok best practices (hence the name). In conjunction with the Storyblok MCP server, it enables the agent to design and decide between blocks and content types, datasources and inline options, and more, regardless if the source is a written brief, a URL, or a design, and applies them the same way regardless of existing content modeling patterns in the target space. It changes the schema, not story content.

The Storyblok Skills Series:

The Storyblok agent skills library is an open source set of skills that teach an AI coding agent how to work with Storyblok: when to use the CLI vs the MCP server, modeling schemas, reading and writing content through the Storyblok MCP server, turning a design into a page, and more.

Why use this skill?

To show the benefits of utilizing this skill, two separate agents were tasked with creating a content model from the same page brief:

Create a content model in Storyblok space 123 from brief:

Product: Crest Desk — smart standing desk
Launch date: 2026-11-03
Markets: US (en)

Context
Crest Desk is the third model in our standing desk line, after the Crest
Mini and Crest Pro. This page should link
out to those two under a "More from the Crest line" section near the
bottom.

Target audience
Remote and hybrid knee workers who've been putting off a standing desk
because the cheap ones wobble and the good ones need an electrician.
Price-conscious but willing to pay more once they trust the motor.

Core benefits
  - Whisper-quiet dual motor, four memory-preset heights
  - Anti-collision sensor stops the desk before it hits a shelf or a dog
  - Built-in cable tray and a single power brick
  - Assembles in under 20 minutes with the included tool, no electrician

Value proposition
 What we're selling: a standing desk you trust enough to actually use twice
 a day instead of leaving parked at one height forever.
 Why it matters: most standing desks get used once, then abandoned at
 sitting height because raising and lowering them is a hassle or feels
 unstable.
 The payoff: four one-touch presets mean switching height is as easy as
 picking up a phone.

What's in the box
  - Desktop (finish options below)
  - Dual-motor frame with anti-collision sensor
  - Cable tray and single power brick
  - Preset remote
  - Assembly tool and instructions

Finish
Walnut, white, and black laminate at launch. Merchandising maintains the
finish list centrally since it's shared across every desk in the Crest
line and gets a new option added every year or so (a fourth finish is
already planned for spring).

Price
$549 in white or black laminate, $589 in walnut (solid wood costs more to
source). One-time purchase, no subscription. Free shipping over $500,
which this qualifies for either way.

Customer reviews
Three customers agreed to be quoted and named. All three will have
profiles on the site's Customers page from previous product launches:
  - Benito Martinez, a product designer in Austin, switched from a competitor's
    desk after its motor died in year one. Five stars, says the preset
    remote is what actually got him to stand more. Yo Perreo Solo.
  - Rauw Alejandro, a freelance developer in New York, was skeptical about the
    anti-collision sensor until it stopped the desk two inches from a
    bookshelf during setup. Five stars.
  - Karol G, an accessibility consultant in Chicago, uses the lowest
    preset for a wheelchair-height sit-stand transition. Four stars, wishes
    the remote had a fifth programmable preset.

Specs
    Desktop: 60" x 30", three finishes
    Height range: 24.5" to 50.5"
    Weight capacity: 220 lbs
    Motor: dual, 3100N per leg, rated for 30,000 cycles
    Warranty: 10 years frame and motor, 2 years electronics

Tested with:

Learn:

Claude Code v2.1.267

Opus 5

Storyblok MCP server

Storyblok Skills package: 0.1.0

Hint:

Run 1 did not use any skills.

Run 2 used the official Storyblok skills package.

The interactions

Run 1 made every decision without any input. Run 2 asked before deciding where the schema should live, presented a full content model plan, and waited for confirmation before writing anything to Storyblok.

Run 2 began by asking where the schema location should live, in Storyblok only, or in code (asking should it create the models directly in the space, or should it generate them using the Storyblok Schema package and save it to the current project).

Once the this was confirmed and the agent did some Flibbertigibbeting, it presented a content model plan block by block, field by field, and asked for confirmation on proceeding. This is point of the run where the user can review the proposed schema and provide feedback/make changes that might better fit their needs.

After confirming and the agent has done some Discombobulating, it asks a final question: if it should only generate the schemas like was asked or also generate the content. To reach the goal, only the schema is needed.

Run 1 did some noodling the **entire way through without asking for any input on its decisions.

Decision point

Run 1

Run 2

Schema location (UI vs. code)

Not asked, went straight at the space

Asked directly; Storyblok UI was chosen

Content model plan

Not presented, went straight to createComponent calls

Full plan presented field by field; execution paused for confirmation

Scope: schema only, or schema plus content

Not asked, proceeded straight into stories after the schema

Asked directly: schema and content, schema only, or revise first. Schema only was chosen

Blocks generated

Run 1 generated 15 blocks (three content types and 12 nestable blocks), a datasource, and left the four original demo blocks in the space. Run 2 generated 14 blocks (two content types and 12 nestable blocks), the same datasource, left three of the four demo blocks alone, and took the existing feature block, extended it, and reused it instead of creating a new benefit block.

Role

Run 1

Run 2

Product page (content type)

product_page (see below)

product_page (see below)

Customer profile (content type)

customer (full_name, role, location, portrait, bio)

customer (full_name, role, location, photo)

Site-wide config (content type)

site_config (free shipping threshold, currency, shipping note)

None, shipping terms live inside a section block

Benefit item (nestable)

benefit (title, description, icon asset)

The existing feature block was extended and reused (title, description, icon - list tied to front end svgs: motor, sensor, cable, tool)

Box-contents item (nestable)

box_item (item, note)

box_item (name, description, image)

Value Proposition

value_proposition

value_proposition (What we’re selling, Why it matters, The payoff)

Finish and price pair (nestable)

finish_option (finish, price, swatch, available at launch)

product_variant (finish, price, swatch)

Spec row (nestable)

spec (label, value)

spec_row (label, value)

Review (nestable)

review (customer, rating option, quote, headline)

review (customer, rating number, quote)

Shared UI (nestable)

None

button (label, link, variant), whitelisted in hero and pricing

Finish datasource

desk-finishes (three entries)

desk-finishes (three entries)

Existing blocks extended

None

feature, given a description field and a four-value icon option list

Left untouched

page, feature, grid, teaser

page, grid, teaser

Run 2 read the space first and recognized that a benefit block on a product page was similar to a feature, so it added a description , textarea , and icon option list to feature and added it to the accepted blocks list within benefit_list. Run 1 built benefit with a near-identical shape and left feature next to it, unused: nothing in Run 1's model references feature at all.
Not only that, but Run 2 also built a shared button block (label, multilink, and a primary or secondary variant) and added it to the accepted blocks list in both hero and pricing. Run 1 didn't give any section a call to action, so link and button fields are repeated across block definitions.

The product page

Both runs named the content type product_page, kept it generic instead of scoping it to the Crest line, and composed the page out of section blocks in a body field with a specified acceptable block list. In the previous comparison, the unskilled run kept the whole product page as one long, flat list of ungrouped fields. This time Run 1 organized the page too, so the difference comes down to what each run recognized in the brief.

Concept

Run 1: product_page

Run 2: product_page

Hero

Tab: Content title (text, required, max 80) tagline (text, max 160) hero_image (asset, images) intro (richtext)

title (text, required) summary (textarea) image (asset, images) Block: hero headline (text, required) intro (textarea) image (asset) buttons (blocks → button)

Launch date

launch_date (datetime, date only, required)

launch_date (datetime, date only)

Market

Not modeled

Not modeled

Target audience

Not modeled

Not modeled

Value proposition

Block: value_proposition

Block: value_proposition

Benefits

Block: benefit_list headline (text) benefits (blocks → benefit, required, min 1)

Block: benefit_list heading (text) intro (textarea) benefits (blocks → feature)

Box contents

Block: box_contents headline (text, default "What's in the box") items (blocks → box_item, required, min 1)

Block: whats_in_the_box heading (text) intro (textarea) items (blocks → box_item)

Subscription

purchase_type (option: One-time purchase or Subscription, required)

Not modeled

Shipping

site_config content type: free_shipping_threshold (number) shipping_note (text)

pricing block: fine_print (richtext)

Currency

currency (option, one value: USD) on both product_page and site_config

Not modeled, USD is stated in a field description

Price / finish

Finishes & pricing (blocks → finish_option, required, min 1), on the Commerce tab

variants (blocks → product_variant)

Specs

Block: spec_table (blocks → spec, required, min 1)

Block: spec_table (blocks → spec_row)

Reviews

Block: review_list (blocks → review, required, min 1)

Block: review_list (blocks → review)

Related products

Block: related_products headline (text, default "More from the Crest line") products (options, internal_stories → product_page, use_uuid, min 1)

Block: related_products heading (text) products (options, internal_stories → product_page)

Page composition

body (blocks → the seven section blocks)

body (blocks → the seven section blocks)

Editor organization

Two tab fields: Content and Commerce

None

Notice that although, they are similar in some areas, Run 2 recognized this as a product brief and only created what was in scope. Run 1 made assumptions and misread content in the brief.

The brief mentions the price and that it's a "one-time purchase, no subscription." The agent saw that subscription was mentioned and added purchase_type, a required option list with two values: One-time purchase and Subscription. But the brief was saying no subscription is available, it's only a one-time purchase. Now an author has to pick between the two on every product page in order to publish it, but the concept of a subscription doesn’t even exist.

Run 1 also added fields the brief never mentions. The prices in the brief are in dollars, and Run 1 turned that into a currency field with one option, USD, twice: once in product_page and once in site_config. It added an available_at_launch boolean to each finish, and a show_prices boolean on finish_showcase that hides prices stored on a different block. Not only that, but every field on the page is required with at least one entry. An author has to add benefits, box contents, finishes, specs, and reviews before the page passes validation, so a new product with no reviews yet can’t even be published.

Run 2 generated fewer fields and picked better field types for them. The rating is a number from 1 to 5, so it can be sorted and averaged. Run 1 stored it as an option list, so "5" is saved as text. The brief lists four core benefits, and Run 2 turned those into a four-value icon option list on feature (motor, sensor, cable, tool) that the frontend maps to its own icons. Run 1 made icon an asset field, so the icons have to be uploaded and live in Storyblok.

Scalability

Both schemas are meant to serve more than one desk. product_page is written in each run as the one shared content type for Crest Mini, Crest Pro, and Crest Desk alike, but that intent holds up differently once another product needs to use it.


Run 1

Run 2

Shared root content type across the line

Yes, product_page

Yes, product_page

Datasource naming

desk-finishes, reusable across the catalog

desk-finishes, reusable across the catalog

A new finish

One entry, no schema change

One entry, no schema change

Near-duplicate blocks left in the space

Yes

No

Shared CTA styling

No button block, every section invents its own links

One button block, two reuse sites

Result

Run 1 created a working schema without any user input. The schema suffers from modeling more than the brief asks for. The result is a duplicate block, a required subscription option for a choice that doesn't exist, a one-value currency field in two places, two booleans the brief never mentions, and assumed required entry in every section of the page.

Run 2 created a similar page but handed the power and ownership over to the user. It presented it’s plans, steps, and asked for input and confirmation before proceeding to make real changes. So regardless if it created a schema that perfectly fits the needs of the user, the user has the control and can iterate on the plan with the agent before it is written to Storyblok. Regardless, it still built the cleaner model. It extended feature instead of creating a new block, built one shared button, typed the rating as a number, and only created what was in scope. The gaps it did leave are the kind a user catches while reviewing the plan, before anything is written to Storyblok.

Every judgment call made in Run 2: reuse over duplication, reference over nest, additive over destructive, content-type over block, datasource over hardcoded list, is something an experienced Storyblok developer already does by habit. This skill makes an agent do the same, probabilistically, run after run, even when it's told not to stop and ask.

Get the skills

To make use of the skill library in your projects, simply install the Storyblok Agent Plugin; it sets up everything your agent needs to perform at the level of an experienced Storyblok Developer.

We want your feedback

We would love to hear back from you on how you use these skills and how they are working for you! Let us know in our Discord.