The CWA is in heavy development
The CWA is still in alpha and not ready for production - some code and implementations are likely to change. If you would like to try out the CWA, please enjoy what we have provided and feel free to provide feedback, or get involved on GitHub.
DraftComponent Helpers

Collections & Pagination

Render paginated resource lists with useCwaCollectionResource and bind page navigation to the URL query string.

The Collection built-in component proxies any resource collection endpoint. On the front-end, useCwaCollectionResource unwraps the Hydra response and gives you items, pagination state, and navigation helpers — all URL-bound.

Display Component

<!-- app/cwa/components/BlogList/BlogList.vue -->
<template>
    <div>
        <div v-if="isLoadingCollection" class="space-y-4">
            <div v-for="n in 6" :key="n" class="h-48 bg-gray-100 animate-pulse rounded" />
        </div>

        <div v-else class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
            <ArticleCard
                v-for="item in collectionItems"
                :key="item['@id']"
                :article="item.data"
                :href="resolveResourceLink(item)"
            />
        </div>

        <div v-if="totalPages > 1" class="flex items-center justify-center gap-4 mt-8">
            <button
                :disabled="!pageModel || pageModel <= 1"
                class="btn"
                @click="goToPreviousPage"
            >
                Previous
            </button>

            <span class="text-sm text-gray-600">
                Page {{ pageModel }} of {{ totalPages }}
            </span>

            <button
                :disabled="pageModel >= totalPages"
                class="btn"
                @click="goToNextPage"
            >
                Next
            </button>
        </div>
    </div>
</template>

<script setup lang="ts">
import { toRef } from 'vue'
import type { IriProp } from '#cwa/composables/cwa-resource'
import { useCwaCollectionResource } from '#imports'
import { resolveResourceLink } from '@cwa/nuxt/runtime/utils'

const props = defineProps<IriProp>()

const {
    getResource,
    exposeMeta,
    collectionItems,
    isLoadingCollection,
    totalPages,
    pageModel,
    goToNextPage,
    goToPreviousPage
} = useCwaCollectionResource(toRef(props, 'iri'))

const resource = getResource()
defineExpose(exposeMeta)
</script>

Return Values

ReturnTypeDescription
collectionItemsComputedRef<Resource[]>The hydra:member array — each item is a full resource
isLoadingCollectionComputedRef<boolean>true while the proxied collection fetch is in progress
totalPagesComputedRef<number>Computed from hydra:totalItems ÷ perPage
pageModelRef<number>Current page number — bound to the URL ?page= query param
goToNextPage() => voidIncrements pageModel
goToPreviousPage() => voidDecrements pageModel (min: 1)
changePage(page: number) => voidJump to a specific page

collectionItems is always an array — never null — so v-for won't error during loading.

Numbered Pagination

Use useCwaCollectionPagination to generate a page number list with ellipsis markers for long ranges:

import { useCwaCollectionPagination } from '#imports'

const { pages } = useCwaCollectionPagination(totalPages, pageModel)
// pages.value → [1, 2, '...', 8, 9, 10] when on page 1 of 10
<nav class="flex gap-1">
    <button
        v-for="p in pages"
        :key="p"
        :disabled="p === '...'"
        :class="p === pageModel ? 'font-bold' : ''"
        @click="typeof p === 'number' && changePage(p)"
    >
        {{ p }}
    </button>
</nav>

Linking to a Resource's Page

resolveResourceLink looks up the Route whose PageData IRI matches the item, and returns the path:

import { resolveResourceLink } from '@cwa/nuxt/runtime/utils'

// In template
:href="resolveResourceLink(item)"

This is how you turn a collection item into a <NuxtLink> without knowing its URL in advance.

User-Controlled Sorting and Filtering

useQueryBoundModel binds any query parameter to the URL, triggering a re-fetch when it changes:

import { useQueryBoundModel } from '#imports'

const sortOrder = useQueryBoundModel('order[createdAt]', 'desc')
// Changing sortOrder.value updates ?order[createdAt]=... in the URL
<select v-model="sortOrder">
    <option value="desc">Newest first</option>
    <option value="asc">Oldest first</option>
</select>

The collection re-fetches automatically when the URL changes. Default query parameters set in the PHP Collection entity are the baseline; useQueryBoundModel lets users override them.

Admin: Setting Up a Collection

The manager tab (auto-provided by the built-in Collection entity) lets admins:

  1. Select which resource to list (resourceIri — searchable dropdown)
  2. Set perPage — how many items per page
  3. Configure defaultQueryParameters — default sort and filter values

No custom admin tab file needed for the standard Collection component — it's provided by the bundle.