From a6a92f75eaf094a5848df04c6a0e40ac93f914e8 Mon Sep 17 00:00:00 2001 From: Cristian Felipe Cruz Buitron Date: Thu, 13 Aug 2026 01:59:44 -0500 Subject: [PATCH] fix(ecommerce): render product detail dynamically instead of stale SSG+ISR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Product detail pages were generateStaticParams'd at Docker build time, where MEDUSA_* env vars aren't set, so the static snapshot baked in the mock catalog (price: null for all products). With revalidate=60 and no shared ISR cache handler across the 2 frontend replicas, each pod healed its own cache independently on next visit past staleness — so a product could show "Consultar precio" on one pod and the real price on the other, while the fully-dynamic catalog listing always hit Medusa fresh. Verified against the live Medusa API that pricing/region data itself was correct for the reported failing products. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01DXqBoNfYQNwFg65mbx2FWM --- .../ecommerce/app/product/[slug]/page.tsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/workloads/ecommerce/app/product/[slug]/page.tsx b/workloads/ecommerce/app/product/[slug]/page.tsx index facb724..742569b 100644 --- a/workloads/ecommerce/app/product/[slug]/page.tsx +++ b/workloads/ecommerce/app/product/[slug]/page.tsx @@ -9,17 +9,17 @@ import { getProductBySlug, getProducts } from "@/lib/headless/client"; interface ProductPageProps { params: Promise<{ slug: string }> } -// Sin esto, la página queda estática para siempre con los datos del build -// (que usa el catálogo mock porque HEADLESS_PROVIDER/MEDUSA_* no existen en -// el contexto del Docker build). El listado sí se refresca porque su ruta -// es dinámica por searchParams; esta ruta necesita el revalidate explícito -// para que el runtime (que sí tiene las env vars de Medusa) la regenere. -export const revalidate = 60; - -export async function generateStaticParams() { - const products = await getProducts(); - return products.map((product) => ({ slug: product.slug })); -} +// generateStaticParams + revalidate quedaban aquí para pre-renderizar en +// build time, pero HEADLESS_PROVIDER/MEDUSA_* no existen en el contexto del +// Docker build: el snapshot estático quedaba congelado con el catálogo mock +// (todos los productos con price: null) hasta que ISR lo revalidara. Con +// frontend-deploy corriendo 2 réplicas y sin cacheHandler compartido, cada +// pod revalida su propia caché de forma independiente, así que un producto +// podía mostrar "Consultar precio" en un pod y el precio real en el otro +// según cuál hubiera sido "calentado". force-dynamic elimina esa caché por +// pod y deja esta ruta en vivo contra Medusa, igual que el listado +// (dinámico por searchParams). +export const dynamic = "force-dynamic"; export async function generateMetadata({ params }: ProductPageProps): Promise { const { slug } = await params; -- 2.54.0