useXAFContentQuery
useXAFContentQuery
Generic content query state manager for the review-site family. Accepts a fetcher function and returns reactive pagination, loading, and error state. The composable is source-agnostic — the fetcher can call Nuxt Content's queryContent(), a custom API endpoint, or a static array filter.
useXAFContentQuery itself is auto-imported. The typed wrappers (useXAFReviews, useXAFArticles, useXAFCategories, useXAFSearch) are exported from the same file but are not auto-imported (multi-export file) — import them explicitly when you need them.
Usage
const { items, loading, error, page, hasMore, nextPage } = useXAFContentQuery(
async ({ page, perPage }) => {
const items = await queryContent('reviews')
.skip((page - 1) * perPage)
.limit(perPage)
.find()
return { items, total: 100 }
},
{ perPage: 12 },
)
Parameters
| Param | Type | Description |
|---|---|---|
fetcher | (params: { page, perPage, sortBy?, sortOrder?, filter? }) => Promise<{ items: T[], total: number }> | Async function returning the current page of items plus the total count. |
options.page | number | Initial page (1-indexed). Default 1. |
options.perPage | number | Items per page. Default 12. |
options.sortBy / options.sortOrder | string / 'asc' | 'desc' | Sort hints passed through to the fetcher. |
options.filter | Record<string, unknown> | Arbitrary filter object passed through to the fetcher. |
Returns
| Key | Type | Description |
|---|---|---|
items | Ref<T[]> | Fetched items for the current page. |
loading | Ref<boolean> | Whether a fetch is in-flight. |
error | Ref<string | null> | Error message, or null when idle/success. |
total | Ref<number> | Total items across all pages (as reported by the fetcher). |
page / perPage | Ref<number> | Current page (1-indexed) and page size. |
hasMore | ComputedRef<boolean> | true when there are more pages to fetch. |
refresh() | () => Promise<void> | Re-fetch the current page. |
nextPage() / prevPage() | () => Promise<void> | Advance / go back one page (no-op at the bounds). |
setPage(p) | (p: number) => Promise<void> | Jump to an arbitrary page. |
Typed wrappers
Same file, explicit import required:
import { useXAFReviews, useXAFSearch } from '@xenterprises/nuxt-x-affiliate/app/composables/useXAFContentQuery'
// Reviews: defaults sortBy "publishedAt" desc; options: { category, minRating, perPage, sortBy, sortOrder, filter }
const reviews = useXAFReviews(fetcher, { category: 'keyboards', minRating: 4 })
// Articles: options: { tag, author, perPage, sortBy, sortOrder, filter }
const articles = useXAFArticles(fetcher, { tag: 'testing' })
// Categories: same pagination shape, typed for XAFCategoryItem
const categories = useXAFCategories(fetcher)
// Search: debounced (300ms default), minChars 2, limit 24
const { hits, search, clear } = useXAFSearch(
async (query) => ({ hits: await $fetch('/api/search', { query: { q: query } }), total: 42 }),
{ debounceMs: 300, minChars: 2, limit: 24 },
)
AI Context
composable: useXAFContentQuery
package: "@xenterprises/nuxt-x-affiliate"
use-when: >
Paginated listing pages (/reviews, /articles, category indexes) and
search. Source-agnostic fetcher pattern; returns reactive items /
loading / error / page / hasMore state. Typed wrappers useXAFReviews,
useXAFArticles, useXAFCategories, useXAFSearch live in the same file
and need explicit imports (multi-export file, not in the auto-import
preset).
useXAFConsentTracking
Reads app.config.xAffiliate.tracking and dynamically injects GTM / GA4 / Clarity / custom scripts only after the matching consent category is granted. Used by <XAFCookieConsent> and the xaf-consent-tracking.client.ts plugin.
Configuration
app.config.ts reference for @xenterprises/nuxt-x-affiliate — covers xAffiliate (dashboard + brand + author + legal + tracking) and xAffiliateContent (merchants + currency).
