Skip to content

Fix international SEO, Market-aware routing, SKU fallback, and extension hydration - #198

Merged
damianlegawiec merged 13 commits into
spree:mainfrom
laaichiu:fix-issues-191-188-180-187
Jul 24, 2026
Merged

Fix international SEO, Market-aware routing, SKU fallback, and extension hydration#198
damianlegawiec merged 13 commits into
spree:mainfrom
laaichiu:fix-issues-191-188-180-187

Conversation

@laaichiu

@laaichiu laaichiu commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR fixes several storefront issues related to product data, international SEO, locale routing, sitemap generation, and hydration behavior.

It also introduces a shared Market-aware locale foundation so routing, metadata, and sitemaps use the same set of storefront-supported locales.

Changes

Display the default variant SKU

Products without custom variants now display the SKU from default_variant.

  • Expands default_variant on product detail requests.
  • Prefers the selected variant SKU when available.
  • Falls back to the default/master variant SKU for single-variant products.

Add canonical metadata to policy pages

Policy pages now generate a localized canonical URL using the current country, locale, and resolved policy slug.

  • Adds rel="canonical" metadata.
  • Uses the same URL for Open Graph metadata.
  • Fetches policies with explicit locale and country context.
  • Treats only API 404 responses as missing policies instead of hiding unrelated API errors.

Make routing and sitemaps Market-aware

Locale handling is now derived from a single registry of storefront message bundles and the Markets returned by the Store API.

Routing now:

  • Canonicalizes BCP 47 locale values.
  • Validates locales against the bundles the storefront can render.
  • Negotiates Accept-Language using quality weights.
  • Preserves the current pathname and query string during redirects.
  • Synchronizes country and locale cookies with the URL.
  • Redirects unsupported locales to a valid configured fallback.
  • Sets the document lang and dir attributes from the resolved route locale.

Sitemaps now:

  • Include every renderable Market/country/locale combination.
  • Keep inventories isolated when Markets share a locale.
  • Include localized static, product, and category URLs.
  • Split large catalogs into bounded sitemap files.
  • Limit Store API concurrency and fetch only pages needed by the requested chunk.
  • Isolate product and category failures so one failed request does not discard the remaining sitemap.
  • Avoid process-level catalog caches that could retain stale Market data.

Tolerate browser-extension root mutations

Adds suppressHydrationWarning only to the root <html> element.

This handles extensions that inject classes or inline styles before React hydrates the document, while still allowing hydration mismatches inside the application tree to be reported normally.

Add reciprocal Market-aware hreflang metadata

Localized metadata is now generated for:

  • Homepage
  • Product listing
  • Category listing
  • Product details
  • Category details
  • Policy details

The hreflang implementation:

  • Builds a reciprocal cluster across every Market served by the storefront.
  • Generates regional codes such as en-US and de-DE when multiple countries are present.
  • Resolves localized product, category, and policy slugs by stable resource ID.
  • Publishes only locales that are enabled by the Market and supported by a storefront message bundle.
  • Detects Spree/Mobility fallback content and does not advertise it as a real translation.
  • Canonicalizes fallback pages to the current Market's renderable default-locale version.
  • Generates a stable and deterministic x-default.
  • Falls back to self-referencing metadata if the Markets API is temporarily unavailable.

Adding a new storefront locale now requires only registering its message loader and enabling it in the relevant Market; middleware, metadata, and sitemap generation will use it automatically.

Verification

  • pnpm test — 24 test files, 174 tests passed
  • pnpm check:locales
  • pnpm exec tsc --noEmit
  • pnpm check
  • pnpm build
  • git diff --check

Additional runtime scenarios verified:

  • Reciprocal hreflang clusters remain identical across localized versions.
  • Missing translations are excluded from hreflang output.
  • Fallback pages canonicalize to the Market default locale.
  • x-default remains stable across Markets and locales.
  • An unsupported configured default locale redirects to an available locale instead of redirecting to itself.

Closes #191
Closes #188
Closes #180
Closes #187

Summary by CodeRabbit

  • New Features
    • Improved country and language routing with locale negotiation, redirects, and search/path preservation.
    • Expanded localized SEO metadata: hreflang alternates and Open Graph URLs for home, products, categories, and policy pages.
    • Product details now show the default variant SKU when the selected variant has no SKU.
    • Sitemap generation is now more dynamic and chunked by market/locale for better coverage and performance.
  • Bug Fixes
    • Strengthened locale/market validation and fallbacks to reduce missing/incorrect localized content.
    • Added/confirmed right-to-left direction support for rendered documents.
  • Chores
    • Added comprehensive automated tests for routing, metadata, and sitemap behavior.

@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

@laaichiu is attempting to deploy a commit to the Spree Commerce Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@laaichiu, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 59 seconds

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a1b1e28b-a5bb-4eff-8a88-f28b466cace6

📥 Commits

Reviewing files that changed from the base of the PR and between e1fde60 and 2f05a18.

📒 Files selected for processing (4)
  • src/app/[country]/[locale]/(storefront)/layout.test.tsx
  • src/app/[country]/[locale]/(storefront)/layout.tsx
  • src/components/layout/Footer.tsx
  • src/components/layout/Header.tsx

Walkthrough

The PR centralizes locale configuration and negotiation, adds market-aware routing and runtime message loading, introduces localized canonical and hreflang metadata, refactors sitemap generation around chunked catalog ranges, improves asynchronous storefront navigation, and fixes SKU rendering for products without custom variants.

Changes

Localized storefront routing

Layer / File(s) Summary
Locale and market resolution
src/i18n/*, src/types/next-intl.d.ts
Adds supported-locale loading, normalization, negotiation, market targeting, redirect construction, and shared locale typing.
Middleware and application layout
src/lib/spree/middleware.ts, src/proxy.ts, src/app/[country]/[locale]/layout.tsx, src/app/[country]/[locale]/layout.test.tsx
Adds supported-locale middleware negotiation, market-aware redirects, preserved pathname/query context, dynamic messages, and typed providers.
Document and storefront rendering
src/components/layout/DocumentShell.tsx, src/app/dev/layout.tsx, src/app/[country]/[locale]/(storefront)/layout.tsx
Introduces locale-aware document markup, direction detection, hydration-warning suppression, and Suspense-based navigation loading.

Localized metadata and policy retrieval

Layer / File(s) Summary
Alternate metadata engine
src/lib/metadata/alternates.ts, src/lib/metadata/__tests__/alternates.test.ts
Builds localized canonical URLs, hreflang maps, x-default targets, and translation-fallback handling.
Storefront metadata
src/lib/metadata/{home,products,product,categories,category}.ts
Adds localized alternates to home, catalog, category, and product metadata.
Policy metadata and caching
src/lib/data/policies.ts, src/app/[country]/[locale]/(storefront)/policies/[slug]/page.tsx
Adds localized policy lookup, cached error handling, policy fingerprints, and canonical/Open Graph metadata.

Chunked sitemap generation

Layer / File(s) Summary
Sitemap data access
src/lib/data/sitemap.ts, src/lib/data/__tests__/sitemap.test.ts
Adds cached market, count, product-page, and category-page helpers.
Catalog chunks and range fetching
src/app/sitemap.ts, src/app/sitemap.test.ts, src/app/robots.ts
Computes locale catalogs, validates chunks, fetches intersecting ranges with bounded concurrency, reuses page promises, and forces dynamic robots evaluation.

Product detail SKU fallback

Layer / File(s) Summary
Default variant SKU
src/app/[country]/[locale]/(storefront)/products/[slug]/ProductDetails.tsx, src/lib/data/cached.ts, src/app/[country]/[locale]/(storefront)/products/[slug]/ProductDetails.test.tsx
Displays the selected SKU or default variant SKU and expands/tests default variant data.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Poem

A rabbit hops through locales bright,
Canonical links gleam in moonlit light.
Markets turn, and sitemaps grow,
Default SKUs proudly show.
“Hreflang!” the bunny sings with cheer—
Every storefront route is clear.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR adds broad i18n, routing, sitemap, and layout refactors that are not required by the linked issues. Split the unrelated routing/i18n/sitemap/layout work into separate PRs, or explain why each change is needed for the linked issues.
Docstring Coverage ⚠️ Warning Docstring coverage is 26.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main fixes: SEO metadata, market-aware routing, SKU fallback, and hydration handling.
Linked Issues check ✅ Passed The PR covers #191, #188, #180, and #187 with SKU fallback, canonical metadata, html hydration suppression, and hreflang metadata.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (8)
src/app/[country]/[locale]/(storefront)/products/[slug]/ProductDetails.test.tsx (3)

36-70: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Type-check the product fixture instead of bypassing it.

as unknown as Product suppresses SDK shape validation. Use satisfies Product (and fill required fields) or a typed fixture builder so SDK contract changes fail the test at compile time.

As per coding guidelines, “use satisfies for type checking object literals.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/app/`[country]/[locale]/(storefront)/products/[slug]/ProductDetails.test.tsx
around lines 36 - 70, Update the productWithoutCustomVariants fixture to use
satisfies Product instead of as unknown as Product, adding any required Product
fields so the object conforms to the SDK contract and future shape changes fail
compilation.

Source: Coding guidelines


5-5: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use the configured absolute import alias.

Replace ./ProductDetails with its @/app/.../ProductDetails path.

As per coding guidelines, “Use absolute imports with @/ alias prefix instead of relative imports.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/app/`[country]/[locale]/(storefront)/products/[slug]/ProductDetails.test.tsx
at line 5, Update the ProductDetails import in the test to use the configured `@/`
absolute alias and the module’s full app path instead of the relative
"./ProductDetails" path.

Source: Coding guidelines


7-34: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add explicit return types to the new callbacks.

The mock factories/components and describe/it callbacks currently rely on inferred return types.

As per coding guidelines, “Always define explicit return types for functions.”

Also applies to: 72-88

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/app/`[country]/[locale]/(storefront)/products/[slug]/ProductDetails.test.tsx
around lines 7 - 34, Add explicit return type annotations to the callback
functions introduced in the test, including the vi.mock factories, mocked
components, and describe/it callbacks. Update the callbacks near the mocked
modules and the additional callbacks around the referenced later section, using
appropriate return types while preserving their existing behavior.

Source: Coding guidelines

src/lib/data/sitemap.ts (1)

23-28: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add an explicit return type to getSitemapMarkets.

Unlike the other three exports, this function has no explicit return type and relies on inference of .data.

As per coding guidelines: "Always define explicit return types for functions."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/data/sitemap.ts` around lines 23 - 28, Update the exported
getSitemapMarkets function to declare an explicit return type matching the
resolved type of the markets.list(options).data result, consistent with the
other sitemap exports, while preserving its existing implementation.

Source: Coding guidelines

src/app/[country]/[locale]/layout.tsx (1)

87-133: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Parallelize the independent getMarkets/loadMessages calls.

loadMessages(requestedLocale) only depends on requestedLocale, which is known before getMarkets is even called, yet it's awaited later, after several branches. Per the project's data-fetching guideline, kick both off together and await loadMessages where needed.

⚡ Sketch: start loadMessages alongside getMarkets
   const requestedLocale = resolveSupportedLocale(locale);
   if (!requestedLocale) notFound();
 
-  const markets = await getMarkets({ country, locale: requestedLocale })
-    .then((res) => res.data)
-    .catch(() => null);
+  const messagesPromise = loadMessages(requestedLocale);
+  const markets = await getMarkets({ country, locale: requestedLocale })
+    .then((res) => res.data)
+    .catch(() => null);

Then replace the later const messages = await loadMessages(requestedLocale); occurrences with await messagesPromise.

As per coding guidelines, "Use Promise.all() for parallel data fetching in server components instead of sequential awaits."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`[country]/[locale]/layout.tsx around lines 87 - 133, Parallelize the
independent market and message fetches in the layout’s data-loading flow: start
getMarkets and loadMessages(requestedLocale) together using Promise.all, retain
the existing markets error handling and validation branches, and replace every
later loadMessages await with the shared messages result.

Source: Coding guidelines

src/lib/spree/middleware.test.ts (1)

22-32: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Use buildLocalizedRedirectPath for middleware locale redirects.

buildLocalizedRedirectPath exists in src/i18n/routing.ts, but this middleware still reimplements prefix matching/slicing in createSpreeMiddleware. Reuse that helper for lines 108–132 to keep middleware and layout-level redirects aligned.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/spree/middleware.test.ts` around lines 22 - 32, Update
createSpreeMiddleware’s locale redirect logic to use the existing
buildLocalizedRedirectPath helper from routing.ts instead of reimplementing
locale prefix matching and path slicing. Preserve the current redirect behavior,
including retaining the request path and applying the resolved country and
locale values.
src/lib/metadata/alternates.ts (1)

194-210: 🧹 Nitpick | 🔵 Trivial

Consider logging swallowed resolvePath failures.

.catch(() => null) treats a genuine "no localized resource" 404 and a transient Store API 500 identically, silently dropping that locale from the hreflang cluster (this is called out as deliberate in the docstring at lines 137-146, so not raising as a bug). For SEO-facing output it may be worth at least logging/observing these failures so a temporary Store API blip isn't mistaken for permanently-missing translations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/metadata/alternates.ts` around lines 194 - 210, Add observability to
the resolvePath failure handler in resolveLocalizedResource without changing its
existing null-return behavior. Capture the rejection error and log or report it
through the module’s established logging/monitoring mechanism, while continuing
to cache and return null for failed resolutions.
src/app/[country]/[locale]/(storefront)/policies/[slug]/page.test.tsx (1)

16-19: 📐 Maintainability & Code Quality | 🔵 Trivial

Consider testing generateMetadata's resolvePath closure directly.

buildLocalizedAlternates is fully mocked here, so the actual resolvePath implementation in page.tsx (which calls cachedGetPolicy(policy.id, target) and maps its result to { path, fingerprint } or undefined) is untested by this file, and isn't covered elsewhere with the real closure either. Consider asserting the args passed to buildLocalizedAlternates (via mock.calls) and/or invoking the captured resolvePath callback with a mocked cachedGetPolicy to cover the null/localized-slug mapping.

Also applies to: 49-81

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`[country]/[locale]/(storefront)/policies/[slug]/page.test.tsx around
lines 16 - 19, Extend the generateMetadata tests to cover the real resolvePath
closure in page.tsx instead of only mocking buildLocalizedAlternates. Inspect
buildLocalizedAlternates mock.calls to capture and invoke resolvePath, mock
cachedGetPolicy with matching and null results, and assert it returns { path,
fingerprint } for localized policies and undefined when no policy is found.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`[country]/[locale]/layout.tsx:
- Around line 109-122: Update the currentMarket fallback in the layout component
to avoid redirecting when fallbackCountry and fallbackLocale match the requested
country and locale; use the existing outage-safe render path for this
empty-markets case instead. Preserve the redirect behavior when the fallback
target differs, and add coverage for getMarkets resolving to an empty data array
on the default route.

In `@src/lib/spree/middleware.ts`:
- Around line 106-122: Update the locale resolution for the country/locale
prefix in the middleware’s visible locale-matching flow to use negotiateLocale()
instead of matchLocale(), allowing values such as en-US to resolve to the
configured en bundle. Preserve the requested country and let the existing
canonical-prefix redirect normalize the locale spelling; only use the
defaultCountry/defaultLocale fallback when negotiation returns no locale.

---

Nitpick comments:
In `@src/app/`[country]/[locale]/(storefront)/policies/[slug]/page.test.tsx:
- Around line 16-19: Extend the generateMetadata tests to cover the real
resolvePath closure in page.tsx instead of only mocking
buildLocalizedAlternates. Inspect buildLocalizedAlternates mock.calls to capture
and invoke resolvePath, mock cachedGetPolicy with matching and null results, and
assert it returns { path, fingerprint } for localized policies and undefined
when no policy is found.

In
`@src/app/`[country]/[locale]/(storefront)/products/[slug]/ProductDetails.test.tsx:
- Around line 36-70: Update the productWithoutCustomVariants fixture to use
satisfies Product instead of as unknown as Product, adding any required Product
fields so the object conforms to the SDK contract and future shape changes fail
compilation.
- Line 5: Update the ProductDetails import in the test to use the configured `@/`
absolute alias and the module’s full app path instead of the relative
"./ProductDetails" path.
- Around line 7-34: Add explicit return type annotations to the callback
functions introduced in the test, including the vi.mock factories, mocked
components, and describe/it callbacks. Update the callbacks near the mocked
modules and the additional callbacks around the referenced later section, using
appropriate return types while preserving their existing behavior.

In `@src/app/`[country]/[locale]/layout.tsx:
- Around line 87-133: Parallelize the independent market and message fetches in
the layout’s data-loading flow: start getMarkets and
loadMessages(requestedLocale) together using Promise.all, retain the existing
markets error handling and validation branches, and replace every later
loadMessages await with the shared messages result.

In `@src/lib/data/sitemap.ts`:
- Around line 23-28: Update the exported getSitemapMarkets function to declare
an explicit return type matching the resolved type of the
markets.list(options).data result, consistent with the other sitemap exports,
while preserving its existing implementation.

In `@src/lib/metadata/alternates.ts`:
- Around line 194-210: Add observability to the resolvePath failure handler in
resolveLocalizedResource without changing its existing null-return behavior.
Capture the rejection error and log or report it through the module’s
established logging/monitoring mechanism, while continuing to cache and return
null for failed resolutions.

In `@src/lib/spree/middleware.test.ts`:
- Around line 22-32: Update createSpreeMiddleware’s locale redirect logic to use
the existing buildLocalizedRedirectPath helper from routing.ts instead of
reimplementing locale prefix matching and path slicing. Preserve the current
redirect behavior, including retaining the request path and applying the
resolved country and locale values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 090b2ebd-9cda-45ef-bde5-b0fae1a6d0e7

📥 Commits

Reviewing files that changed from the base of the PR and between 13d86fa and 77f5414.

📒 Files selected for processing (38)
  • src/app/[country]/[locale]/(storefront)/page.tsx
  • src/app/[country]/[locale]/(storefront)/policies/[slug]/page.test.tsx
  • src/app/[country]/[locale]/(storefront)/policies/[slug]/page.tsx
  • src/app/[country]/[locale]/(storefront)/products/[slug]/ProductDetails.test.tsx
  • src/app/[country]/[locale]/(storefront)/products/[slug]/ProductDetails.tsx
  • src/app/[country]/[locale]/layout.test.tsx
  • src/app/[country]/[locale]/layout.tsx
  • src/app/dev/layout.tsx
  • src/app/robots.ts
  • src/app/sitemap.test.ts
  • src/app/sitemap.ts
  • src/components/layout/DocumentShell.test.tsx
  • src/components/layout/DocumentShell.tsx
  • src/i18n/__tests__/locales.test.ts
  • src/i18n/__tests__/markets.test.ts
  • src/i18n/__tests__/routing.test.ts
  • src/i18n/locales.ts
  • src/i18n/markets.ts
  • src/i18n/normalize.ts
  • src/i18n/request.ts
  • src/i18n/routing.ts
  • src/lib/data/__tests__/policies.test.ts
  • src/lib/data/__tests__/sitemap.test.ts
  • src/lib/data/cached.ts
  • src/lib/data/categories.ts
  • src/lib/data/policies.ts
  • src/lib/data/sitemap.ts
  • src/lib/metadata/__tests__/alternates.test.ts
  • src/lib/metadata/alternates.ts
  • src/lib/metadata/categories.ts
  • src/lib/metadata/category.ts
  • src/lib/metadata/home.ts
  • src/lib/metadata/product.ts
  • src/lib/metadata/products.ts
  • src/lib/spree/middleware.test.ts
  • src/lib/spree/middleware.ts
  • src/proxy.ts
  • src/types/next-intl.d.ts

Comment thread src/app/[country]/[locale]/layout.tsx
Comment thread src/lib/spree/middleware.ts
@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
storefront Ready Ready Preview, Comment Jul 24, 2026 4:25pm

Request Review

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/app/[country]/[locale]/layout.test.tsx (1)

26-29: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Type the new mock and test callbacks explicitly.

Add return annotations and use satisfies (or an equivalent typed mock) so the @/lib/store mock cannot drift from its module contract; annotate the async test callback as async (): Promise<void> =>.

Also applies to: 111-111

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`[country]/[locale]/layout.test.tsx around lines 26 - 29, Type the
`@/lib/store` mock explicitly by annotating getDefaultCountry and getDefaultLocale
return values and constraining the mock with satisfies or an equivalent typed
mock against the module contract. Update the async test callback referenced in
the test to use the explicit async (): Promise<void> signature.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/app/`[country]/[locale]/layout.test.tsx:
- Around line 26-29: Type the `@/lib/store` mock explicitly by annotating
getDefaultCountry and getDefaultLocale return values and constraining the mock
with satisfies or an equivalent typed mock against the module contract. Update
the async test callback referenced in the test to use the explicit async ():
Promise<void> signature.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 23eaf9e0-3942-432b-8a96-48b2c8aa480a

📥 Commits

Reviewing files that changed from the base of the PR and between 77f5414 and 52eafda.

📒 Files selected for processing (2)
  • src/app/[country]/[locale]/layout.test.tsx
  • src/app/[country]/[locale]/layout.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/[country]/[locale]/layout.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`[country]/[locale]/(storefront)/layout.tsx:
- Around line 14-44: Update the navigation Suspense boundaries that currently
use async Header and Footer fallbacks: move category-aware Header/Footer
rendering into the suspended content, and replace each fallback with a
lightweight synchronous skeleton or loading placeholder. Keep the existing
getRootCategories and Header/Footer category behavior unchanged once the
boundary resolves.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c9c29262-94b7-4172-a0e7-420384c5e45f

📥 Commits

Reviewing files that changed from the base of the PR and between 52eafda and e1fde60.

📒 Files selected for processing (6)
  • src/app/[country]/[locale]/(storefront)/layout.tsx
  • src/app/[country]/[locale]/(storefront)/products/[slug]/ProductDetails.tsx
  • src/app/[country]/[locale]/layout.test.tsx
  • src/app/[country]/[locale]/layout.tsx
  • src/lib/data/categories.ts
  • src/lib/spree/middleware.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/app/[country]/[locale]/(storefront)/products/[slug]/ProductDetails.tsx
  • src/app/[country]/[locale]/layout.tsx
  • src/lib/spree/middleware.ts

Comment thread src/app/[country]/[locale]/(storefront)/layout.tsx
@damianlegawiec
damianlegawiec merged commit a3d8454 into spree:main Jul 24, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants