Vigencia parcial — verificada el 2026-08-19
Plan preexistente migrado al estándar. Verificación puntual contra el código de la
rama develop: el paso 1 (variable NEXT_PUBLIC_ALGOLIA_API_KEY en
src/lib/search-client.ts) y el paso 3 (home restringida a py/ar/br)
siguen pendientes. El resto de los pasos no fue verificado.
Plan de Resolución de Problemas - Navegación y Algolia¶
Este documento presenta un plan paso a paso para resolver los problemas identificados en la integración con Algolia y el sistema de navegación.
Resumen de Problemas por Prioridad¶
| # | Prioridad | Problema | Impacto |
|---|---|---|---|
| 1 | CRÍTICO | Variable de entorno incorrecta en search-client.ts |
App crash en búsqueda |
| 2 | CRÍTICO | SearchBar no incluye countryCode |
Pérdida de contexto regional |
| 3 | MEDIA | Homepage restringida a py/ar/br | 404 para otras regiones |
| 4 | MEDIA | InstantSearch routing deshabilitado | URL no sincroniza con filtros |
| 5 | BAJA | Clientes Algolia duplicados | Mantenibilidad |
| 6 | BAJA | Índice Algolia hardcodeado | Mantenibilidad |
Paso 1: Corregir Variable de Entorno (CRÍTICO)¶
Archivo a Modificar¶
src/lib/search-client.ts
Problema Actual¶
const searchClient = liteClient(
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
process.env.NEXT_PUBLIC_ALGOLIA_API_KEY! // ❌ No existe
)
Solución¶
const searchClient = liteClient(
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY! // ✅ Variable correcta
)
Verificación¶
- Buscar otros usos de
NEXT_PUBLIC_ALGOLIA_API_KEYen el proyecto - Confirmar que
.env.localtieneNEXT_PUBLIC_ALGOLIA_SEARCH_KEY
Paso 2: Agregar Country Code al SearchBar (CRÍTICO)¶
Archivo a Modificar¶
src/modules/search/component/SearchBar.tsx
Cambios Requeridos¶
2.1 Importar hook useParams¶
import { useParams, useRouter } from "next/navigation"
2.2 Obtener countryCode en el componente¶
export default function SearchBar({ className }: SearchBarProps) {
const { countryCode } = useParams<{ countryCode: string }>()
const router = useRouter()
// ...
}
2.3 Actualizar todas las navegaciones¶
onSubmit (búsqueda con Enter):
// Antes
router.push(`/store?q=${state.query}`)
// Después
router.push(`/${countryCode}/store?q=${encodeURIComponent(state.query)}`)
onSelect en querySuggestionsSource:
// Antes
router.push(`/store?q=${item.query}`)
// Después
router.push(`/${countryCode}/store?q=${encodeURIComponent(item.query)}`)
onSelect en categorySuggestionsSource:
// Antes
router.push(`/store?category=${item.value}`)
// Después
router.push(`/${countryCode}/store?category=${encodeURIComponent(item.value)}`)
onSelect en products:
// Antes
router.push(`/products${item.url}`) o router.push(`/products/${sku}`)
// Después
router.push(`/${countryCode}/products${item.url}`)
// o
router.push(`/${countryCode}/products/${sku}`)
Botón Clear/Limpiar:
// Antes
router.push(`/store`)
// Después
router.push(`/${countryCode}/store`)
Verificación¶
- Probar búsqueda desde diferentes regiones (/py/, /ar/, /br/)
- Verificar que la URL mantiene el countryCode después de buscar
- Probar click en sugerencias, categorías y productos
Paso 3: Resolver Restricción de Homepage (MEDIA)¶
Archivo a Modificar¶
src/app/[countryCode]/(main)/page.tsx
Opciones de Solución¶
Opción A: Permitir todos los países de Medusa (Recomendada)¶
import { listRegions } from "@lib/data/regions"
export default async function Home({ params }: Props) {
const { countryCode } = await params
// Validar contra regiones de Medusa
const regions = await listRegions()
const validCodes = regions.flatMap(r =>
r.countries?.map(c => c.iso_2.toLowerCase()) || []
)
if (!validCodes.includes(countryCode.toLowerCase())) {
notFound()
}
// ... resto del componente
}
Opción B: Redirigir a región default¶
import { redirect } from "next/navigation"
const ALLOWED = ["py", "ar", "br"] as const
const DEFAULT_REGION = "py"
export default async function Home({ params }: Props) {
const { countryCode } = await params
if (!ALLOWED.includes(countryCode as any)) {
redirect(`/${DEFAULT_REGION}`)
}
// ... resto del componente
}
Opción C: Mostrar página de región no disponible¶
export default async function Home({ params }: Props) {
const { countryCode } = await params
if (!ALLOWED.includes(countryCode as any)) {
return <RegionNotAvailable countryCode={countryCode} />
}
// ... resto del componente
}
Decisión Requerida¶
Confirmar cuál de las tres opciones implementar según la estrategia de negocio.
Paso 4: Habilitar InstantSearch Routing (MEDIA)¶
Archivo a Modificar¶
src/modules/store/templates/instantsearch-store-template.tsx
Cambio Requerido¶
import { history } from "instantsearch.js/es/lib/routers"
export default function InstantSearchStoreTemplate({
initialFilters,
countryCode
}: Props) {
return (
<InstantSearchNext
searchClient={searchClient}
indexName={ALGOLIA_INDEX}
routing={{
router: history({
cleanUrlOnDispose: false,
getLocation: () =>
typeof window === "undefined"
? new URL(`https://localhost/${countryCode}/store`) as unknown as Location
: window.location,
}),
stateMapping: {
stateToRoute(uiState) {
const indexUiState = uiState[ALGOLIA_INDEX] || {}
return {
q: indexUiState.query,
category: indexUiState.refinementList?.category?.join(","),
brand: indexUiState.refinementList?.brand?.join(","),
product_tag: indexUiState.refinementList?.product_tags?.join(","),
price_min: indexUiState.range?.price?.min,
price_max: indexUiState.range?.price?.max,
}
},
routeToState(routeState) {
return {
[ALGOLIA_INDEX]: {
query: routeState.q,
refinementList: {
category: routeState.category?.split(","),
brand: routeState.brand?.split(","),
product_tags: routeState.product_tag?.split(","),
},
range: {
price: {
min: routeState.price_min,
max: routeState.price_max,
},
},
},
}
},
},
}}
>
<Configure filters="total_stock > 0" />
<InstantSearchContent />
</InstantSearchNext>
)
}
Archivos Adicionales a Modificar¶
src/modules/store/components/instantsearch-content/index.tsx- Remover o simplificar componente
ApplyFiltersFromURL - El routing nativo de InstantSearch manejará la sincronización
Verificación¶
- Verificar que cambiar filtros actualiza la URL
- Verificar que compartir URL con filtros funciona
- Verificar que el botón "atrás" del navegador funciona correctamente
Paso 5: Consolidar Clientes Algolia (BAJA)¶
Archivos a Crear/Modificar¶
5.1 Crear estructura unificada¶
src/lib/algolia/
├── index.ts # Re-exports
├── client.ts # Cliente client-side (lite)
├── server.ts # Cliente server-side (full)
└── constants.ts # Constantes compartidas
5.2 constants.ts¶
export const ALGOLIA_APP_ID = process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!
export const ALGOLIA_SEARCH_KEY = process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY!
export const ALGOLIA_ADMIN_KEY = process.env.ALGOLIA_ADMIN_API_KEY!
export const ALGOLIA_PRODUCT_INDEX = process.env.NEXT_PUBLIC_ALGOLIA_PRODUCT_INDEX!
export const ALGOLIA_SUGGESTIONS_INDEX = process.env.NEXT_PUBLIC_ALGOLIA_SUGGESTIONS_INDEX!
5.3 client.ts¶
"use client"
import { liteClient as algoliasearch } from "algoliasearch/lite"
import { ALGOLIA_APP_ID, ALGOLIA_SEARCH_KEY } from "./constants"
export const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_SEARCH_KEY)
5.4 server.ts¶
import "server-only"
import algoliasearch from "algoliasearch"
import { ALGOLIA_APP_ID, ALGOLIA_SEARCH_KEY } from "./constants"
export const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_SEARCH_KEY)
5.5 index.ts¶
export * from "./constants"
Archivos a Actualizar¶
src/lib/algolia.ts→ Eliminar, usarsrc/lib/algolia/server.tssrc/lib/search-client.ts→ Eliminar, usarsrc/lib/algolia/client.tssrc/modules/store/templates/instantsearch-store-template.tsx→ Importar de@lib/algolia/clientsrc/modules/search/component/SearchBar.tsx→ Importar de@lib/algoliasrc/lib/algolia-products.ts→ Importar de@lib/algolia/server
Paso 6: Usar Constantes para Índices (BAJA)¶
Archivos a Modificar¶
Buscar y reemplazar todas las instancias hardcodeadas:
// Antes
indexName="product_items_view_index_dev"
// Después
import { ALGOLIA_PRODUCT_INDEX } from "@lib/algolia"
indexName={ALGOLIA_PRODUCT_INDEX}
Archivos Afectados¶
src/modules/store/templates/instantsearch-store-template.tsxsrc/lib/parse-search-params.tssrc/lib/algolia-products.ts(múltiples lugares)
Orden de Implementación Sugerido¶
Fase 1: Correcciones Críticas (Inmediato)
├── Paso 1: Variable de entorno (5 min)
└── Paso 2: Country code en SearchBar (30 min)
Fase 2: Mejoras Funcionales (Corto plazo)
├── Paso 3: Homepage restriction (15 min)
└── Paso 4: InstantSearch routing (1-2 horas)
Fase 3: Refactoring (Cuando haya tiempo)
├── Paso 5: Consolidar clientes (1 hora)
└── Paso 6: Constantes para índices (30 min)
Checklist de Verificación Final¶
Después de Fase 1¶
- [ ] Búsqueda funciona sin errores de consola
- [ ] SearchBar navega correctamente con countryCode
- [ ] Usuarios mantienen su región al buscar
- [ ] Click en productos lleva a URL correcta
Después de Fase 2¶
- [ ] Homepage funciona para todas las regiones configuradas
- [ ] Filtros de InstantSearch se reflejan en URL
- [ ] URL compartidas con filtros funcionan
- [ ] Botón atrás del navegador funciona correctamente
Después de Fase 3¶
- [ ] No hay imports de archivos eliminados
- [ ] Build pasa sin errores
- [ ] Tests de búsqueda pasan
- [ ] No hay warnings de variables de entorno
Notas Adicionales¶
Dependencias entre pasos¶
- Paso 5 debe completarse antes de Paso 6
- Pasos 1-4 son independientes entre sí
Riesgos¶
- Paso 4: Cambiar el routing de InstantSearch puede requerir ajustes adicionales en componentes que dependen del estado actual
- Paso 5: Refactoring de imports puede causar errores temporales si no se actualiza todo
Testing Recomendado¶
- Probar flujo de búsqueda completo en cada región
- Probar navegación desde diferentes puntos de entrada
- Verificar que SEO/URLs canónicas siguen correctas