Skip to main content

<CmsPageRenderer>

Renders a CmsPage's block list. Each block is dispatched through the renderers map by its block.type discriminator.

<script setup lang="ts">
import { CmsPageRenderer } from 'propeller-v2-cms-vue';
import HeroBlock from '@/components/cms/HeroBlock.vue';

defineProps<{ page: CmsPage }>();
const renderers = { hero: HeroBlock };
</script>

<template>
<CmsPageRenderer :page="page" :renderers="renderers" />
</template>

Props

PropTypeRequiredNotes
pageCmsPageyesThe page object returned by adapter.getPage(slug).
renderersRecord<string, Component>yesMap keyed by block.type. Values are Vue components.
fallbackComponent | nullnoComponent rendered for unknown block types. Default: null (skipped silently).
classstringnoFalls through to the wrapper <div>.

Block component contract

Each entry in renderers is a Vue component that receives the block as :block:

<!-- HeroBlock.vue -->
<script setup lang="ts">
import type { CmsBlockShape } from 'propeller-v2-cms-vue';
defineProps<{ block: CmsBlockShape }>();
</script>

<template>
<section class="hero">
<h1>{{ block.data.headline }}</h1>
</section>
</template>

If you'd rather destructure block.data, do it inside the component; the renderer always passes the full block.

What it does NOT do

  • No client-side fetching. The page must already be loaded; pass it as a prop. Use useCms() if you want to fetch inside a component.
  • No block-level loading / error states. Blocks are synchronous renders. If a block needs its own async data (a product carousel hitting the commerce API), build that into the block component.
  • No layout opinions. Blocks render in document order inside the wrapper <div>. Style the wrapping element via the fall-through class attribute.

Sharing the renderers map

Define the map once, reuse it across pages and any standalone <CmsBlock> calls:

// cms/renderers.ts
import HeroBlock from '@/components/cms/HeroBlock.vue';
import TextBlock from '@/components/cms/TextBlock.vue';

export const cmsRenderers = { hero: HeroBlock, text: TextBlock };