Skip to content
On this page

Kirby Blocks


The Kirby Nuxt Starter Kit provides a <KirbyBlocks /> component for you with a set of blocks which you can use as well.

Consider the following Nuxt page below, illustrating how to query Kirby Blocks.

For demonstration purposes, only heading and image blocks are parsed. Using a v-for directive we iterate over each block and read out its content property – like content.level and content.text of a heading. For every other block, existence of the text content key is assumed.

Typings are optional to use, but will improve your editor suggestions and reduce type errors.

<script setup lang="ts">
// `#nuxt-kql` may find a special place in your heart just for providing types
import { KirbyBlock } from '#nuxt-kql'

// Select page content needed for a simple page
const { data } = await useKql({
  query: 'page("notes/across-the-ocean")',
  select: {
    id: true,
    title: true,
    // That is where the magic happens
    text: 'page.text.toBlocks',

// Shorthand getter for the nested `text` object key inside the query result
// We type the response, since we know its more than just `any`
const blocks = computed<KirbyBlock<string>[]>(() => data.value?.result?.text ?? [])

    <h1>{{ data?.result?.title }}</h1>

    <div class="prose">
      <!-- Iterate over each block -->
      <template v-for="(block, index) in blocks" :key="index">
        <!-- Handle the heading block -->
        <component :is="block.content.level" v-if="block.type === 'heading'">
          <!-- Type cast the block as heading for the correct `content` typings -->
          {{ (block as KirbyBlock<'heading'>).content.text }}

        <!-- Handle the image block -->
          v-else-if="block.type === 'image'"
          :src="(block as KirbyBlock<'image'>).content.url"

        <!-- Output text if it exists on any other block -->
        <div v-else v-html="block.content?.text" />

Released under the MIT License.