Files
blog/frontend/server/utils/queries.ts
T
davide a808f1010f Add Nuxt frontend with blog index, article and category pages
The browser never talks to Strapi: pages call Nitro endpoints under
server/api/, which are the only place Strapi queries are built. That keeps the
Strapi URL internal to the Docker network and avoids CORS entirely.

Article bodies are rendered from Markdown to HTML in the endpoint, so the
content is server-rendered and crawlable, marked stays out of the client
bundle, and the meta description is derived from the opening of the body.

Pages carry canonical URLs, Open Graph tags and BlogPosting structured data,
and handle empty, missing and failed states.
2026-08-25 11:42:17 +02:00

31 lines
1.1 KiB
TypeScript

/** Strapi query fragments. Only the fields the pages actually render are requested. */
const list = (prefix: string, names: readonly string[]) =>
names.map((name, i) => `${prefix}[${i}]=${name}`).join('&')
const IMAGE_FIELDS = ['url', 'alternativeText', 'width', 'height'] as const
export const ARTICLE_SUMMARY_QUERY = [
list('fields', ['title', 'slug', 'publishedAt']),
list('populate[cover][fields]', IMAGE_FIELDS),
list('populate[category][fields]', ['name', 'slug']),
'sort[0]=publishedAt:desc',
].join('&')
export const ARTICLE_DETAIL_QUERY = [
list('fields', ['title', 'slug', 'content', 'publishedAt']),
list('populate[cover][fields]', IMAGE_FIELDS),
list('populate[category][fields]', ['name', 'slug']),
].join('&')
export const PAGE_SIZE = 12
export const pagination = (page: number, pageSize = PAGE_SIZE) =>
`pagination[page]=${page}&pagination[pageSize]=${pageSize}`
/** Reads a positive integer query param, falling back to 1. */
export const pageParam = (value: unknown): number => {
const page = Number(value)
return Number.isInteger(page) && page > 0 ? page : 1
}