diff --git a/dist/modules/seo/buildSitemapXml.d.ts b/dist/modules/seo/buildSitemapXml.d.ts index ed4e5ed..d52d1a9 100644 --- a/dist/modules/seo/buildSitemapXml.d.ts +++ b/dist/modules/seo/buildSitemapXml.d.ts @@ -1,14 +1,25 @@ import type { SitemapEntry } from './buildSitemapEntries.js'; +type BuildSitemapXmlOptions = { + /** + * URL of a CSS stylesheet to make the sitemap readable in the browser, e.g. + * '/sitemap.css'. Uses `type="text/css"` — the W3C "Associating Style Sheets + * with XML" mechanism, which is NOT deprecated (unlike XSLT / type="text/xsl", + * which Chrome/WebKit are removing). CSS on XML shows no warning, styles the + * raw tags directly (e.g. `url { display: block }` turns the wall of text into + * cards), and crawlers ignore the directive entirely. + */ + cssUrl?: string; +}; /** * Serializes sitemap entries to a clean, indented XML STRING — valid for crawlers - * and readable in the browser as the native XML tree (indented, collapsible, - * syntax-highlighted by the browser itself). + * and (with `cssUrl`) styled in the browser via plain CSS. * - * NO XSLT stylesheet: browsers (Chrome et al.) are REMOVING XSLT support, so a - * approach is a dead end — it shows a deprecation warning now - * and will break soon. Instead we serve plain XML with the correct Content-Type; - * the browser renders its built-in formatted XML view (the "code tree" look) with - * no transformation needed. + * Two viewing modes: + * - No cssUrl → the browser's native formatted XML tree (indented, collapsible). + * - With cssUrl → a `` directive; the project's + * CSS styles the XML tags (cards, labels via ::before). NOT XSLT — that's being + * removed from browsers and shows a deprecation warning. CSS is safe and + * W3C-standard. * * // app/sitemap.xml/route.ts * import { buildSitemapXml } from '@intecion/ipal-kit' @@ -16,16 +27,19 @@ import type { SitemapEntry } from './buildSitemapEntries.js'; * export const dynamic = 'force-dynamic' * export async function GET() { * const entries = await sitemap() - * const xml = buildSitemapXml(entries) + * const xml = buildSitemapXml(entries, { cssUrl: '/sitemap.css' }) * return new Response(xml, { * headers: { 'Content-Type': 'application/xml; charset=utf-8' }, * }) * } * - * The indentation makes the raw XML pleasant to read; the browser's default XML - * viewer adds the tree/fold UI. Crawlers read the XML as usual. + * Put sitemap.css in the project's /public and style the tags (see docs/seo.md + * for a starter). Note: is an XML tag, not — CSS can't make it a + * clickable link (some browsers auto-detect URLs); the win is readability, not + * clickability. * - * NOTE: if you use this custom route, DON'T also keep app/sitemap.ts — pick one - * (this route OR the Next MetadataRoute). Two sitemaps confuse crawlers. + * NOTE: if you use this custom route, DON'T also keep app/sitemap.ts — pick one. + * Two sitemaps confuse crawlers. */ -export declare function buildSitemapXml(entries: SitemapEntry[]): string; +export declare function buildSitemapXml(entries: SitemapEntry[], opts?: BuildSitemapXmlOptions): string; +export {}; diff --git a/dist/modules/seo/buildSitemapXml.js b/dist/modules/seo/buildSitemapXml.js index 6b205fc..ac89aa9 100644 --- a/dist/modules/seo/buildSitemapXml.js +++ b/dist/modules/seo/buildSitemapXml.js @@ -1,13 +1,13 @@ /** * Serializes sitemap entries to a clean, indented XML STRING — valid for crawlers - * and readable in the browser as the native XML tree (indented, collapsible, - * syntax-highlighted by the browser itself). + * and (with `cssUrl`) styled in the browser via plain CSS. * - * NO XSLT stylesheet: browsers (Chrome et al.) are REMOVING XSLT support, so a - * approach is a dead end — it shows a deprecation warning now - * and will break soon. Instead we serve plain XML with the correct Content-Type; - * the browser renders its built-in formatted XML view (the "code tree" look) with - * no transformation needed. + * Two viewing modes: + * - No cssUrl → the browser's native formatted XML tree (indented, collapsible). + * - With cssUrl → a `` directive; the project's + * CSS styles the XML tags (cards, labels via ::before). NOT XSLT — that's being + * removed from browsers and shows a deprecation warning. CSS is safe and + * W3C-standard. * * // app/sitemap.xml/route.ts * import { buildSitemapXml } from '@intecion/ipal-kit' @@ -15,18 +15,21 @@ * export const dynamic = 'force-dynamic' * export async function GET() { * const entries = await sitemap() - * const xml = buildSitemapXml(entries) + * const xml = buildSitemapXml(entries, { cssUrl: '/sitemap.css' }) * return new Response(xml, { * headers: { 'Content-Type': 'application/xml; charset=utf-8' }, * }) * } * - * The indentation makes the raw XML pleasant to read; the browser's default XML - * viewer adds the tree/fold UI. Crawlers read the XML as usual. + * Put sitemap.css in the project's /public and style the tags (see docs/seo.md + * for a starter). Note: is an XML tag, not — CSS can't make it a + * clickable link (some browsers auto-detect URLs); the win is readability, not + * clickability. * - * NOTE: if you use this custom route, DON'T also keep app/sitemap.ts — pick one - * (this route OR the Next MetadataRoute). Two sitemaps confuse crawlers. - */ export function buildSitemapXml(entries) { + * NOTE: if you use this custom route, DON'T also keep app/sitemap.ts — pick one. + * Two sitemaps confuse crawlers. + */ export function buildSitemapXml(entries, opts = {}) { + const { cssUrl } = opts; const esc = (s)=>s.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, '''); const urls = entries.map((e)=>{ const parts = [ @@ -36,12 +39,8 @@ const iso = e.lastModified instanceof Date ? e.lastModified.toISOString() : String(e.lastModified); parts.push(` ${esc(iso)}`); } - if (e.changeFrequency) { - parts.push(` ${e.changeFrequency}`); - } - if (typeof e.priority === 'number') { - parts.push(` ${e.priority}`); - } + if (e.changeFrequency) parts.push(` ${e.changeFrequency}`); + if (typeof e.priority === 'number') parts.push(` ${e.priority}`); const alternates = e.alternates?.languages; if (alternates) { for (const [lang, href] of Object.entries(alternates)){ @@ -52,7 +51,8 @@ } return ` \n${parts.join('\n')}\n `; }).join('\n'); - return `\n` + `\n` + urls + `\n`; + const stylesheet = cssUrl ? `\n` : ''; + return `\n` + stylesheet + `\n` + urls + `\n`; } //# sourceMappingURL=buildSitemapXml.js.map \ No newline at end of file diff --git a/dist/modules/seo/buildSitemapXml.js.map b/dist/modules/seo/buildSitemapXml.js.map index b366dc5..c5e9736 100644 --- a/dist/modules/seo/buildSitemapXml.js.map +++ b/dist/modules/seo/buildSitemapXml.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../../src/modules/seo/buildSitemapXml.ts"],"sourcesContent":["import type { SitemapEntry } from './buildSitemapEntries.js'\n\n/**\n * Serializes sitemap entries to a clean, indented XML STRING — valid for crawlers\n * and readable in the browser as the native XML tree (indented, collapsible,\n * syntax-highlighted by the browser itself).\n *\n * NO XSLT stylesheet: browsers (Chrome et al.) are REMOVING XSLT support, so a\n * approach is a dead end — it shows a deprecation warning now\n * and will break soon. Instead we serve plain XML with the correct Content-Type;\n * the browser renders its built-in formatted XML view (the \"code tree\" look) with\n * no transformation needed.\n *\n * // app/sitemap.xml/route.ts\n * import { buildSitemapXml } from '@intecion/ipal-kit'\n * import { sitemap } from '@/lib/content'\n * export const dynamic = 'force-dynamic'\n * export async function GET() {\n * const entries = await sitemap()\n * const xml = buildSitemapXml(entries)\n * return new Response(xml, {\n * headers: { 'Content-Type': 'application/xml; charset=utf-8' },\n * })\n * }\n *\n * The indentation makes the raw XML pleasant to read; the browser's default XML\n * viewer adds the tree/fold UI. Crawlers read the XML as usual.\n *\n * NOTE: if you use this custom route, DON'T also keep app/sitemap.ts — pick one\n * (this route OR the Next MetadataRoute). Two sitemaps confuse crawlers.\n */\nexport function buildSitemapXml(entries: SitemapEntry[]): string {\n const esc = (s: string): string =>\n s\n .replace(/&/g, '&')\n .replace(//g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n\n const urls = entries\n .map((e) => {\n const parts = [` ${esc(e.url)}`]\n if (e.lastModified) {\n const iso =\n e.lastModified instanceof Date ? e.lastModified.toISOString() : String(e.lastModified)\n parts.push(` ${esc(iso)}`)\n }\n if (e.changeFrequency) {parts.push(` ${e.changeFrequency}`)}\n if (typeof e.priority === 'number') {parts.push(` ${e.priority}`)}\n const alternates = e.alternates?.languages\n if (alternates) {\n for (const [lang, href] of Object.entries(alternates)) {\n if (typeof href === 'string') {\n parts.push(\n ` `,\n )\n }\n }\n }\n return ` \\n${parts.join('\\n')}\\n `\n })\n .join('\\n')\n\n return (\n `\\n` +\n `\\n` +\n urls +\n `\\n`\n )\n}\n"],"names":["buildSitemapXml","entries","esc","s","replace","urls","map","e","parts","url","lastModified","iso","Date","toISOString","String","push","changeFrequency","priority","alternates","languages","lang","href","Object","join"],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BC,GACD,OAAO,SAASA,gBAAgBC,OAAuB;IACrD,MAAMC,MAAM,CAACC,IACXA,EACGC,OAAO,CAAC,MAAM,SACdA,OAAO,CAAC,MAAM,QACdA,OAAO,CAAC,MAAM,QACdA,OAAO,CAAC,MAAM,UACdA,OAAO,CAAC,MAAM;IAEnB,MAAMC,OAAOJ,QACVK,GAAG,CAAC,CAACC;QACJ,MAAMC,QAAQ;YAAC,CAAC,SAAS,EAAEN,IAAIK,EAAEE,GAAG,EAAE,MAAM,CAAC;SAAC;QAC9C,IAAIF,EAAEG,YAAY,EAAE;YAClB,MAAMC,MACJJ,EAAEG,YAAY,YAAYE,OAAOL,EAAEG,YAAY,CAACG,WAAW,KAAKC,OAAOP,EAAEG,YAAY;YACvFF,MAAMO,IAAI,CAAC,CAAC,aAAa,EAAEb,IAAIS,KAAK,UAAU,CAAC;QACjD;QACA,IAAIJ,EAAES,eAAe,EAAE;YAACR,MAAMO,IAAI,CAAC,CAAC,gBAAgB,EAAER,EAAES,eAAe,CAAC,aAAa,CAAC;QAAC;QACvF,IAAI,OAAOT,EAAEU,QAAQ,KAAK,UAAU;YAACT,MAAMO,IAAI,CAAC,CAAC,cAAc,EAAER,EAAEU,QAAQ,CAAC,WAAW,CAAC;QAAC;QACzF,MAAMC,aAAaX,EAAEW,UAAU,EAAEC;QACjC,IAAID,YAAY;YACd,KAAK,MAAM,CAACE,MAAMC,KAAK,IAAIC,OAAOrB,OAAO,CAACiB,YAAa;gBACrD,IAAI,OAAOG,SAAS,UAAU;oBAC5Bb,MAAMO,IAAI,CACR,CAAC,0CAA0C,EAAEb,IAAIkB,MAAM,QAAQ,EAAElB,IAAImB,MAAM,GAAG,CAAC;gBAEnF;YACF;QACF;QACA,OAAO,CAAC,SAAS,EAAEb,MAAMe,IAAI,CAAC,MAAM,UAAU,CAAC;IACjD,GACCA,IAAI,CAAC;IAER,OACE,CAAC,wCAAwC,CAAC,GAC1C,CAAC,4DAA4D,CAAC,GAC9D,CAAC,6CAA6C,CAAC,GAC/ClB,OACA,CAAC,WAAW,CAAC;AAEjB"} \ No newline at end of file +{"version":3,"sources":["../../../src/modules/seo/buildSitemapXml.ts"],"sourcesContent":["import type { SitemapEntry } from './buildSitemapEntries.js'\n\ntype BuildSitemapXmlOptions = {\n /**\n * URL of a CSS stylesheet to make the sitemap readable in the browser, e.g.\n * '/sitemap.css'. Uses `type=\"text/css\"` — the W3C \"Associating Style Sheets\n * with XML\" mechanism, which is NOT deprecated (unlike XSLT / type=\"text/xsl\",\n * which Chrome/WebKit are removing). CSS on XML shows no warning, styles the\n * raw tags directly (e.g. `url { display: block }` turns the wall of text into\n * cards), and crawlers ignore the directive entirely.\n */\n cssUrl?: string\n}\n\n/**\n * Serializes sitemap entries to a clean, indented XML STRING — valid for crawlers\n * and (with `cssUrl`) styled in the browser via plain CSS.\n *\n * Two viewing modes:\n * - No cssUrl → the browser's native formatted XML tree (indented, collapsible).\n * - With cssUrl → a `` directive; the project's\n * CSS styles the XML tags (cards, labels via ::before). NOT XSLT — that's being\n * removed from browsers and shows a deprecation warning. CSS is safe and\n * W3C-standard.\n *\n * // app/sitemap.xml/route.ts\n * import { buildSitemapXml } from '@intecion/ipal-kit'\n * import { sitemap } from '@/lib/content'\n * export const dynamic = 'force-dynamic'\n * export async function GET() {\n * const entries = await sitemap()\n * const xml = buildSitemapXml(entries, { cssUrl: '/sitemap.css' })\n * return new Response(xml, {\n * headers: { 'Content-Type': 'application/xml; charset=utf-8' },\n * })\n * }\n *\n * Put sitemap.css in the project's /public and style the tags (see docs/seo.md\n * for a starter). Note: is an XML tag, not — CSS can't make it a\n * clickable link (some browsers auto-detect URLs); the win is readability, not\n * clickability.\n *\n * NOTE: if you use this custom route, DON'T also keep app/sitemap.ts — pick one.\n * Two sitemaps confuse crawlers.\n */\nexport function buildSitemapXml(\n entries: SitemapEntry[],\n opts: BuildSitemapXmlOptions = {},\n): string {\n const { cssUrl } = opts\n\n const esc = (s: string): string =>\n s\n .replace(/&/g, '&')\n .replace(//g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n\n const urls = entries\n .map((e) => {\n const parts = [` ${esc(e.url)}`]\n if (e.lastModified) {\n const iso =\n e.lastModified instanceof Date ? e.lastModified.toISOString() : String(e.lastModified)\n parts.push(` ${esc(iso)}`)\n }\n if (e.changeFrequency) parts.push(` ${e.changeFrequency}`)\n if (typeof e.priority === 'number') parts.push(` ${e.priority}`)\n const alternates = e.alternates?.languages\n if (alternates) {\n for (const [lang, href] of Object.entries(alternates)) {\n if (typeof href === 'string') {\n parts.push(\n ` `,\n )\n }\n }\n }\n return ` \\n${parts.join('\\n')}\\n `\n })\n .join('\\n')\n\n const stylesheet = cssUrl ? `\\n` : ''\n\n return (\n `\\n` +\n stylesheet +\n `\\n` +\n urls +\n `\\n`\n )\n}\n"],"names":["buildSitemapXml","entries","opts","cssUrl","esc","s","replace","urls","map","e","parts","url","lastModified","iso","Date","toISOString","String","push","changeFrequency","priority","alternates","languages","lang","href","Object","join","stylesheet"],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BC,GACD,OAAO,SAASA,gBACdC,OAAuB,EACvBC,OAA+B,CAAC,CAAC;IAEjC,MAAM,EAAEC,MAAM,EAAE,GAAGD;IAEnB,MAAME,MAAM,CAACC,IACXA,EACGC,OAAO,CAAC,MAAM,SACdA,OAAO,CAAC,MAAM,QACdA,OAAO,CAAC,MAAM,QACdA,OAAO,CAAC,MAAM,UACdA,OAAO,CAAC,MAAM;IAEnB,MAAMC,OAAON,QACVO,GAAG,CAAC,CAACC;QACJ,MAAMC,QAAQ;YAAC,CAAC,SAAS,EAAEN,IAAIK,EAAEE,GAAG,EAAE,MAAM,CAAC;SAAC;QAC9C,IAAIF,EAAEG,YAAY,EAAE;YAClB,MAAMC,MACJJ,EAAEG,YAAY,YAAYE,OAAOL,EAAEG,YAAY,CAACG,WAAW,KAAKC,OAAOP,EAAEG,YAAY;YACvFF,MAAMO,IAAI,CAAC,CAAC,aAAa,EAAEb,IAAIS,KAAK,UAAU,CAAC;QACjD;QACA,IAAIJ,EAAES,eAAe,EAAER,MAAMO,IAAI,CAAC,CAAC,gBAAgB,EAAER,EAAES,eAAe,CAAC,aAAa,CAAC;QACrF,IAAI,OAAOT,EAAEU,QAAQ,KAAK,UAAUT,MAAMO,IAAI,CAAC,CAAC,cAAc,EAAER,EAAEU,QAAQ,CAAC,WAAW,CAAC;QACvF,MAAMC,aAAaX,EAAEW,UAAU,EAAEC;QACjC,IAAID,YAAY;YACd,KAAK,MAAM,CAACE,MAAMC,KAAK,IAAIC,OAAOvB,OAAO,CAACmB,YAAa;gBACrD,IAAI,OAAOG,SAAS,UAAU;oBAC5Bb,MAAMO,IAAI,CACR,CAAC,0CAA0C,EAAEb,IAAIkB,MAAM,QAAQ,EAAElB,IAAImB,MAAM,GAAG,CAAC;gBAEnF;YACF;QACF;QACA,OAAO,CAAC,SAAS,EAAEb,MAAMe,IAAI,CAAC,MAAM,UAAU,CAAC;IACjD,GACCA,IAAI,CAAC;IAER,MAAMC,aAAavB,SAAS,CAAC,uCAAuC,EAAEC,IAAID,QAAQ,KAAK,CAAC,GAAG;IAE3F,OACE,CAAC,wCAAwC,CAAC,GAC1CuB,aACA,CAAC,4DAA4D,CAAC,GAC9D,CAAC,6CAA6C,CAAC,GAC/CnB,OACA,CAAC,WAAW,CAAC;AAEjB"} \ No newline at end of file diff --git a/docs/seo.md b/docs/seo.md index 4e5010a..83fdf2b 100644 --- a/docs/seo.md +++ b/docs/seo.md @@ -19,14 +19,14 @@ admina i bez importMap się nie wyrenderują. ```ts ipalKit({ - seo: { - collections: ['pages', 'posts'], // które kolekcje dostają meta - // generateTitle: ({ doc }) => `${doc.title}`, // opcjonalne - // generateDescription: ({ doc }) => doc.excerpt ?? '', - // fields: [...], // extra pola w grupie SEO - // autoFill: { title: 'title', description: 'excerpt' }, // mapowanie auto-fill - // autoFill: false, // wyłącz auto-fill - }, + seo: { + collections: ['pages', 'posts'], // które kolekcje dostają meta + // generateTitle: ({ doc }) => `${doc.title}`, // opcjonalne + // generateDescription: ({ doc }) => doc.excerpt ?? '', + // fields: [...], // extra pola w grupie SEO + // autoFill: { title: 'title', description: 'excerpt' }, // mapowanie auto-fill + // autoFill: false, // wyłącz auto-fill + }, }) ``` @@ -89,16 +89,16 @@ import { createPageMetadata } from '@intecion/ipal-kit' import { i18nConfig } from '@/i18n.config' const pageMetadata = createPageMetadata({ - config: i18nConfig, - baseUrl: process.env.NEXT_PUBLIC_SERVER_URL, - // collection: 'pages', // domyślne - // settingsSlug: 'site-settings', // domyślne - // siteNameField: 'siteName', // domyślne + config: i18nConfig, + baseUrl: process.env.NEXT_PUBLIC_SERVER_URL, + // collection: 'pages', // domyślne + // settingsSlug: 'site-settings', // domyślne + // siteNameField: 'siteName', // domyślne }) export async function generateMetadata({ params }): Promise { - const { locale, slug } = await params - return pageMetadata({ payload: await getPayload({ config }), locale, slug }) + const { locale, slug } = await params + return pageMetadata({ payload: await getPayload({ config }), locale, slug }) } ``` @@ -121,43 +121,43 @@ global. Klient dostarcza resolvery. import { createMetadataGenerator } from '@intecion/ipal-kit' const generate = createMetadataGenerator({ - config: i18nConfig, - baseUrl: process.env.NEXT_PUBLIC_SERVER_URL, - homeSlug: 'homepage', + config: i18nConfig, + baseUrl: process.env.NEXT_PUBLIC_SERVER_URL, + homeSlug: 'homepage', - resolveDocument: async ({ payload, params, locale }) => { - const slug = (params.slug as string[])?.join('/') + resolveDocument: async ({ payload, params, locale }) => { + const slug = (params.slug as string[])?.join('/') - // meta MUSI przyjść w konkretnym locale (stringi), a slug jako mapa - // locale→wartość (hreflang) — to dwa różne odczyty. - const found = await payload.find({ - collection: 'posts', - where: { slug: { equals: slug } }, - locale, - depth: 1, - limit: 1, - }) - const doc = found.docs[0] - if (!doc) return null + // meta MUSI przyjść w konkretnym locale (stringi), a slug jako mapa + // locale→wartość (hreflang) — to dwa różne odczyty. + const found = await payload.find({ + collection: 'posts', + where: { slug: { equals: slug } }, + locale, + depth: 1, + limit: 1, + }) + const doc = found.docs[0] + if (!doc) return null - const allLocales = await payload.findByID({ - collection: 'posts', - id: doc.id, - locale: 'all', - depth: 0, - }) + const allLocales = await payload.findByID({ + collection: 'posts', + id: doc.id, + locale: 'all', + depth: 0, + }) - return { ...doc, slug: allLocales.slug } - }, + return { ...doc, slug: allLocales.slug } + }, - resolveSiteName: async ({ payload, locale }) => - (await getSiteSettings(payload, { locale })).siteName ?? null, - resolveImageUrl: async ({ doc }) => doc.meta?.image?.url ?? null, + resolveSiteName: async ({ payload, locale }) => + (await getSiteSettings(payload, { locale })).siteName ?? null, + resolveImageUrl: async ({ doc }) => doc.meta?.image?.url ?? null, }) export async function generateMetadata({ params }) { - const { locale, slug } = await params - return generate({ payload: await getPayload({ config }), params: { slug }, locale }) + const { locale, slug } = await params + return generate({ payload: await getPayload({ config }), params: { slug }, locale }) } ``` @@ -176,16 +176,16 @@ Gdy chcesz pełną kontrolę: import { buildMetadata, getLocalizedSlugs } from '@intecion/ipal-kit' return buildMetadata({ - meta: doc.meta, // z plugin-seo - siteName: settings.siteName, - imageUrl: '/og.png', - locale: 'pl', - slugs: getLocalizedSlugs({ slugField: docAllLocales.slug, config }), - config, - baseUrl: 'https://example.com', - separator: ' – ', // opcjonalne - order: 'site-first', // opcjonalne - homeSlug: 'homepage', + meta: doc.meta, // z plugin-seo + siteName: settings.siteName, + imageUrl: '/og.png', + locale: 'pl', + slugs: getLocalizedSlugs({ slugField: docAllLocales.slug, config }), + config, + baseUrl: 'https://example.com', + separator: ' – ', // opcjonalne + order: 'site-first', // opcjonalne + homeSlug: 'homepage', }) // → { title, description, openGraph, alternates: { canonical, languages } } ``` @@ -232,10 +232,10 @@ nie rozjedzie się z tym, co strony serwują. Handlery są gotowe w ```ts // src/lib/content.ts export const { /* ... */, sitemap, robots } = createContentHelpers({ - config, - content: contentConfig, - i18n: i18nConfig, // wymagane dla sitemap (hreflang) - baseUrl: process.env.NEXT_PUBLIC_SERVER_URL, + config, + content: contentConfig, + i18n: i18nConfig, // wymagane dla sitemap (hreflang) + baseUrl: process.env.NEXT_PUBLIC_SERVER_URL, }) ``` @@ -278,7 +278,7 @@ Niskopoziomowo (własna trasa zamiast handlera z fabryki): import { buildSitemapEntries, buildRobots } from '@intecion/ipal-kit' const entries = await buildSitemapEntries({ - payload, config: i18nConfig, baseUrl, content: contentConfig, + payload, config: i18nConfig, baseUrl, content: contentConfig, }) ``` @@ -321,9 +321,9 @@ import { buildIconsMetadata } from '@intecion/ipal-kit' import { getSettings } from '@/lib/payload' export async function generateMetadata({ params }): Promise { - const { locale } = await params - const settings = await getSettings(locale) - return buildIconsMetadata(settings.favicon) // z pola favicon (panel) + const { locale } = await params + const settings = await getSettings(locale) + return buildIconsMetadata(settings.favicon) // z pola favicon (panel) } ``` @@ -346,16 +346,16 @@ wynikach, logo w knowledge panel. import { buildOrganizationJsonLd } from '@intecion/ipal-kit' const jsonLd = buildOrganizationJsonLd({ - name: settings.siteName, - url: process.env.NEXT_PUBLIC_SERVER_URL!, - logo: settings.logo, - sameAs: settings.socialLinks, // opcjonalne: profile społecznościowe -}) + name: settings.siteName, + url: process.env.NEXT_PUBLIC_SERVER_URL!, + logo: settings.logo, + sameAs: settings.socialLinks, // opcjonalne: profile społecznościowe + }) -// w JSX layoutu: -