Skip to content

Use Categories#51

Merged
damianlegawiec merged 2 commits into
mainfrom
fix/categories
Mar 10, 2026
Merged

Use Categories#51
damianlegawiec merged 2 commits into
mainfrom
fix/categories

Conversation

@damianlegawiec
Copy link
Copy Markdown
Member

@damianlegawiec damianlegawiec commented Mar 10, 2026

Summary by CodeRabbit

  • Refactor

    • Header now shows dynamic top-level categories and links to category pages (/c/...), improving navigation.
    • Category browsing and product pages switched to category-based URLs and breadcrumbs (removed static “Categories” link).
    • Store initialization now seeds market/country data earlier to stabilize locale/currency behavior.
  • Bug Fixes

    • "Browse Categories" and Footer category links now point to the unified products listing.
  • Chores

    • Updated dependencies: @spree/next and @spree/sdk to ^0.8.1.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 10, 2026

Walkthrough

Migrates the storefront from taxon/taxonomies to category-based APIs and routes: adds category data wrappers, removes taxonomies module and page, renames props/paths from taxon→category, fetches root categories in StorefrontLayout and passes them to Header, and initializes StoreProvider with markets passed from root layout.

Changes

Cohort / File(s) Summary
Dependency Updates
package.json
Bumps @spree/next and @spree/sdk from ^0.8.0^0.8.1.
Data layer: categories added / taxonomies removed
src/lib/data/categories.ts, src/lib/data/index.ts, src/lib/data/taxonomies.ts, src/lib/data/products.ts
Adds getCategories, getCategory, getCategoryProducts wrappers. Removes the taxonomies data module and the getTaxonProducts export. Re-exports updated to include categories and drop taxonomies.
Category pages & product content
src/app/.../c/[...permalink]/page.tsx, src/app/.../c/[...permalink]/CategoryProductsContent.tsx
Replaces taxon-based fetches/usages with category equivalents: imports, function calls, prop names, filter params, routes (/t//c/), and UI labels.
Layouts & routing
src/app/[country]/[locale]/(storefront)/layout.tsx, src/app/[country]/[locale]/layout.tsx, src/app/[country]/[locale]/(storefront)/page.tsx, src/app/.../taxonomies/page.tsx
Makes StorefrontLayout async and fetch root categories; passes rootCategories to Header. Root layout fetches markets and passes initialMarkets to StoreProvider. Updates Browse Categories link to /products. Removes entire taxonomies page.
Header, Footer, Breadcrumbs
src/components/layout/Header.tsx, src/components/layout/Footer.tsx, src/components/navigation/Breadcrumbs.tsx
Header now accepts rootCategories: Category[] prop and renders dynamic category links (/c/{permalink}). Footer link updated to /products. Breadcrumbs refactored from taxon→category props and routes.
Components & hooks
src/components/products/ProductCarousel.tsx, src/hooks/useCarouselProducts.ts
Renames taxonIdcategoryId in props/hook. Hook switches from getTaxonProducts to getCategoryProducts with fallback to getProducts.
Context & store init
src/contexts/StoreContext.tsx
Adds initialMarkets to StoreProviderProps. Replaces runtime markets fetch and loading flow with synchronous initialization from initialMarkets; moves redirect handling to a guarded synchronous flow that sets cookies and router.replace.
Analytics mapping
src/lib/analytics/gtm.ts
GA4 mapping now reads item category from product.categories[0].name instead of product.taxons[0].name.

Sequence Diagram(s)

sequenceDiagram
  participant Req as Browser Request
  participant Layout as StorefrontLayout (server)
  participant CategoriesAPI as getCategories (server)
  participant RootHeader as Header (server-render)
  participant RootLayout as Root Layout (server)
  participant MarketsAPI as getMarkets (server)
  participant StoreProv as StoreProvider (client/server)
  participant Router as next/router

  Req->>Layout: request /c/{permalink}
  Layout->>CategoriesAPI: listCategories(depth_eq:0)
  CategoriesAPI-->>Layout: rootCategories
  Layout->>RootHeader: render Header with rootCategories
  Req->>RootLayout: page-level render
  RootLayout->>MarketsAPI: getMarkets()
  MarketsAPI-->>RootLayout: initialMarkets
  RootLayout->>StoreProv: initialize(initialMarkets, initialCountry/Locale)
  StoreProv->>StoreProv: compute initialCountries/initialResolved
  alt needs redirect
    StoreProv->>Router: router.replace(newPath) and set cookies
  end
  RootHeader-->>Req: rendered header with category links
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hopped from taxons to categories today,
Links now /c/ where /t/ used to play,
Headers bloom with roots fetched bright and clear,
Markets load early — no async delay here,
A carrot for categories — hop, cheer! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'Use Categories' directly reflects the main objective of migrating from taxon-based to category-based naming throughout the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/categories

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/app/[country]/[locale]/(storefront)/c/[...permalink]/page.tsx (1)

17-83: Add generateMetadata for SEO.

As per coding guidelines, pages with route params should use generateMetadata to dynamically generate SEO metadata. This page fetches category data that could populate title, description, and OpenGraph tags.

📝 Suggested implementation
import type { Metadata } from "next";

export async function generateMetadata({ params }: CategoryPageProps): Promise<Metadata> {
  const { permalink } = await params;
  const fullPermalink = permalink.join("/");
  
  try {
    const category = await getCategory(fullPermalink);
    return {
      title: category?.name,
      description: category?.description,
    };
  } catch {
    return {};
  }
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`[country]/[locale]/(storefront)/c/[...permalink]/page.tsx around
lines 17 - 83, Add a server-side generateMetadata function to produce dynamic
SEO metadata for this paramized page: implement export async function
generateMetadata({ params }: CategoryPageProps): Promise<Metadata> that builds
fullPermalink from params.permalink, calls getCategory(fullPermalink) (handle
errors with try/catch) and returns title: category?.name and description:
category?.description (plus optional openGraph fields if desired); keep it
separate from the CategoryPage default export and import Metadata type from
"next".
src/components/layout/Footer.tsx (1)

22-36: Both "All Products" and "Categories" links point to the same URL.

Lines 23 and 31 both link to /products, which may confuse users expecting distinct destinations. Consider either:

  • Differentiating the destinations (e.g., /products vs /categories or /products?view=categories)
  • Removing one of the duplicate links
  • Adding a query parameter to distinguish the intent (e.g., /products?filter=categories)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/layout/Footer.tsx` around lines 22 - 36, The two Link elements
in Footer.tsx render "All Products" and "Categories" but both use
href="/products"; update the href on the Link that renders the "Categories" text
to a distinct destination (for example change the Link with children
"Categories" to href="/categories" or href="/products?filter=categories") so the
Link component with inner text "Categories" no longer points to the same URL as
the Link component with inner text "All Products".
src/app/[country]/[locale]/(storefront)/page.tsx (1)

29-35: Both buttons link to the same destination.

The "Shop Now" and "Browse Categories" buttons now both navigate to ${basePath}/products. While this may be intentional after removing the taxonomies page, having two adjacent buttons with identical destinations could confuse users. Consider whether "Browse Categories" should link to a different view (e.g., /products?view=categories or a future categories landing page) or if one button should be removed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`[country]/[locale]/(storefront)/page.tsx around lines 29 - 35, The
two adjacent Button components (Button size="lg" asChild and Button
variant="outline" size="lg" asChild) both use Link
href={`${basePath}/products`}, which duplicates destinations; update the second
Button (the one labeled "Browse Categories") to point to a distinct destination
(for example change its Link href to `${basePath}/products?view=categories` or
to the planned categories landing route) or remove the duplicate button entirely
so users are not confused.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/`[country]/[locale]/(storefront)/c/[...permalink]/page.tsx:
- Around line 60-68: Replace the plain <a> used inside category.children.map
with Next.js' Link to enable client-side navigation: import Link from
"next/link" at the top of the file and swap the <a key={child.id}
href={`${basePath}/c/${child.permalink}`} className="...">...</a> for a <Link
href={`${basePath}/c/${child.permalink}`} key={child.id} className="...">
{child.name} </Link> (retain the same className and content); ensure the unique
key remains on the Link element so React list rendering is preserved.

---

Nitpick comments:
In `@src/app/`[country]/[locale]/(storefront)/c/[...permalink]/page.tsx:
- Around line 17-83: Add a server-side generateMetadata function to produce
dynamic SEO metadata for this paramized page: implement export async function
generateMetadata({ params }: CategoryPageProps): Promise<Metadata> that builds
fullPermalink from params.permalink, calls getCategory(fullPermalink) (handle
errors with try/catch) and returns title: category?.name and description:
category?.description (plus optional openGraph fields if desired); keep it
separate from the CategoryPage default export and import Metadata type from
"next".

In `@src/app/`[country]/[locale]/(storefront)/page.tsx:
- Around line 29-35: The two adjacent Button components (Button size="lg"
asChild and Button variant="outline" size="lg" asChild) both use Link
href={`${basePath}/products`}, which duplicates destinations; update the second
Button (the one labeled "Browse Categories") to point to a distinct destination
(for example change its Link href to `${basePath}/products?view=categories` or
to the planned categories landing route) or remove the duplicate button entirely
so users are not confused.

In `@src/components/layout/Footer.tsx`:
- Around line 22-36: The two Link elements in Footer.tsx render "All Products"
and "Categories" but both use href="/products"; update the href on the Link that
renders the "Categories" text to a distinct destination (for example change the
Link with children "Categories" to href="/categories" or
href="/products?filter=categories") so the Link component with inner text
"Categories" no longer points to the same URL as the Link component with inner
text "All Products".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4cdfc6e2-37d6-468c-99cf-dde73fc75d46

📥 Commits

Reviewing files that changed from the base of the PR and between d983295 and ebc4975.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • package.json
  • src/app/[country]/[locale]/(storefront)/c/[...permalink]/CategoryProductsContent.tsx
  • src/app/[country]/[locale]/(storefront)/c/[...permalink]/loading.tsx
  • src/app/[country]/[locale]/(storefront)/c/[...permalink]/page.tsx
  • src/app/[country]/[locale]/(storefront)/layout.tsx
  • src/app/[country]/[locale]/(storefront)/page.tsx
  • src/app/[country]/[locale]/(storefront)/taxonomies/page.tsx
  • src/app/[country]/[locale]/layout.tsx
  • src/components/layout/Footer.tsx
  • src/components/layout/Header.tsx
  • src/components/navigation/Breadcrumbs.tsx
  • src/components/products/ProductCarousel.tsx
  • src/contexts/StoreContext.tsx
  • src/hooks/useCarouselProducts.ts
  • src/lib/analytics/gtm.ts
  • src/lib/data/categories.ts
  • src/lib/data/index.ts
  • src/lib/data/products.ts
  • src/lib/data/taxonomies.ts
💤 Files with no reviewable changes (3)
  • src/app/[country]/[locale]/(storefront)/taxonomies/page.tsx
  • src/lib/data/products.ts
  • src/lib/data/taxonomies.ts

Comment thread src/app/[country]/[locale]/(storefront)/c/[...permalink]/page.tsx
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/app/[country]/[locale]/(storefront)/c/[...permalink]/page.tsx (1)

18-84: ⚠️ Potential issue | 🟠 Major

Add generateMetadata function to generate category-specific SEO metadata.

This page has dynamic route parameters and fetches category data with name and description, but does not export generateMetadata. Category pages lack SEO/social preview metadata and fall back to generic defaults. The category's name, description, and image should be used to generate appropriate title, description, and OG tags for search engines and social sharing.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`[country]/[locale]/(storefront)/c/[...permalink]/page.tsx around
lines 18 - 84, Add an exported async generateMetadata function that mirrors
CategoryPage's params handling (use the same params -> country, locale,
permalink -> fullPermalink and basePath), call getCategory(fullPermalink, {
expand: ["ancestors","children"] }) to fetch the category, and return a metadata
object using category.name for title, category.description for description, and
include openGraph (og:title, og:description, og:image using category.image_url),
twitter card info, and a canonical URL built from basePath + "/c/" +
fullPermalink; handle fetch errors or missing category by returning sensible
fallback metadata (or call notFound()) to avoid breaking the page.
🧹 Nitpick comments (1)
src/app/[country]/[locale]/(storefront)/c/[...permalink]/page.tsx (1)

18-25: Tighten the TypeScript surface here.

let category; weakens the main render path to an implicit loose type, and CategoryPage still has no explicit return type. Please give category a concrete type and declare the component return type explicitly. As per coding guidelines: **/*.ts{,x}: Use strict TypeScript type checking; define explicit return types for functions and avoid 'any' type.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`[country]/[locale]/(storefront)/c/[...permalink]/page.tsx around
lines 18 - 25, The function and local variable lack explicit TypeScript types;
update the component signature and the category variable: change CategoryPage to
declare an explicit async return type (e.g., export default async function
CategoryPage({ params }: CategoryPageProps): Promise<JSX.Element>) and give
category a concrete type (for example let category: Category | null = null or
const category: Category = await getCategory(...) if getCategory always returns
a Category). Import the appropriate Category (or equivalent) type used by
getCategory and adjust null/undefined handling in the render path to satisfy the
stricter type (use runtime checks or throw if missing).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/`[country]/[locale]/(storefront)/c/[...permalink]/page.tsx:
- Around line 24-30: The catch currently maps every getCategory(fullPermalink,
...) failure to notFound(), causing transient/network errors to show a 404;
change the catch to inspect the thrown error (e.g., if error is a Response with
error.status === 404 or an API error object with status === 404) and call
notFound() only in that case, otherwise rethrow the error so upstream/error
boundaries can handle retries/logging; update the catch around getCategory to
perform this conditional check and rethrow non-404 errors.

---

Outside diff comments:
In `@src/app/`[country]/[locale]/(storefront)/c/[...permalink]/page.tsx:
- Around line 18-84: Add an exported async generateMetadata function that
mirrors CategoryPage's params handling (use the same params -> country, locale,
permalink -> fullPermalink and basePath), call getCategory(fullPermalink, {
expand: ["ancestors","children"] }) to fetch the category, and return a metadata
object using category.name for title, category.description for description, and
include openGraph (og:title, og:description, og:image using category.image_url),
twitter card info, and a canonical URL built from basePath + "/c/" +
fullPermalink; handle fetch errors or missing category by returning sensible
fallback metadata (or call notFound()) to avoid breaking the page.

---

Nitpick comments:
In `@src/app/`[country]/[locale]/(storefront)/c/[...permalink]/page.tsx:
- Around line 18-25: The function and local variable lack explicit TypeScript
types; update the component signature and the category variable: change
CategoryPage to declare an explicit async return type (e.g., export default
async function CategoryPage({ params }: CategoryPageProps):
Promise<JSX.Element>) and give category a concrete type (for example let
category: Category | null = null or const category: Category = await
getCategory(...) if getCategory always returns a Category). Import the
appropriate Category (or equivalent) type used by getCategory and adjust
null/undefined handling in the render path to satisfy the stricter type (use
runtime checks or throw if missing).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5773efa4-34a8-4ced-85da-a64f086f4d12

📥 Commits

Reviewing files that changed from the base of the PR and between ebc4975 and b92d40c.

📒 Files selected for processing (1)
  • src/app/[country]/[locale]/(storefront)/c/[...permalink]/page.tsx

Comment on lines 24 to 30
try {
taxon = await getTaxon(fullPermalink, {
category = await getCategory(fullPermalink, {
expand: ["ancestors", "children"],
});
} catch (error) {
console.error("Failed to fetch taxon:", error);
console.error("Failed to fetch category:", error);
notFound();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, read the complete page.tsx file to see full context
cat -n src/app/[country]/[locale]/\(storefront\)/c/\[..\.permalink\]/page.tsx

Repository: spree/storefront

Length of output: 3169


🏁 Script executed:

# Search for the getCategory function definition
rg -A 20 "export\s+(?:async\s+)?function\s+getCategory|const\s+getCategory\s*=" --type ts --type tsx

Repository: spree/storefront

Length of output: 87


🏁 Script executed:

# Check for error types or status codes used in error handling
rg "notFound\(\)" -B 5 -A 2 --type ts --type tsx | head -50

Repository: spree/storefront

Length of output: 87


🏁 Script executed:

# Search for getCategory in the categories data file
find . -name "categories.ts" -o -name "categories.tsx" | head -5

Repository: spree/storefront

Length of output: 88


🏁 Script executed:

# Try to find getCategory with rg without file type specification
rg "getCategory" -A 15 | head -80

Repository: spree/storefront

Length of output: 6515


🏁 Script executed:

# Look for Spree API error handling patterns in the codebase
rg "catch.*error" -A 3 -B 1 | grep -A 3 "notFound" | head -50

Repository: spree/storefront

Length of output: 331


🏁 Script executed:

# Read the full categories.ts file
cat -n src/lib/data/categories.ts

Repository: spree/storefront

Length of output: 833


🏁 Script executed:

# Search for other error handling patterns with status codes
rg "status|statusCode|404|notFound" -B 3 -A 3 | head -100

Repository: spree/storefront

Length of output: 5989


🏁 Script executed:

# Look for HTTP error handling or Spree SDK imports to understand error structure
rg "@spree|HttpError|ApiError" -B 2 -A 2 | head -80

Repository: spree/storefront

Length of output: 3785


🏁 Script executed:

# Search for how Spree SDK errors are handled in the codebase
rg "error\s*as\s*\w+|error\s*:\s*\w+|error\.\w+" -B 2 -A 2 | head -60

Repository: spree/storefront

Length of output: 3120


🏁 Script executed:

# Look for any HTTP status checking in similar data fetching patterns
rg "response|status|code" -B 3 -A 3 | grep -A 3 -B 3 "getCategory\|getProduct\|get[A-Z]" | head -80

Repository: spree/storefront

Length of output: 4863


🏁 Script executed:

# Check if there are examples of conditional error handling in the codebase
rg "throw|Error|catch" -B 2 -A 3 | grep -A 5 "if\|status\|code" | head -80

Repository: spree/storefront

Length of output: 4912


🏁 Script executed:

# Check if Spree SDK provides error types or status codes
rg "error\.status|error\.code|error\.response|HttpError|ApiError" -B 2 -A 2 | head -80

Repository: spree/storefront

Length of output: 42


🏁 Script executed:

# Look at the withFallback utility to see how errors are handled there
rg -A 15 "export.*withFallback|function withFallback" src/lib/data/utils.ts

Repository: spree/storefront

Length of output: 257


🏁 Script executed:

# Check other data fetching pages to see error handling patterns
fd "page.tsx" src/app | xargs rg -l "catch.*error" | head -5

Repository: spree/storefront

Length of output: 125


🏁 Script executed:

# Search for Spree SDK documentation or error handling in package.json or README
cat package.json | grep -A 5 -B 5 "@spree"

Repository: spree/storefront

Length of output: 412


🏁 Script executed:

# Look for any error handling examples with status or type checking in other files
rg "catch.*error|error.*status|error.*message" -B 3 -A 5 src/lib/data/ | head -100

Repository: spree/storefront

Length of output: 1115


🏁 Script executed:

# Check if there's a products page that handles errors differently for comparison
cat -n src/app/\[country\]/\[locale\]/\(storefront\)/products/\[slug\]/page.tsx 2>/dev/null | head -50

Repository: spree/storefront

Length of output: 593


🏁 Script executed:

# Check if there are any tests that show how getCategory errors are expected to be handled
find . -name "*.test.ts" -o -name "*.test.tsx" | xargs rg "getCategory" -B 3 -A 5 2>/dev/null | head -80

Repository: spree/storefront

Length of output: 42


🏁 Script executed:

# Look for any middleware or error boundary that handles API errors
rg "error\.status|response\.status|404|notFound" -B 3 -A 3 | grep -v node_modules | head -100

Repository: spree/storefront

Length of output: 3066


🏁 Script executed:

# Check if there's documentation on Spree error handling in comments or docs
find . -name "*.md" -o -name "*.tsx" -o -name "*.ts" | xargs rg "Spree.*error|SDK.*error|notFound.*404" 2>/dev/null | head -50

Repository: spree/storefront

Length of output: 42


🏁 Script executed:

# Check the actual Spree SDK behavior - look for how getCategory behaves with non-existent categories
rg "response\.data|response\.success|null|undefined" src/lib/data/categories.ts -B 3 -A 3

Repository: spree/storefront

Length of output: 42


🏁 Script executed:

# Look at Spree/Next documentation or types to understand error structure
find . -name "*.d.ts" | xargs grep -l "getCategory" 2>/dev/null | head -3

Repository: spree/storefront

Length of output: 42


🏁 Script executed:

# Check if getCategory might return null/undefined instead of throwing
rg "getCategory" -B 5 -A 15 src/ --type ts --type tsx | grep -A 10 "return\|null\|undefined" | head -50

Repository: spree/storefront

Length of output: 87


🏁 Script executed:

# Check how the Spree SDK might indicate "not found" - look for response structure
rg "\.data|\.success|\.errors" src/lib/data/ -B 2 -A 2 | head -60

Repository: spree/storefront

Length of output: 643


🏁 Script executed:

# Search for any network/API error handling patterns to understand error types
rg "throw|Error\(" src/lib/data/ -B 3 -A 3 | head -80

Repository: spree/storefront

Length of output: 4899


🏁 Script executed:

# Look at the full ProductDetailsWrapper to understand how it handles getProduct errors
cat -n src/app/\[country\]/\[locale\]/\(storefront\)/products/\[slug\]/ProductDetailsWrapper.tsx

Repository: spree/storefront

Length of output: 3124


🏁 Script executed:

# Check if there's any distinction in how Spree SDK errors are handled elsewhere
rg "getProduct|listProducts" -A 8 src/lib/data/products.ts

Repository: spree/storefront

Length of output: 571


🏁 Script executed:

# Look for any error inspection patterns with instanceof or type checking
rg "instanceof|error\.type|error\.code|error\.name" src/ -B 2 -A 2 | head -80

Repository: spree/storefront

Length of output: 670


🏁 Script executed:

# Check what happens when getCategory/getProduct return null or empty
rg "category|product" src/app/\[country\]/\[locale\]/\(storefront\)/c/\[..\.permalink\]/page.tsx -B 2 -A 2 | head -40

Repository: spree/storefront

Length of output: 1255


🏁 Script executed:

# Check if there's any way to distinguish error types in Spree SDK
rg "HttpError|NotFoundError|error\.response|error\.status" -B 2 -A 2

Repository: spree/storefront

Length of output: 42


🏁 Script executed:

# Look for any comments or documentation about error handling
rg "error|exception|404" src/lib/data/categories.ts -B 3 -A 3

Repository: spree/storefront

Length of output: 42


🏁 Script executed:

# Check if there are any integration tests showing expected behavior
find . -name "*.test.ts" -o -name "*.spec.ts" | xargs cat 2>/dev/null | grep -A 20 "getCategory\|notFound" | head -80

Repository: spree/storefront

Length of output: 42


Distinguish real "not found" from transient errors in the catch block.

This catch block turns every getCategory() failure into notFound(), so a transient API/network error will render as a false 404 page. Only map actual "category not found" (404) responses to notFound() and rethrow other errors.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`[country]/[locale]/(storefront)/c/[...permalink]/page.tsx around
lines 24 - 30, The catch currently maps every getCategory(fullPermalink, ...)
failure to notFound(), causing transient/network errors to show a 404; change
the catch to inspect the thrown error (e.g., if error is a Response with
error.status === 404 or an API error object with status === 404) and call
notFound() only in that case, otherwise rethrow the error so upstream/error
boundaries can handle retries/logging; update the catch around getCategory to
perform this conditional check and rethrow non-404 errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant