Contentful
Overview
Contentful is a highly scalable, API-first headless CMS platform designed for large volumes of complex, structured content. The SCAYLE Storefront Application includes a comprehensive, production-ready integration that leverages Contentful's powerful API and content modeling capabilities.
The integration manages API complexity, allowing your team to focus on building and deploying stunning content experiences. You get structured content with strong typing, flexible content modeling, and high-performance delivery.
Key Features
- Content Model Stability: Structured content types with precise developer control and strong
- Inspection Mode: Click-to-edit functionality for direct content editor integration.typing.
- Live Preview: Real-time content editing with instant preview updates in the Contentful editor.
- Component Flexibility: Pre-built component library with automatic component resolution and custom component support.
- Locale Support: Multi-language content with configurable fallback chains and automatic locale detection.
- Type Safety: Automatic TypeScript type generation from Contentful content models.
Quick Links
Getting Started
Prerequisites
Before setting up Contentful, ensure you have the following ready:
- Contentful account: Sign up at contentful.com.
- Contentful space: Create a new space for your new Storefront Application project.
- Access tokens:
- Delivery API token: For fetching published content in production, see Content Delivery API.
- Preview API token: For development and draft content access, see Preview API.
- Management API token: For content model setup and type generation, see Content Management API.
Setup Your Contentful Storefront
The Contentful integration is included with the Storefront Application. To enable and configure it:
Step 1: Run Setup Command
Run the SCAYLE Storefront CLI setup command, passing contentful with the --provider flag:
This command prompts you to:
- Select a CMS provider (choose "contentful").
- Provide your Contentful space ID.
- Provide a Delivery API access token.
- Provide a Preview API access token.
- Provide a Management API access token.
- Specify whether to import the content model.
Importing the content model is only intended for empty CMS spaces. Running it on spaces with existing content may cause issues.
Step 2: Review Configuration
After setup, your nuxt.config.ts will include:
The following environment variables are updated in your local .env file:
CMS_PROVIDER(required during build-time)NUXT_PUBLIC_CMS_SPACE(required during runtime)NUXT_PUBLIC_CMS_ACCESS_TOKEN(required during runtime)NUXT_PUBLIC_CMS_PREVIEW_ACCESS_TOKEN(optional during runtime)CONTENTFUL_MANAGEMENT_TOKEN(required for cli commands)
Step 3: Environment Configuration & Deployment
The Contentful integration leverages Nuxt's RuntimeConfig, which provides flexibility for different deployment environments.
Runtime vs Build-Time Configuration
Unlike traditional build-time configuration, environment variables can be set at runtime. This means:
- During development: Set variables in your
.envfile. - During deployment: Update environment variables on your hosting platform without rebuilding.
- Different environments: Use the same build for development, staging, and production with different variables.
Environment Variables Reference
All Contentful configuration can be set via environment variables:
Production Deployment Checklist
- Use Delivery API token in production (not Preview token)
- Optionally disable Live Preview in production (
_editorModenot in URL) - Use Preview token only in development/staging environments
- Ensure all required environment variables are configured on your hosting platform
- Test content loading in your production environment before going live
Architecture & Integration
Shop Runtime Integration
The runtime integration between Contentful and the Storefront Application uses the contentful, @contentful/rich-text-html-renderer and @contentful/live-preview packages.
The integration additionally relies on the @nuxt/image module (see the Nuxt Image module documentation) to handle images used with Contentful components.
How It Works
Contentful uses a content-type-based architecture where content is built from flexible, reusable content blocks. Each Contentful content type maps to a Vue component in your application, enabling a seamless bridge between your CMS and Storefront.
Content Type Mapping Pattern:
- Contentful content type
TextComponent→ Vue componentTextComponent.vue - Contentful content type
ImageComponent→ Vue componentImageComponent.vue - Contentful content type
SectionComponent→ Vue componentSectionComponent.vue - Contentful content type
ProductListingPageComponent→ Vue componentProductListingPageComponent.vue
Content Organization Architecture
To connect your application with Contentful content, set up the correct content structure in your CMS.
Create the Homepage
Your homepage content must be created with a specific slug to be automatically picked up by the application's routing:
- Contentful Slug:
homepage
Create Locales
Organize your content by locale in Contentful:
- Go to "Settings → Locales".
- Create locales matching your shop codes (e.g.,
de-DE,en-US,de-AT). - Set appropriate fallback chains for locale resolution.
Example Locale Setup:
de-DE(German) - Fallback toen-USde-AT(Austrian) - Fallback tode-DE→en-USde-CH(Swiss) - Fallback tode-DE→en-USen-US(English) - Default fallback
Content Fetching Flow
When a user visits your storefront, the integration follows this flow:
- Route resolves: User navigates to a URL.
- Query construction: The integration builds a Contentful query with the slug and locale.
- Locale detection: Current shop locale is automatically included.
- API request: Content is fetched from Contentful (Delivery or Preview API).
- Component mapping: Contentful entries are mapped to Vue components.
- Rendering: Vue components render the content with proper styling.
Locale & Fallback Strategy
Contentful provides powerful locale fallback capabilities. The integration uses a hybrid approach for optimal performance:
Primary: Contentful's Native Fallback (Recommended)
Configure fallback locales directly in your Contentful space for server-side handling:
- Go to "Settings" → "Locales".
- Set fallback chains for each locale.
- Example:
de-CH→de-DE→en-US.
Benefits:
- Single API request (no retry needed).
- Granular control over fallback chains.
- Content team configures logic in the CMS.
- Handles partial translations elegantly.
Secondary: Application-Level Fallback (Safety Net)
If a locale is unconfigured in Contentful, the integration provides automatic fallback:
- Attempt to fetch content with the shop's configured locale.
- If that fails with a
BadRequesterror, automatically retry without specifying a locale. - Log a warning recommending proper configuration in Contentful.
When this applies:
- Launching in a new market before the locale is configured.
- Testing with locale combinations not yet set up.
- Edge cases during development.
Live Preview Integration
Live Preview enables you to see changes in real-time as you edit content in Contentful:
- Editor detection: The integration detects the
_editorModequery parameter. - Preview API activation: Client switches to Preview API with preview access token.
- Draft content loading: Draft versions are loaded instead of published versions.
- Live updates: Changes in Contentful appear instantly in the preview.
- Deep reactivity: Component updates trigger Vue re-renders automatically.
.png)
Contentful Preview
Configure Preview Access
To display unpublished changes on initial load in the Contentful editor, your access token must have the Preview API permission. If your token doesn't have preview access, unpublished changes appear only after publishing in the editor.
Configure Preview URLs in Contentful
In your Contentful space, configure preview URLs for each content type:
- Go to "Settings" → "Content preview".
- Add preview URL for each content type (e.g.,
http://localhost:3000for local development). - Include the
_editorModequery parameter with the entry's updated timestamp.
Example preview URLs:
.png)
Locale to Path Mapping:
This feature requires a Contentful Premium plan. For details, see Contentful's custom preview tokens documentation.
To map content locales to their respective shops, configure custom preview tokens in your Contentful settings. Custom preview tokens allow you to create locale-specific URL strings and parameters that resolve differently for each locale during preview.
To set up custom preview tokens:
- Go to "Settings → Content preview".
- Scroll to "Custom preview tokens" at the bottom.
- Click "Copy template to clipboard" to get the JSON template.
- Adjust the tokens to map your locales to shop paths:\
This configuration allows preview URLs like https://your-domain.com/{localeToPath[{locale}]}/content/{entry.fields.slug}?_editorMode={entry.sys.updatedAt} to automatically resolve to the correct shop path based on the content's locale.
Enable Inspection Mode for Live Preview
Use data attributes on component root elements to enable click-to-edit functionality:
data-contentful-entry-id: Identifies the entry being editeddata-contentful-field-id: Identifies the specific field being edited
These attributes enable content editors to click directly on content in the preview to edit it.
Test Live Preview
- Create draft content in Contentful.
- Set up preview URL with
_editorModeparameter. - Click "Open preview" in Contentful.
- Verify the preview loads correctly.
- Make changes in Contentful and verify they appear instantly.
Embedding CMS Content in Existing Pages
You can enrich existing Storefront Application pages with CMS-managed sections without converting the entire page to CMS. The Product Listing Page (PLP) demonstrates this pattern:
This pattern lets you add CMS-controlled blocks to any page region while keeping core page logic in your application.
Available Components
The integration provides pre-built components organized by function. These components serve as building blocks for your content. You can explore all components in our UI Component Overview.
Core Content Primitives
| Component | Description |
|---|---|
TextComponent | Text content with flexible heading levels (h1-h4) and paragraphs. |
LinkComponent | Navigable text and image links with proper URL resolution. |
ImageComponent | Optimized images with responsive sizing and aspect ratio. |
VideoComponent | Embed videos with customizable playback controls. |
Interactive & Basic Content Blocks
| Component | Description |
|---|---|
AccordionComponent | Collapsible accordion sections. |
AccordionItemComponent | Individual accordion items with expand/collapse functionality. |
ButtonComponent | Action buttons with configurable styling and link destinations. |
Layout & Structural
| Component | Description |
|---|---|
PageComponent | Top-level page container for full-page content. |
ProductListingPageComponent | Specialized component for category page content. |
SectionComponent | Content container with background image/color support. |
GridComponent | Multi-column layout system for content organization. |
DividerComponent | Visual spacing and divider elements. |
Rich Content
| Component | Description |
|---|---|
RichTextComponent | Contentful rich text with proper formatting and link resolution. |
E-Commerce Specific
| Component | Description |
|---|---|
SliderComponent | Carousel for multiple content items. |
ProductSliderComponent | Product carousel with selectable products. |
RecentlyViewedProductsComponent | Recently viewed products. |
SmartSortingProductsSliderComponent | Configurable product slider that accepts a Smart Sorting Key and additional parameters. |
Guidelines: Content
Using Base Components
The included pre-built components provide all the building blocks needed to create common e-commerce content patterns. Compose flexible sections that adapt to your brand and merchandising needs.
Hero Banner
Combine these components to create an impactful hero banner:
- Use
SectionComponentwith a background image. - Add
TextComponentfor the headline and description. - Include one or more
ButtonComponentinstances for calls-to-action. - Use
DividerComponentfor vertical spacing.
.png)
Structure
-(1)-(1).png)
Category Teasers / Cards
Create a card grid layout:
- Use
GridComponentwith four columns on desktop, two on mobile. - Inside each column, add
SectionComponentwith a background image. - Include
ButtonComponentto link to the category page.
.png)
Structure
-(2).png)
Promotional Slider
Implement a carousel pattern:
- Use
SliderComponentas the container. - For each slide use a
SectionComponentas container. - Add
TextComponentfor each slide title. - Add
DividerComponentas separator. - Include
ButtonComponentto drive users to listings or campaigns.
.png)
Structure
-(1)-(1).png)
Split Image & Text Section
Create a side-by-side layout:
- Use
GridComponentwith two columns on desktop, one on mobile. - First column:
SectionComponentwith background image. - Second column:
TextComponentfor headline/description andButtonComponentfor CTA.
.png)
Structure
-(1)-(1).png)
By combining these base primitives, you can build visually appealing, commerce-relevant sections without custom code.
Creating Content for PLP
The Product Listing Page (PLP) is a main discovery point in the user journey. Our specialized component allows you to seamlessly inject custom, commerce-relevant content before and after your product stream.
Follow these steps to set up content for a specific category:
-(2).png)
-(1).png)
.png)
-(1).png)
.png)
.png)
Congratulations! Your customized PLP content is now ready to go live.
Guidelines: Development
Customizing Existing Components
You can customize existing components by modifying their Vue implementations to match your design system and requirements.
How Component Customization Works
All Contentful components are rendered through the ContentfulComponent registry. To customize a component:
- Locate the component in
modules/cms/providers/contentful/components/. - Modify the Vue component to match your design system.
- Test in Live Preview to verify your changes.
Available Components to Customize
The integration provides a comprehensive set of pre-built components that can be customized:
TextComponent.vue- Customize text rendering and stylingImageComponent.vue- Customize image display and responsivenessButtonComponent.vue- Customize button appearance and interactionsSectionComponent.vue- Customize layout and spacingGridComponent.vue- Customize grid columns and gapsLinkComponent.vue- Customize link styling and behavior- ... and all other available components.
Each component is registered in the ContentfulComponent (see the "Nested Components" section for details on how this registry works).
To customize any component, navigate to modules/cms/providers/contentful/components/ and modify the Vue implementation to match your brand and design requirements.
Nested Components
Contentful content types can reference other content types, creating nested component hierarchies. The ContentfulComponent serves as the central registry that maps all Contentful content types to their corresponding Vue components.
How ContentfulComponent Works:
The ContentfulComponent is a dynamic component dispatcher that:
- Receives a Contentful entry (content element) as a prop
- Examines the entry's content type
- Renders the appropriate Vue component based on the content type
- Passes the entry data to the mapped component
This allows you to build deeply nested content structures where any content type can contain references to other content types, and they'll all render correctly without needing to know about each other.
Example - Nested Content:
Components can contain other components via reference fields:
The ContentfulComponent Registry:
Under the hood, ContentfulComponent.vue contains a series of conditional branches that determine which Vue component to render:
Benefits of This Pattern:
- Flexibility: Build complex content hierarchies with any combination of components.
- Reusability: Components don't need to know about each other, just about
ContentfulComponent. - Maintainability: Add new components to one central place (the registry).
- Type Safety: Type guards (e.g.,
isTypeTextComponent) ensure correct component rendering. - Fallback Handling: Unknown component types display a helpful message instead of breaking.
Building New Components
Creating new Contentful components allows you to extend the pre-built library with custom functionality.
Step 1: Define Content Type in Contentful
- Go to your Contentful space → "Content model".
- Click "Add content type".
- Define the content structure with appropriate fields (text, images, references, etc.).
- Publish the content type schema.
Step 2: Generate TypeScript Types
After defining your content type, generate types by running the cms:sync command from your Storefront Application root directory:
This command:
- Exports content schema from your Contentful space.
- Generates TypeScript types automatically.
- Organizes types in
modules/cms/providers/contentful/types/gen/.
What Gets Generated
The cms:sync command generates:
- Content type interfaces: Full TypeScript definitions for all Contentful content types.
- Type files: Organized in
modules/cms/providers/contentful/types/gen/. - Type guards: Ready-to-use type checking utilities (e.g.,
isTypeMyBannerComponent).
Generated Type Example
After running pnpm cms:sync, your component types are automatically available:
Import Generated Types
Use the auto-generated types in your Vue components:
Never manually edit files in modules/cms/providers/contentful/types/gen/. These are auto-generated and will be overwritten when you run pnpm cms:sync again.
Step 3: Create Vue Component
Create a corresponding Vue component in your application. Components receive a contentElement prop containing the Contentful entry data:
Step 4: Register Component
Register the component in ContentfulComponent.vue to make it renderable:
Best Practices
Content Organization
- Use consistent naming: Follow a clear naming convention for content types and fields.
- Organize with references: Use reference fields to create reusable content blocks.
- Leverage validation: Use Contentful's field validations to ensure content quality.
- Document content models: Add descriptions to content types and fields for team clarity.
Translation Workflow
- Configure fallback locales: Set up fallback chains in Contentful for optimal performance.
- Create default locale first: Start with one locale as the source of truth.
- Use Contentful's translation features: Leverage built-in translation workflows.
- Review process: Implement a review process for translated content before publishing.
- Test across locales: Verify content displays correctly in all locales.
Performance
- Use lazy loading: Enable
lazy: truefor below-the-fold content. - Optimized images: Use the existing image component provided.
- Leverage caching: Use unique cache keys for proper deduplication.
- Monitor payload size: Keep content payloads small by selecting only needed fields.
- Use Contentful's native fallback: Configure fallback locales in Contentful for single API call.
SEO Considerations
- Unique meta tags: Ensure each page has unique meta titles and descriptions.
- Structured data: Add structured data fields to content types when appropriate.
- Canonical URLs: Set canonical URLs appropriately for each page.
- Sitemap: Generate sitemaps that include CMS-managed pages.
- Hreflang tags: Implement hreflang tags for multilingual SEO.
Development Workflow
- Use Live Preview: Enable Live Preview for content editors during development.
- Sync types regularly: Run
pnpm cms:syncafter content model changes. - Test with draft content: Verify draft content displays correctly before publishing.
- Handle errors gracefully: Implement proper error boundaries and fallbacks.
Troubleshooting
Content Not Loading
Problem
Content exists in Contentful but doesn't appear in the application.
Possible causes:
- Configuration is incorrect or missing
- Content is not published in Contentful
- Slug in Contentful doesn't match the query
- Content doesn't exist in the requested locale
Solutions
- Verify
NUXT_PUBLIC_CMS_SPACEandNUXT_PUBLIC_CMS_ACCESS_TOKENare set correctly - Ensure content is published in Contentful
- Check that the slug in Contentful matches the query exactly
- Verify content exists in the requested locale or configure fallback locales
- Check browser console and server logs for error messages
Prevention: Use consistent slug naming conventions and test content in all locales before publishing.
Debugging
Type Errors
Problem
TypeScript errors when using generated types.
Possible causes:
- Generated types are outdated.
- Importing from incorrect path.
- Contentful content model doesn't match expected structure.
Solutions
- Run
pnpm cms:syncto regenerate types. - Verify you're importing from
~/modules/cms/providers/contentful/types. - Ensure Contentful content model matches expected structure.
- Clear TypeScript cache and restart IDE.
Prevention: Run pnpm cms:sync after every content model change in Contentful.
Live Preview Not Working
Problem
Live Preview doesn't load or shows errors.
Possible causes:
- Preview access token is missing or incorrect
_editorModequery parameter is missing- Preview token doesn't have correct permissions
- Content is not in draft state
Solutions
- Verify
NUXT_PUBLIC_CMS_PREVIEW_ACCESS_TOKENis set correctly. - Check that
_editorModeis in the preview URL. - Verify preview token has correct permissions in Contentful.
- Ensure content is in draft state (not published).
- Check application logs for warnings.
Prevention: Test Live Preview setup in development before deploying to production.
Debugging:
Locale Issues
Problem
Wrong locale content is displayed or locale errors occur.
Possible causes:
- Fallback locales are not configured in Contentful.
- Shop locale codes don't match Contentful locale codes.
- Locale is not configured in Contentful space.
Solutions
- Configure fallback locales in Contentful space settings.
- Ensure shop locale codes match Contentful locale codes exactly.
- Verify all required locales are configured in Contentful.
- Check application logs for locale-related warnings.
Prevention: Configure all required locales in Contentful before launching in new markets.
Debugging: