fix createContentHelpers.ts

This commit is contained in:
2026-09-15 22:16:01 +02:00
parent b27031f7c4
commit 988fcaf855
4 changed files with 180 additions and 133 deletions
+80 -70
View File
@@ -141,79 +141,89 @@ import { buildRobots, buildSitemapEntries } from '../seo/index.js';
* // app/(frontend)/[[...slug]]/page.tsx (or [locale]/[[...slug]])
* export { generateStaticParams } from '@/lib/content'
*/ const generateStaticParams = async ()=>{
const payload = await getCachedPayload();
const locales = i18n ? i18n.locales.map((l)=>l.code) : [
undefined
];
const singleLocale = !i18n || i18n.locales.length === 1;
// Home slug per locale, to exclude the homepage (it's the root, slug []).
const settings = await payload.findGlobal({
slug: settingsSlug,
depth: 1,
locale: 'all'
}).catch(()=>null);
const homeId = settings?.homepage?.id;
const EXCLUDED = new Set([
'404',
'500',
'error',
'not-found'
]);
const params = [];
for (const locale of locales){
// NO where:{_status} filter — collections without drafts enabled don't
// register the _status field, and querying it throws
// "path cannot be queried: _status". We filter drafts in memory below,
// which is safe for every collection (with or without drafts).
const result = await payload.find({
collection: pagesSlug,
depth: 0,
limit: 1000,
locale: locale ?? 'all'
});
for (const raw of result.docs){
// Draft filter in memory (safe whether or not the collection has drafts).
if (raw._status && raw._status !== 'published') {
continue;
}
// NOTE: unlike the sitemap, we do NOT skip meta.noindex here. A noindex
// page (privacy, cookies, terms) still needs to render — users reach it
// from the footer and crawlers read its <meta robots=noindex>. Pre-render
// it as SSG so it's fast and its <head> is complete; noindex controls
// INDEXING, not whether the page exists. Skipping it would force dynamic
// rendering (the very streaming problem we're avoiding).
if (homeId && raw.id === homeId) {
// Homepage → root. Emit an empty-slug param so '/' (or '/pl') builds.
const empty = singleLocale ? {
slug: []
} : {
slug: [],
locale: locale
};
if (!params.some((p)=>JSON.stringify(p) === JSON.stringify(empty))) {
params.push(empty);
}
continue;
}
// Slug may be a plain string OR a localized map ({ pl: 'kontakt' }) when
// read with locale:'all' or left unflattened. Handle both, or localized
// pages get silently dropped.
const rawSlug = raw.slug;
const slug = typeof rawSlug === 'string' ? rawSlug : rawSlug && typeof rawSlug === 'object' ? rawSlug[locale ?? ''] ?? Object.values(rawSlug)[0] : undefined;
if (!slug || EXCLUDED.has(slug)) {
continue;
}
// Multi-level slugs ('atrakcje/telefon') → array segments.
const segments = String(slug).split('/').filter(Boolean);
params.push(singleLocale ? {
slug: segments
} : {
slug: segments,
locale: locale
try {
const payload = await getCachedPayload();
const locales = i18n ? i18n.locales.map((l)=>l.code) : [
undefined
];
const singleLocale = !i18n || i18n.locales.length === 1;
// Home slug per locale, to exclude the homepage (it's the root, slug []).
const settings = await payload.findGlobal({
slug: settingsSlug,
depth: 1,
locale: 'all'
}).catch(()=>null);
const homeId = settings?.homepage?.id;
const EXCLUDED = new Set([
'404',
'500',
'error',
'not-found'
]);
const params = [];
for (const locale of locales){
// NO where:{_status} filter — collections without drafts enabled don't
// register the _status field, and querying it throws
// "path cannot be queried: _status". We filter drafts in memory below,
// which is safe for every collection (with or without drafts).
const result = await payload.find({
collection: pagesSlug,
depth: 0,
limit: 1000,
locale: locale ?? 'all'
});
for (const raw of result.docs){
// Draft filter in memory (safe whether or not the collection has drafts).
if (raw._status && raw._status !== 'published') {
continue;
}
// NOTE: unlike the sitemap, we do NOT skip meta.noindex here. A noindex
// page (privacy, cookies, terms) still needs to render — users reach it
// from the footer and crawlers read its <meta robots=noindex>. Pre-render
// it as SSG so it's fast and its <head> is complete; noindex controls
// INDEXING, not whether the page exists. Skipping it would force dynamic
// rendering (the very streaming problem we're avoiding).
if (homeId && raw.id === homeId) {
// Homepage → root. Emit an empty-slug param so '/' (or '/pl') builds.
const empty = singleLocale ? {
slug: []
} : {
slug: [],
locale: locale
};
if (!params.some((p)=>JSON.stringify(p) === JSON.stringify(empty))) {
params.push(empty);
}
continue;
}
// Slug may be a plain string OR a localized map ({ pl: 'kontakt' }) when
// read with locale:'all' or left unflattened. Handle both, or localized
// pages get silently dropped.
const rawSlug = raw.slug;
const slug = typeof rawSlug === 'string' ? rawSlug : rawSlug && typeof rawSlug === 'object' ? rawSlug[locale ?? ''] ?? Object.values(rawSlug)[0] : undefined;
if (!slug || EXCLUDED.has(slug)) {
continue;
}
// Multi-level slugs ('atrakcje/telefon') → array segments.
const segments = String(slug).split('/').filter(Boolean);
params.push(singleLocale ? {
slug: segments
} : {
slug: segments,
locale: locale
});
}
}
return params;
} catch (err) {
// DB unreachable — typically a container build (Docker/Coolify/CI) with no
// database network. Return [] so the build doesn't crash: Next falls back
// to on-demand rendering for the routes, which fill in once the DB is
// reachable at runtime. Without this every project would need its own
// try/catch here. (Same graceful-degradation as the sitemap handler.)
console.warn('[ipal] generateStaticParams: database not reachable during build ' + '(Docker/CI) — returning empty params; routes render on-demand at runtime:', err);
return [];
}
return params;
};
return {
generateStaticParams,