From caa266bad8ed20364e52ebbfecd70513e9a34aae Mon Sep 17 00:00:00 2001 From: fanny Date: Wed, 7 Jan 2026 00:40:13 -0300 Subject: [PATCH 01/15] chore: Updates cp version --- packages/core/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 057777e32d..2571c1149a 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -54,7 +54,7 @@ "@lexical/rich-text": "^0.34.0", "@types/react": "catalog:", "@vtex/client-cms": "^0.2.16", - "@vtex/client-cp": "0.3.5", + "@vtex/client-cp": "0.4.0", "@vtex/prettier-config": "1.0.0", "autoprefixer": "^10.4.0", "cookie": "catalog:", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6dbc0155a6..eee2117197 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -494,8 +494,8 @@ importers: specifier: ^0.2.16 version: 0.2.16(encoding@0.1.13) '@vtex/client-cp': - specifier: 0.3.5 - version: 0.3.5 + specifier: 0.4.0 + version: 0.4.0 '@vtex/prettier-config': specifier: 1.0.0 version: 1.0.0(prettier@2.8.8) @@ -4212,8 +4212,8 @@ packages: '@vtex/client-cms@0.2.16': resolution: {integrity: sha512-mK5OiaaGHItVuispyy8yXLILnMx4aOJj7HkamOmAL12+KbnkiKKpO1vJEb3hRB16lK1rHtl7Q5H3aTFsMqrf0w==} - '@vtex/client-cp@0.3.5': - resolution: {integrity: sha512-uzvpYz1LHiPxBc0FmVVG0azfGWiYJhIJf2JgcNSsi3V5oxR/dwM6tbh+JigSNQpp6bNn9GglLvMpYboxORMsnQ==} + '@vtex/client-cp@0.4.0': + resolution: {integrity: sha512-tZxZL4ixR29fkhJ04mBcvCxD3ZBMP2dV5vXoubfgMnNP7PnhdREP4Oj7uR/CkL2jT3kRSS7u6pbetQ1ilwFByw==} engines: {node: '>=16'} '@vtex/faststore-sdk@0.1.1-canary.1': @@ -16064,7 +16064,7 @@ snapshots: transitivePeerDependencies: - encoding - '@vtex/client-cp@0.3.5': + '@vtex/client-cp@0.4.0': dependencies: axios: 1.13.2 transitivePeerDependencies: From 65427f57dda0c3a5c64fb85fd53372cd49b7813d Mon Sep 17 00:00:00 2001 From: fanny Date: Wed, 7 Jan 2026 10:34:30 -0300 Subject: [PATCH 02/15] fix: temp fix for product shelf without title --- packages/core/src/utils/utilities.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/core/src/utils/utilities.ts b/packages/core/src/utils/utilities.ts index 2a92a21578..96328edda7 100644 --- a/packages/core/src/utils/utilities.ts +++ b/packages/core/src/utils/utilities.ts @@ -7,7 +7,10 @@ * textToKebabCase("Example Text!") // example-text * ``` */ -export function textToKebabCase(text: string): string { +export function textToKebabCase(text: string | null | undefined): string { + // Handle null, undefined, or empty strings + if (!text) return '' + // Replace spaces and special characters with hyphens let kebabCase = text.replace(/[^\w\s]/gi, '-') From 1de5c5c63372b04e945c332ffef809f70370e7d0 Mon Sep 17 00:00:00 2001 From: fanny Date: Wed, 7 Jan 2026 10:49:50 -0300 Subject: [PATCH 03/15] chore: Passing locale to cp --- packages/core/src/server/content/service.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/core/src/server/content/service.ts b/packages/core/src/server/content/service.ts index aa48d2ae16..cf74cb5df1 100644 --- a/packages/core/src/server/content/service.ts +++ b/packages/core/src/server/content/service.ts @@ -23,8 +23,11 @@ export class ContentService { private clientCP: ClientCP constructor() { + // TODO: In the future, the locale should be dynamically retrieved from the current session + // instead of being hardcoded. For now, can try using 'pt-BR'/'en-EN'/'de-DE'/'es-ES'/'fr-FR' for testing purposes. this.clientCP = new ClientCP({ tenant: config.api.storeId, + locale: 'fr-FR', // Fixed locale for testing - should use session.locale in the future }) } @@ -187,7 +190,8 @@ export class ContentService { const { cmsOptions } = options const params: Partial = { accountName: config.api.storeId, - storeId: 'faststore', + // storeId: 'faststore', + storeId: 'multilanguage', contentType: cmsOptions.contentType, slug: options.slug, } From 9bac56ac30f07e0272ad7ff67a48b0c67d096b43 Mon Sep 17 00:00:00 2001 From: fanny Date: Wed, 7 Jan 2026 10:50:11 -0300 Subject: [PATCH 04/15] chore: For testing purposes, passing documentId --- .../templates/LandingPage/LandingPage.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/core/src/components/templates/LandingPage/LandingPage.tsx b/packages/core/src/components/templates/LandingPage/LandingPage.tsx index 78a73526f5..6540a0498a 100644 --- a/packages/core/src/components/templates/LandingPage/LandingPage.tsx +++ b/packages/core/src/components/templates/LandingPage/LandingPage.tsx @@ -3,7 +3,6 @@ import type { ComponentType } from 'react' import { default as GLOBAL_COMPONENTS } from 'src/components/cms/global/Components' import RenderSections from 'src/components/cms/RenderSections' -import { getComponentKey } from 'src/utils/cms' import BannerNewsletter from 'src/components/sections/BannerNewsletter/BannerNewsletter' import { OverriddenDefaultBannerText as BannerText } from 'src/components/sections/BannerText/OverriddenDefaultBannerText' import { OverriddenDefaultCrossSellingShelf as CrossSellingShelf } from 'src/components/sections/CrossSellingShelf/OverriddenDefaultCrossSellingShelf' @@ -17,6 +16,7 @@ import PLUGINS_COMPONENTS from 'src/plugins' import MissingContentError from 'src/sdk/error/MissingContentError/MissingContentError' import PageProvider from 'src/sdk/overrides/PageProvider' import type { PageContentType } from 'src/server/cms' +import { getComponentKey } from 'src/utils/cms' import storeConfig from 'discovery.config' import { contentService } from 'src/server/content/service' @@ -128,7 +128,8 @@ export const getLandingPageBySlug = async ( await contentService.getSingleContent({ contentType: 'landingPage', previewData, - documentId: pageBySlug.documentId, + // documentId: pageBySlug.documentId, + documentId: '11a7ccfb-ac7e-4ab0-ab5b-7438106edb3d', versionId: pageBySlug.versionId, releaseId: pageBySlug.releaseId, slug: pageBySlug.settings?.seo?.slug, @@ -143,10 +144,13 @@ export const getLandingPageBySlug = async ( contentType: 'landingPage', previewData, slug, - filters: - previewData?.contentType !== 'landingPage' - ? { filters: { 'settings.seo.slug': `/${slug}` } } - : undefined, + // TODO: REMOVE just for testing purposes - passing documentId manually + documentId: '11a7ccfb-ac7e-4ab0-ab5b-7438106edb3d', + // TODO: puts back the filters when the default documentId is removed + // filters: + // previewData?.contentType !== 'landingPage' + // ? { filters: { 'settings.seo.slug': `/${slug}` } } + // : undefined, }) return landingPageData } catch (error) { From 878044c08e4363a389fb986e9d02e841ca2e2e28 Mon Sep 17 00:00:00 2001 From: fanny Date: Wed, 7 Jan 2026 10:52:23 -0300 Subject: [PATCH 05/15] chore: Temp handles empty global sections scenario --- packages/core/src/server/cms/global.ts | 49 ++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/packages/core/src/server/cms/global.ts b/packages/core/src/server/cms/global.ts index ea71b81436..bd7594685e 100644 --- a/packages/core/src/server/cms/global.ts +++ b/packages/core/src/server/cms/global.ts @@ -1,5 +1,4 @@ import type { GlobalSectionsData } from 'src/components/cms/GlobalSections' -import ChildrenSectionNotFoundError from 'src/sdk/error/ChildrenSectionNotFoundError' type InjectGlobalSectionsProps = { globalSections: GlobalSectionsData @@ -12,14 +11,58 @@ export function injectGlobalSections({ globalSectionsHeader, globalSectionsFooter, }: InjectGlobalSectionsProps) { + // TODO: remover later + // Temp Handle case when globalSections or sections array is undefined/empty + if ( + !globalSections || + !globalSections.sections || + globalSections.sections.length === 0 + ) { + console.warn( + 'Global Sections content type was not found or has no sections. Returning minimal structure for development.' + ) + // Return minimal structure with header and footer sections + const headerSections = globalSectionsHeader?.sections || [] + const footerSections = globalSectionsFooter?.sections || [] + + return { + sections: [ + ...headerSections, + { + name: 'Children', + data: {}, + }, + ...footerSections, + ], + settings: globalSections?.settings || {}, + } + } + const childrenIndex = globalSections.sections.findIndex( (section) => section.name === 'Children' ) if (childrenIndex === -1) { - throw new ChildrenSectionNotFoundError( - 'Children section in Global Sections content type was not found. Please add a Children Section.' + // TODO: remover later - temp warning for testing + console.warn( + 'Children section in Global Sections not found. Adding it automatically for development.' ) + // Add Children section if missing + const headerSections = globalSectionsHeader?.sections || [] + const footerSections = globalSectionsFooter?.sections || [] + + return { + ...globalSections, + sections: [ + ...headerSections, + ...globalSections.sections, + { + name: 'Children', + data: {}, + }, + ...footerSections, + ], + } } const headerSections = globalSectionsHeader?.sections || [] From d815823238f95b42a894f1eb20d1b29429600691 Mon Sep 17 00:00:00 2001 From: fanny Date: Wed, 7 Jan 2026 21:09:11 -0300 Subject: [PATCH 06/15] chore: Adding locale to ContentParams --- packages/core/src/server/content/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/server/content/types.ts b/packages/core/src/server/content/types.ts index b08ed933c9..5cbf7dfada 100644 --- a/packages/core/src/server/content/types.ts +++ b/packages/core/src/server/content/types.ts @@ -17,6 +17,7 @@ export interface ContentParams { versionId?: string releaseId?: string filters?: Record + locale?: string } export interface ContentOptions { From 06d22747116ed09f751abac80695d2b52ee96c34 Mon Sep 17 00:00:00 2001 From: fanny Date: Wed, 7 Jan 2026 21:12:46 -0300 Subject: [PATCH 07/15] feat: Passes locale to client and updates public and private methods --- packages/core/src/server/content/service.ts | 69 ++++++++++++++------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/packages/core/src/server/content/service.ts b/packages/core/src/server/content/service.ts index cf74cb5df1..7213d76303 100644 --- a/packages/core/src/server/content/service.ts +++ b/packages/core/src/server/content/service.ts @@ -20,15 +20,22 @@ import { isBranchPreview, isContentPlatformSource } from './utils' type ContentResult = ContentData | (ContentEntry & PageContentType) export class ContentService { - private clientCP: ClientCP + // private clientCP: ClientCP - constructor() { - // TODO: In the future, the locale should be dynamically retrieved from the current session - // instead of being hardcoded. For now, can try using 'pt-BR'/'en-EN'/'de-DE'/'es-ES'/'fr-FR' for testing purposes. - this.clientCP = new ClientCP({ + // constructor() { + // this.clientCP = new ClientCP({ + // tenant: config.api.storeId, + // // locale: 'fr-FR', // Fixed locale for testing - should use session.locale in the future + // }) + // } + + private getClientCP(locale?: string): ClientCP { + const clientCP = new ClientCP({ tenant: config.api.storeId, - locale: 'fr-FR', // Fixed locale for testing - should use session.locale in the future + locale: locale ?? config.i18n.defaultLocale, }) + + return clientCP } async getSingleContent( @@ -37,7 +44,7 @@ export class ContentService { const options = this.createContentOptions(params) if (isContentPlatformSource()) { - return this.getFromCP(options) + return this.getFromCP(options, params.locale) } return getPage(options.cmsOptions) } @@ -48,9 +55,15 @@ export class ContentService { const options = this.createContentOptions(params) if (isContentPlatformSource()) { + const clientCP = this.getClientCP(params.locale) const serviceParams = this.convertOptionsToParams(options) - const { entries } = await this.clientCP.listEntries(serviceParams) - return this.fillEntriesWithData(entries, serviceParams, options.isPreview) + const { entries } = await clientCP.listEntries(serviceParams) + return this.fillEntriesWithData( + entries, + serviceParams, + options.isPreview, + params.locale + ) } return getCMSPage(options.cmsOptions) } @@ -93,13 +106,15 @@ export class ContentService { } private async getFromCP( - options: ContentOptions + options: ContentOptions, + locale?: string ): Promise { const params = this.convertOptionsToParams(options) try { const entry: PageContentType = await this.getEntry( params, - options.isPreview + options.isPreview, + locale ) return entry as T } catch (err: unknown) { @@ -111,13 +126,15 @@ export class ContentService { private async fillEntriesWithData( entries: ContentEntry[], serviceParams: EntryPathParams, - isPreview: boolean + isPreview: boolean, + locale?: string ): Promise<{ data: (ContentEntry & PageContentType)[] }> { const data = await Promise.all( entries.map(async (entry) => { const entryData = await this.getEntryData( { ...serviceParams, entryId: entry.id }, - isPreview + isPreview, + locale ) return this.mergeEntryWithData(entry, entryData) }) @@ -127,38 +144,44 @@ export class ContentService { private async getEntry( params: EntryPathParams, - isPreview: boolean + isPreview: boolean, + locale?: string ): Promise { return params.entryId || params.slug - ? await this.getEntryData(params, isPreview) - : await this.fetchFirstEntryFromList(params, isPreview) + ? await this.getEntryData(params, isPreview, locale) + : await this.fetchFirstEntryFromList(params, isPreview, locale) } private async getEntryData( params: EntryPathParams, - isPreview: boolean + isPreview: boolean, + locale?: string ): Promise { if (!params.entryId && !params.slug) { const operation = isPreview ? 'Preview' : 'getEntry' throw new Error(`${operation} requires entryId or slug`) } + const clientCP = this.getClientCP(locale) + if (isPreview) { return params.entryId - ? (this.clientCP.previewEntryById(params) as Promise) - : (this.clientCP.previewEntryBySlug(params) as Promise) + ? (clientCP.previewEntryById(params) as Promise) + : (clientCP.previewEntryBySlug(params) as Promise) } return params.entryId - ? (this.clientCP.getEntry(params) as Promise) - : (this.clientCP.getEntryBySlug(params) as Promise) + ? (clientCP.getEntry(params) as Promise) + : (clientCP.getEntryBySlug(params) as Promise) } private async fetchFirstEntryFromList( params: EntryPathParams, - isPreview: boolean + isPreview: boolean, + locale?: string ): Promise { - const { entries } = await this.clientCP.listEntries(params) + const clientCP = this.getClientCP(locale) + const { entries } = await clientCP.listEntries(params) if (!entries || entries.length === 0) { console.warn('No entries found for params', params) return {} as PageContentType From b9aa29ea499f6a0f4ee84fbf3cc28a8ae591a468 Mon Sep 17 00:00:00 2001 From: fanny Date: Wed, 7 Jan 2026 21:15:01 -0300 Subject: [PATCH 08/15] chore: add locale to fetch cp content on main pages and global sections --- .../core/src/components/cms/GlobalSections.tsx | 17 ++++++++++++----- .../templates/LandingPage/LandingPage.tsx | 7 ++++++- packages/core/src/pages/[...slug].tsx | 9 ++++++--- packages/core/src/pages/[slug]/p.tsx | 7 ++++--- packages/core/src/pages/index.tsx | 4 +++- 5 files changed, 31 insertions(+), 13 deletions(-) diff --git a/packages/core/src/components/cms/GlobalSections.tsx b/packages/core/src/components/cms/GlobalSections.tsx index 257273f916..3efac0eba7 100644 --- a/packages/core/src/components/cms/GlobalSections.tsx +++ b/packages/core/src/components/cms/GlobalSections.tsx @@ -15,7 +15,8 @@ export type GlobalSectionsData = { export const getGlobalSectionsByType = async ( previewData: PreviewData, - contentType: string + contentType: string, + locale?: string ): Promise => { if (storeConfig.cms.data) { const cmsData = JSON.parse(storeConfig.cms.data) @@ -25,6 +26,7 @@ export const getGlobalSectionsByType = async ( const pageData = contentService.getSingleContent({ contentType, previewData, + locale, documentId: page.documentId, versionId: page.versionId, releaseId: page.releaseId, @@ -37,25 +39,30 @@ export const getGlobalSectionsByType = async ( const pageData = contentService.getSingleContent({ contentType, previewData, + locale, }) return pageData } export const getGlobalSectionsData = ( - previewData: PreviewData + previewData: PreviewData, + locale?: string ): Promise[] => { const globalSections = getGlobalSectionsByType( previewData, - GLOBAL_SECTIONS_CONTENT_TYPE + GLOBAL_SECTIONS_CONTENT_TYPE, + locale ) const globalHeaderSections = getGlobalSectionsByType( previewData, - GLOBAL_SECTIONS_HEADER_CONTENT_TYPE + GLOBAL_SECTIONS_HEADER_CONTENT_TYPE, + locale ) const globalFooterSections = getGlobalSectionsByType( previewData, - GLOBAL_SECTIONS_FOOTER_CONTENT_TYPE + GLOBAL_SECTIONS_FOOTER_CONTENT_TYPE, + locale ) return [globalSections, globalHeaderSections, globalFooterSections] diff --git a/packages/core/src/components/templates/LandingPage/LandingPage.tsx b/packages/core/src/components/templates/LandingPage/LandingPage.tsx index 6540a0498a..73a12e2259 100644 --- a/packages/core/src/components/templates/LandingPage/LandingPage.tsx +++ b/packages/core/src/components/templates/LandingPage/LandingPage.tsx @@ -114,8 +114,11 @@ export default function LandingPage({ export const getLandingPageBySlug = async ( slug: string, - previewData: PreviewData + previewData: PreviewData, + locale?: string ) => { + console.log('🌐 Locale from context (getLandingPageBySlug):', locale) + try { if (storeConfig.cms.data) { const cmsData = JSON.parse(storeConfig.cms.data) @@ -128,6 +131,7 @@ export const getLandingPageBySlug = async ( await contentService.getSingleContent({ contentType: 'landingPage', previewData, + locale, // documentId: pageBySlug.documentId, documentId: '11a7ccfb-ac7e-4ab0-ab5b-7438106edb3d', versionId: pageBySlug.versionId, @@ -144,6 +148,7 @@ export const getLandingPageBySlug = async ( contentType: 'landingPage', previewData, slug, + locale, // TODO: REMOVE just for testing purposes - passing documentId manually documentId: '11a7ccfb-ac7e-4ab0-ab5b-7438106edb3d', // TODO: puts back the filters when the default documentId is removed diff --git a/packages/core/src/pages/[...slug].tsx b/packages/core/src/pages/[...slug].tsx index 9ec8ee0f81..05bb901e48 100644 --- a/packages/core/src/pages/[...slug].tsx +++ b/packages/core/src/pages/[...slug].tsx @@ -114,17 +114,19 @@ export const getStaticProps: GetStaticProps< Props, { slug: string[] }, PreviewData -> = async ({ params, previewData }) => { +> = async ({ params, previewData, locale }) => { const slug = params?.slug.join('/') ?? '' const rewrites = (await storeConfig.rewrites?.()) ?? [] + console.log('🌐 Locale from context (slug.tsx):', locale) + const [ globalSectionsPromise, globalSectionsHeaderPromise, globalSectionsFooterPromise, - ] = getGlobalSectionsData(previewData) + ] = getGlobalSectionsData(previewData, locale) - const landingPagePromise = getLandingPageBySlug(slug, previewData) + const landingPagePromise = getLandingPageBySlug(slug, previewData, locale) const landingPage = await landingPagePromise @@ -176,6 +178,7 @@ export const getStaticProps: GetStaticProps< { previewData, slug, + locale, }, rewrites ), diff --git a/packages/core/src/pages/[slug]/p.tsx b/packages/core/src/pages/[slug]/p.tsx index 02f9d635c7..90dc7e01d5 100644 --- a/packages/core/src/pages/[slug]/p.tsx +++ b/packages/core/src/pages/[slug]/p.tsx @@ -12,7 +12,6 @@ import type { } from '@generated/graphql' import { default as GLOBAL_COMPONENTS } from 'src/components/cms/global/Components' import RenderSections from 'src/components/cms/RenderSections' -import { getComponentKey } from 'src/utils/cms' import BannerNewsletter from 'src/components/sections/BannerNewsletter/BannerNewsletter' import { OverriddenDefaultBannerText as BannerText } from 'src/components/sections/BannerText/OverriddenDefaultBannerText' import { OverriddenDefaultBreadcrumb as Breadcrumb } from 'src/components/sections/Breadcrumb/OverriddenDefaultBreadcrumb' @@ -27,6 +26,7 @@ import PLUGINS_COMPONENTS from 'src/plugins' import { getRedirect } from 'src/sdk/redirects' import { useSession } from 'src/sdk/session' import { execute } from 'src/server' +import { getComponentKey } from 'src/utils/cms' import storeConfig from 'discovery.config' import { @@ -295,14 +295,14 @@ export const getStaticProps: GetStaticProps< Props, { slug: string }, PreviewData -> = async ({ params, previewData }) => { +> = async ({ params, previewData, locale }) => { const slug = params?.slug ?? '' const [ globalSectionsPromise, globalSectionsHeaderPromise, globalSectionsFooterPromise, - ] = getGlobalSectionsData(previewData) + ] = getGlobalSectionsData(previewData, locale) const [ searchResult, @@ -349,6 +349,7 @@ export const getStaticProps: GetStaticProps< { previewData, slug, + locale, } ) diff --git a/packages/core/src/pages/index.tsx b/packages/core/src/pages/index.tsx index c94e913875..388b9d9305 100644 --- a/packages/core/src/pages/index.tsx +++ b/packages/core/src/pages/index.tsx @@ -154,7 +154,7 @@ export const getStaticProps: GetStaticProps< Props, Record, PreviewData -> = async ({ previewData }) => { +> = async ({ previewData, locale }) => { const [ globalSectionsPromise, globalSectionsHeaderPromise, @@ -175,10 +175,12 @@ export const getStaticProps: GetStaticProps< documentId: cmsPage.documentId, versionId: cmsPage.versionId, releaseId: cmsPage.releaseId, + locale, }) : contentService.getSingleContent({ contentType: 'home', previewData, + locale, }) const [ From 3a284330de2246fdca44136f5dc496be996ae070 Mon Sep 17 00:00:00 2001 From: fanny Date: Wed, 7 Jan 2026 21:27:27 -0300 Subject: [PATCH 09/15] chore: add locale to fetch cp content on other pages --- .../searchServerSideFunctions/getServerSideProps.ts | 9 +++++---- .../searchServerSideFunctions/getStaticProps.ts | 6 ++++-- packages/core/src/pages/404.tsx | 7 ++++--- packages/core/src/pages/500.tsx | 7 ++++--- packages/core/src/pages/login.tsx | 7 ++++--- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/packages/core/src/experimental/searchServerSideFunctions/getServerSideProps.ts b/packages/core/src/experimental/searchServerSideFunctions/getServerSideProps.ts index 5f118dbc3d..5549b912e5 100644 --- a/packages/core/src/experimental/searchServerSideFunctions/getServerSideProps.ts +++ b/packages/core/src/experimental/searchServerSideFunctions/getServerSideProps.ts @@ -3,10 +3,10 @@ import type { SearchPageProps } from './getStaticProps' import storeConfig from 'discovery.config' import { getGlobalSectionsData } from 'src/components/cms/GlobalSections' -import { type SearchContentType, getPage } from 'src/server/cms' +import type { SearchContentType } from 'src/server/cms' import { injectGlobalSections } from 'src/server/cms/global' -import type { PreviewData } from 'src/server/content/types' import { contentService } from 'src/server/content/service' +import type { PreviewData } from 'src/server/content/types' import { withLocaleValidationSSR } from 'src/utils/withLocaleValidation' const getServerSidePropsBase: GetServerSideProps< @@ -14,14 +14,14 @@ const getServerSidePropsBase: GetServerSideProps< Record, PreviewData > = async (context) => { - const { previewData, query, res } = context + const { previewData, query, res, locale } = context const searchTerm = (query.q as string)?.split('+').join(' ') const [ globalSectionsPromise, globalSectionsHeaderPromise, globalSectionsFooterPromise, - ] = getGlobalSectionsData(previewData) + ] = getGlobalSectionsData(previewData, locale) if (storeConfig.cms.data) { const cmsData = JSON.parse(storeConfig.cms.data) @@ -36,6 +36,7 @@ const getServerSidePropsBase: GetServerSideProps< contentService.getSingleContent({ contentType: 'search', previewData, + locale, documentId: page.documentId, versionId: page.versionId, releaseId: page.releaseId, diff --git a/packages/core/src/experimental/searchServerSideFunctions/getStaticProps.ts b/packages/core/src/experimental/searchServerSideFunctions/getStaticProps.ts index 51cf91cc2e..f2168b0461 100644 --- a/packages/core/src/experimental/searchServerSideFunctions/getStaticProps.ts +++ b/packages/core/src/experimental/searchServerSideFunctions/getStaticProps.ts @@ -24,12 +24,12 @@ export const getStaticProps: GetStaticProps< Record, PreviewData > = async (context) => { - const { previewData } = context + const { previewData, locale } = context const [ globalSectionsPromise, globalSectionsHeaderPromise, globalSectionsFooterPromise, - ] = getGlobalSectionsData(previewData) + ] = getGlobalSectionsData(previewData, locale) if (storeConfig.cms.data) { const cmsData = JSON.parse(storeConfig.cms.data) @@ -45,6 +45,7 @@ export const getStaticProps: GetStaticProps< contentService.getSingleContent({ contentType: 'search', previewData, + locale, documentId: page.documentId, versionId: page.versionId, releaseId: page.releaseId, @@ -71,6 +72,7 @@ export const getStaticProps: GetStaticProps< contentService.getSingleContent({ contentType: 'search', previewData, + locale, }), globalSectionsPromise, globalSectionsHeaderPromise, diff --git a/packages/core/src/pages/404.tsx b/packages/core/src/pages/404.tsx index 1e88c5582e..2e7252d411 100644 --- a/packages/core/src/pages/404.tsx +++ b/packages/core/src/pages/404.tsx @@ -8,7 +8,6 @@ import { import { default as GLOBAL_COMPONENTS } from 'src/components/cms/global/Components' import RenderSections from 'src/components/cms/RenderSections' -import { getComponentKey } from 'src/utils/cms' import { OverriddenDefaultEmptyState as EmptyState } from 'src/components/sections/EmptyState/OverriddenDefaultEmptyState' import CUSTOM_COMPONENTS from 'src/customizations/src/components' import PLUGINS_COMPONENTS from 'src/plugins' @@ -17,6 +16,7 @@ import type { PageContentType } from 'src/server/cms' import { injectGlobalSections } from 'src/server/cms/global' import { contentService } from 'src/server/content/service' import type { PreviewData } from 'src/server/content/types' +import { getComponentKey } from 'src/utils/cms' /* A list of components that can be used in the CMS. */ const COMPONENTS: Record> = { @@ -67,18 +67,19 @@ export const getStaticProps: GetStaticProps< Props, Record, PreviewData -> = async ({ previewData }) => { +> = async ({ previewData, locale }) => { const [ globalSectionsPromise, globalSectionsHeaderPromise, globalSectionsFooterPromise, - ] = getGlobalSectionsData(previewData) + ] = getGlobalSectionsData(previewData, locale) const [page, globalSections, globalSectionsHeader, globalSectionsFooter] = await Promise.all([ contentService.getSingleContent({ contentType: '404', previewData, + locale, }), globalSectionsPromise, globalSectionsHeaderPromise, diff --git a/packages/core/src/pages/500.tsx b/packages/core/src/pages/500.tsx index 3077bcc344..03019463df 100644 --- a/packages/core/src/pages/500.tsx +++ b/packages/core/src/pages/500.tsx @@ -8,7 +8,6 @@ import { import { default as GLOBAL_COMPONENTS } from 'src/components/cms/global/Components' import RenderSections from 'src/components/cms/RenderSections' -import { getComponentKey } from 'src/utils/cms' import { OverriddenDefaultEmptyState as EmptyState } from 'src/components/sections/EmptyState/OverriddenDefaultEmptyState' import CUSTOM_COMPONENTS from 'src/customizations/src/components' import PLUGINS_COMPONENTS from 'src/plugins' @@ -17,6 +16,7 @@ import type { PageContentType } from 'src/server/cms' import { injectGlobalSections } from 'src/server/cms/global' import { contentService } from 'src/server/content/service' import type { PreviewData } from 'src/server/content/types' +import { getComponentKey } from 'src/utils/cms' /* A list of components that can be used in the CMS. */ const COMPONENTS: Record> = { @@ -68,18 +68,19 @@ export const getStaticProps: GetStaticProps< Props, Record, PreviewData -> = async ({ previewData }) => { +> = async ({ previewData, locale }) => { const [ globalSectionsPromise, globalSectionsHeaderPromise, globalSectionsFooterPromise, - ] = getGlobalSectionsData(previewData) + ] = getGlobalSectionsData(previewData, locale) const [page, globalSections, globalSectionsHeader, globalSectionsFooter] = await Promise.all([ contentService.getSingleContent({ contentType: '500', previewData, + locale, }), globalSectionsPromise, globalSectionsHeaderPromise, diff --git a/packages/core/src/pages/login.tsx b/packages/core/src/pages/login.tsx index 12ff05754f..5595ab85e1 100644 --- a/packages/core/src/pages/login.tsx +++ b/packages/core/src/pages/login.tsx @@ -9,7 +9,6 @@ import { getGlobalSectionsData, } from 'src/components/cms/GlobalSections' import RenderSections from 'src/components/cms/RenderSections' -import { getComponentKey } from 'src/utils/cms' import { OverriddenDefaultEmptyState as EmptyState } from 'src/components/sections/EmptyState/OverriddenDefaultEmptyState' import CUSTOM_COMPONENTS from 'src/customizations/src/components' import PLUGINS_COMPONENTS from 'src/plugins' @@ -18,6 +17,7 @@ import type { PageContentType } from 'src/server/cms' import { injectGlobalSections } from 'src/server/cms/global' import { contentService } from 'src/server/content/service' import type { PreviewData } from 'src/server/content/types' +import { getComponentKey } from 'src/utils/cms' import storeConfig from '../../discovery.config' /* A list of components that can be used in the CMS. */ @@ -80,18 +80,19 @@ export const getStaticProps: GetStaticProps< Props, Record, PreviewData -> = async ({ previewData }) => { +> = async ({ previewData, locale }) => { const [ globalSectionsPromise, globalSectionsHeaderPromise, globalSectionsFooterPromise, - ] = getGlobalSectionsData(previewData) + ] = getGlobalSectionsData(previewData, locale) const [page, globalSections, globalSectionsHeader, globalSectionsFooter] = await Promise.all([ contentService.getSingleContent({ contentType: 'login', previewData, + locale, }), globalSectionsPromise, globalSectionsHeaderPromise, From 5ee23fc7981869ec56f12556001844e763a44d95 Mon Sep 17 00:00:00 2001 From: fanny Date: Wed, 7 Jan 2026 21:50:44 -0300 Subject: [PATCH 10/15] chore: Reuses cached clientCP for locale whenever possible --- packages/core/src/server/content/service.ts | 22 ++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/core/src/server/content/service.ts b/packages/core/src/server/content/service.ts index 7213d76303..24c5000b68 100644 --- a/packages/core/src/server/content/service.ts +++ b/packages/core/src/server/content/service.ts @@ -20,21 +20,25 @@ import { isBranchPreview, isContentPlatformSource } from './utils' type ContentResult = ContentData | (ContentEntry & PageContentType) export class ContentService { - // private clientCP: ClientCP - - // constructor() { - // this.clientCP = new ClientCP({ - // tenant: config.api.storeId, - // // locale: 'fr-FR', // Fixed locale for testing - should use session.locale in the future - // }) - // } + private clientCPCache = new Map() private getClientCP(locale?: string): ClientCP { + const currentLocale = locale ?? config.i18n.defaultLocale + + // Reuse cached ClientCP for locale + if (this.clientCPCache.has(currentLocale)) { + return this.clientCPCache.get(currentLocale) + } + + // Create new instance only if not in cache const clientCP = new ClientCP({ tenant: config.api.storeId, - locale: locale ?? config.i18n.defaultLocale, + locale: currentLocale, }) + // Store in cache for future use + this.clientCPCache.set(currentLocale, clientCP) + return clientCP } From cc5e8d4b392113de7a2867b4fce1ed55954b1c8b Mon Sep 17 00:00:00 2001 From: fanny Date: Wed, 7 Jan 2026 23:18:14 -0300 Subject: [PATCH 11/15] chore: Undo unnecessary changes --- packages/core/src/server/cms/global.ts | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/packages/core/src/server/cms/global.ts b/packages/core/src/server/cms/global.ts index bd7594685e..c35ad2d6f8 100644 --- a/packages/core/src/server/cms/global.ts +++ b/packages/core/src/server/cms/global.ts @@ -1,4 +1,5 @@ import type { GlobalSectionsData } from 'src/components/cms/GlobalSections' +import ChildrenSectionNotFoundError from 'src/sdk/error/ChildrenSectionNotFoundError' type InjectGlobalSectionsProps = { globalSections: GlobalSectionsData @@ -43,26 +44,9 @@ export function injectGlobalSections({ ) if (childrenIndex === -1) { - // TODO: remover later - temp warning for testing - console.warn( - 'Children section in Global Sections not found. Adding it automatically for development.' + throw new ChildrenSectionNotFoundError( + 'Children section in Global Sections content type was not found. Please add a Children Section.' ) - // Add Children section if missing - const headerSections = globalSectionsHeader?.sections || [] - const footerSections = globalSectionsFooter?.sections || [] - - return { - ...globalSections, - sections: [ - ...headerSections, - ...globalSections.sections, - { - name: 'Children', - data: {}, - }, - ...footerSections, - ], - } } const headerSections = globalSectionsHeader?.sections || [] From 1e67626122983b834625948ddc828d4faf0b247e Mon Sep 17 00:00:00 2001 From: fanny Date: Wed, 7 Jan 2026 23:24:00 -0300 Subject: [PATCH 12/15] chore: Removes console.log tests --- .../core/src/components/templates/LandingPage/LandingPage.tsx | 4 ++-- packages/core/src/pages/[...slug].tsx | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/core/src/components/templates/LandingPage/LandingPage.tsx b/packages/core/src/components/templates/LandingPage/LandingPage.tsx index 73a12e2259..eb4131b1bc 100644 --- a/packages/core/src/components/templates/LandingPage/LandingPage.tsx +++ b/packages/core/src/components/templates/LandingPage/LandingPage.tsx @@ -117,8 +117,6 @@ export const getLandingPageBySlug = async ( previewData: PreviewData, locale?: string ) => { - console.log('🌐 Locale from context (getLandingPageBySlug):', locale) - try { if (storeConfig.cms.data) { const cmsData = JSON.parse(storeConfig.cms.data) @@ -133,6 +131,8 @@ export const getLandingPageBySlug = async ( previewData, locale, // documentId: pageBySlug.documentId, + // TODO: uncomment line above and remove line below. + // REMOVE below line just for testing purposes - passing documentId manually documentId: '11a7ccfb-ac7e-4ab0-ab5b-7438106edb3d', versionId: pageBySlug.versionId, releaseId: pageBySlug.releaseId, diff --git a/packages/core/src/pages/[...slug].tsx b/packages/core/src/pages/[...slug].tsx index 05bb901e48..8bcb648320 100644 --- a/packages/core/src/pages/[...slug].tsx +++ b/packages/core/src/pages/[...slug].tsx @@ -118,8 +118,6 @@ export const getStaticProps: GetStaticProps< const slug = params?.slug.join('/') ?? '' const rewrites = (await storeConfig.rewrites?.()) ?? [] - console.log('🌐 Locale from context (slug.tsx):', locale) - const [ globalSectionsPromise, globalSectionsHeaderPromise, From 469a7470de269f893b5c8567fd8ae17e707c4a13 Mon Sep 17 00:00:00 2001 From: fanny Date: Tue, 20 Jan 2026 22:12:29 -0300 Subject: [PATCH 13/15] chore: Updates naming --- packages/core/src/server/content/service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/server/content/service.ts b/packages/core/src/server/content/service.ts index 24c5000b68..d0d9c97a6d 100644 --- a/packages/core/src/server/content/service.ts +++ b/packages/core/src/server/content/service.ts @@ -23,7 +23,7 @@ export class ContentService { private clientCPCache = new Map() private getClientCP(locale?: string): ClientCP { - const currentLocale = locale ?? config.i18n.defaultLocale + const currentLocale = locale ?? config.localization.defaultLocale // Reuse cached ClientCP for locale if (this.clientCPCache.has(currentLocale)) { From be953ef5ff86909324488227ba795a95001047b3 Mon Sep 17 00:00:00 2001 From: fanny Date: Tue, 20 Jan 2026 22:19:18 -0300 Subject: [PATCH 14/15] chore: Undo specifics test changes --- .../templates/LandingPage/LandingPage.tsx | 16 +++++----------- packages/core/src/server/cms/global.ts | 2 -- packages/core/src/server/content/service.ts | 3 +-- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/packages/core/src/components/templates/LandingPage/LandingPage.tsx b/packages/core/src/components/templates/LandingPage/LandingPage.tsx index eb4131b1bc..c4c041c471 100644 --- a/packages/core/src/components/templates/LandingPage/LandingPage.tsx +++ b/packages/core/src/components/templates/LandingPage/LandingPage.tsx @@ -130,10 +130,7 @@ export const getLandingPageBySlug = async ( contentType: 'landingPage', previewData, locale, - // documentId: pageBySlug.documentId, - // TODO: uncomment line above and remove line below. - // REMOVE below line just for testing purposes - passing documentId manually - documentId: '11a7ccfb-ac7e-4ab0-ab5b-7438106edb3d', + documentId: pageBySlug.documentId, versionId: pageBySlug.versionId, releaseId: pageBySlug.releaseId, slug: pageBySlug.settings?.seo?.slug, @@ -149,13 +146,10 @@ export const getLandingPageBySlug = async ( previewData, slug, locale, - // TODO: REMOVE just for testing purposes - passing documentId manually - documentId: '11a7ccfb-ac7e-4ab0-ab5b-7438106edb3d', - // TODO: puts back the filters when the default documentId is removed - // filters: - // previewData?.contentType !== 'landingPage' - // ? { filters: { 'settings.seo.slug': `/${slug}` } } - // : undefined, + filters: + previewData?.contentType !== 'landingPage' + ? { filters: { 'settings.seo.slug': `/${slug}` } } + : undefined, }) return landingPageData } catch (error) { diff --git a/packages/core/src/server/cms/global.ts b/packages/core/src/server/cms/global.ts index c35ad2d6f8..b2a2cbd33d 100644 --- a/packages/core/src/server/cms/global.ts +++ b/packages/core/src/server/cms/global.ts @@ -12,8 +12,6 @@ export function injectGlobalSections({ globalSectionsHeader, globalSectionsFooter, }: InjectGlobalSectionsProps) { - // TODO: remover later - // Temp Handle case when globalSections or sections array is undefined/empty if ( !globalSections || !globalSections.sections || diff --git a/packages/core/src/server/content/service.ts b/packages/core/src/server/content/service.ts index d0d9c97a6d..1e4e4e2571 100644 --- a/packages/core/src/server/content/service.ts +++ b/packages/core/src/server/content/service.ts @@ -217,8 +217,7 @@ export class ContentService { const { cmsOptions } = options const params: Partial = { accountName: config.api.storeId, - // storeId: 'faststore', - storeId: 'multilanguage', + storeId: 'faststore', contentType: cmsOptions.contentType, slug: options.slug, } From 26182a3569a15d49555b7979b990e2eba7041140 Mon Sep 17 00:00:00 2001 From: fanny Date: Thu, 22 Jan 2026 16:21:22 -0300 Subject: [PATCH 15/15] fix: Passes locale parameter forward --- packages/core/src/pages/checkout.tsx | 4 ++-- packages/core/src/pages/index.tsx | 2 +- packages/core/src/server/content/service.ts | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/core/src/pages/checkout.tsx b/packages/core/src/pages/checkout.tsx index 6ccc486c0a..9cc9d2e44c 100644 --- a/packages/core/src/pages/checkout.tsx +++ b/packages/core/src/pages/checkout.tsx @@ -55,12 +55,12 @@ export const getStaticProps: GetStaticProps< Props, Record, Locator -> = async ({ previewData }) => { +> = async ({ previewData, locale }) => { const [ globalSectionsPromise, globalSectionsHeaderPromise, globalSectionsFooterPromise, - ] = getGlobalSectionsData(previewData) + ] = getGlobalSectionsData(previewData, locale) const [globalSections, globalSectionsHeader, globalSectionsFooter] = await Promise.all([ diff --git a/packages/core/src/pages/index.tsx b/packages/core/src/pages/index.tsx index 388b9d9305..ba473ae4bf 100644 --- a/packages/core/src/pages/index.tsx +++ b/packages/core/src/pages/index.tsx @@ -159,7 +159,7 @@ export const getStaticProps: GetStaticProps< globalSectionsPromise, globalSectionsHeaderPromise, globalSectionsFooterPromise, - ] = getGlobalSectionsData(previewData) + ] = getGlobalSectionsData(previewData, locale) const serverDataPromise = getDynamicContent({ pageType: 'home' }) let cmsPage = null diff --git a/packages/core/src/server/content/service.ts b/packages/core/src/server/content/service.ts index 1e4e4e2571..555714ad2f 100644 --- a/packages/core/src/server/content/service.ts +++ b/packages/core/src/server/content/service.ts @@ -193,7 +193,11 @@ export class ContentService { if (entries.length > 1) { throw new MultipleContentError(params) } - return this.getEntryData({ ...params, entryId: entries[0].id }, isPreview) + return this.getEntryData( + { ...params, entryId: entries[0].id }, + isPreview, + locale + ) } private createContentOptions(params: ContentParams): ContentOptions {