Customer Story
A reusable customer profile and an embedded quote express two distinct relationships in a small, complete model set.
A team wants to explain how its work helped a customer. The customer may appear in several stories. A quotation should retain the attribution and context approved for a particular story.
Those needs give us three models: Customer Story, Customer and Quote. The story is an independently managed entry. Its customer has a reusable identity. Its quote is an optional embedded structure.
See the relationships
Section titled “See the relationships”| Relationship | Field | Behaviour |
|---|---|---|
| Customer Story → Customer | customer |
Linked reference · required |
| Customer Story → Quote | quote |
Embedded object |
The customer field requires one Customer reference. This does not limit the number of stories that can refer to that same customer. The quote field is optional; when a quote is present, its text and attribution are required by the Quote model.
Why these boundaries?
Section titled “Why these boundaries?”Link the customer. A customer profile has its own identity and can be updated independently. Changing a logo or website should not require editing every story.
Embed the quote. Its wording and attribution belong to the context of this story. Reuse the Quote structure across stories while keeping each story’s values separate. If quotations need an independent approval process, reuse or lifecycle, revisit that decision and consider a reference instead.
Keep the story focused. The fields capture a title, URL identifier, listing summary, narrative, customer and optional quote. Publication workflows, consent records and permissions still need decisions in the implementation; this example does not claim to model those processes.
Download and work with the set
Section titled “Download and work with the set”Download the complete Customer Story project · Download the Studio import JSON
The ZIP contains model YAML, a manifest, the pinned schema, a dependency lockfile, a local validator and the same JSON bundle. Use Node 22.12+ to run npm ci and npm run validate from the extracted folder. The first dependency installation needs an internet connection; validation then runs locally.
Build your first model step by step or inspect and edit it in Studio.
Complete source files
Section titled “Complete source files”These are complete model definitions generated into this page from the downloadable source files. They describe the structure of future content, rather than actual customer entries or a finished story.
Manifest
Section titled “Manifest”specVersion: "1.2.0"namespace: example.customer-storymodelsPath: ./modelsdefaults: required: false localisation: falseCustomer Story
Section titled “Customer Story”id: customer-storyname: Customer Storykind: entrydescription: Evidence of a customer outcome, told through a specific challenge, response and result.fields: - id: title name: Title type: string required: true validations: minLength: 5 maxLength: 100 editorial: helpText: Lead with the outcome rather than the name of a product.
- id: slug name: Slug type: slug required: true editorial: helpText: A readable identifier for this story's URL. Agree uniqueness rules with the implementation.
- id: summary name: Summary type: text validations: maxLength: 250 editorial: helpText: Explain the result in a sentence or two for listings and previews.
- id: story name: Story type: richText required: true richTextConfig: marks: [bold, italic, link] blocks: [paragraph, heading-2, unordered-list, quote] editorial: helpText: Describe the challenge, the response and the evidence for the outcome.
- id: customer name: Customer type: reference required: true list: false targets: [customer] relation: ownership: linked editorial: helpText: Choose the reusable customer profile behind this story.
- id: quote name: Quote type: object objectType: quote editorial: helpText: Include an approved quote in its original context. Omit the quote when none is available.
editorial: labelField: title preview: title: title description: summarygovernance: owner: content-team maturity: proposedCustomer
Section titled “Customer”id: customername: Customerkind: entrydescription: A reusable organisation profile that can be linked from more than one customer story.fields: - id: name name: Name type: string required: true validations: maxLength: 100
- id: website name: Website type: string editorial: helpText: The customer's public website. URL validation is an implementation decision.
- id: logo name: Logo type: asset validations: mimeTypes: [image/png, image/svg+xml]
editorial: labelField: name preview: title: name image: logoid: quotename: Quotekind: objectdescription: A quotation and attribution embedded in one customer story, rather than a separately maintained content item.fields: - id: text name: Text type: text required: true validations: maxLength: 500
- id: attribution name: Attribution type: string required: true validations: maxLength: 100
- id: role name: Role type: string validations: maxLength: 100
editorial: labelField: attributionImplementation decisions still to make
Section titled “Implementation decisions still to make”Agree how the target CMS represents an embedded Quote, enforces a single required customer link and supports the declared rich-text capabilities. Record URL uniqueness, quote approval and any unsupported constraints in the implementation decisions log.
The build validates these three models together against the pinned CMMF 1.2.0 schema, IDs, targets, editorial fields and constraint bounds. It does not validate the factual accuracy of a story, approval to publish a quotation or any particular CMS mapping.