Andrea redesign 1: baseline and route contract¶
Historical Step 1 record. The route spike below has been retired; current local Compose uses the deployed routes without an overlay. Start with the redesign story and local operations.
Date: 2026-09-24 (America/Bogota). Branch: jm/andrea-redesign-1.
This is the code and local-runtime baseline for Step 1 of
andrea-redesign-1.md. It separates observed behavior,
the tested route spike, and migration work still required. The opt-in local
spike starts containers against existing local volumes but does not migrate,
reseed, or reset commerce data. No VPS, production host, remote database, or
remote API was inspected or changed.
Observed baseline¶
Checkout, runtime, and visual evidence¶
- Authoritative checkout:
/home/justin/repos/AndreaWeb, WSL Ubuntu-26.04, branchjm/andrea-redesign-1. - Docker Desktop's WSL integration was initially stopped. After starting it,
the local portfolio, storefront, Medusa, PostgreSQL, Redis, and Garage all
ran through the opt-in Compose overlay described below. The WSL
zshlogin shell loaded the local fnm Node/npm installation. - Existing local Medusa products were readable; no seed or database reset was
run. A read-only query of
product_collectionfound zero local collection rows. This says nothing about the VPS catalog; the two approved collection identities and their product assignments need a separate read-only audit before Step 4. Account behavior, verification email, and locale catalogs were not exercised here.
Screenshots were captured at 1440 × 900 on 2026-09-24 from the local services, before visual redesign. The detail screenshot reproduces the actual overlap: the first line of “Organizador Doble” extends beneath the main image.
The direct local catalog paths used for the screenshots were /co and
/co/products/organizador-doble with an empty local Next.js base path. In the
current deployed configuration, the equivalent storefront paths begin with
/cementos. The images document baseline layout, not new Guanza styling.
Applications and URLs today¶
The repository has two customer-facing apps: a Vinext/Vite portfolio and a
Next.js storefront backed by Medusa. The portfolio root re-exports its
/portfolio page; both render the Spanish portfolio. /en/portfolio has an
English portfolio route. The portfolio also serves /cementos and
/en/cementos through CementStore; these are the old simulated shop, not the
Medusa catalog.
The real storefront uses NEXT_PUBLIC_STOREFRONT_BASE_PATH, currently
/cementos in Next config, Compose, and environment templates. Its proxy reads
a country segment after stripping that base path, else choosing configured
default country co. The backend seed defines a Colombia (co) region with
COP. Thus co in current URLs is market/country selection, not language.
The storefront country-root route and /store route both render
StoreTemplate; /store additionally consumes sort, page, and option-value
filter parameters. Nginx sends /cementos and /cementos/... to the same
Next.js service. That accounts for /cementos/co and
/cementos/co/store showing the same principal catalog view.
The store wordmark links to its own root. A desktop-only portfolio link points
to /portfolio; there is no consistent shared home link or mobile cross-app
navigation. A side-menu language selector is conditionally populated by the
optional Medusa /store/locales endpoint. Locale-cookie and cart-locale update
code exists, but does not establish English availability or full translation.
/en/cementos is the separate portfolio PoC and does not use this locale
mechanism.
Catalog, collections, accounts¶
The checked-in Medusa foundation seed creates the Cementos sales channel,
publishable key, Colombia region with COP, and stock location. The starter
catalog seed defines four demo products with COP prices and stock, but does not
create collections or assign products to collections. The catalog upgrade
script only updates products marked as legacy starter data. Repository code
cannot establish whether the intended production commerce database currently
contains GUANZA or Piezas Intervenidas, nor their assignments. The local database
had zero collections at this check. Read the intended
commerce catalog through Medusa Admin/API before mapping collections; record IDs, handles,
assignments, and unknowns. Preserve IDs, inventory, media, and merchant edits.
Do not rerun seed/reset scripts to answer this.
Account code exists: email/password registration and login, customer creation/resolution, conditional email verification, cart transfer, profile, address, and order-history pages. Verification UI/action code is present too. Registration, email delivery, and login were outside this route spike and were not verified; account readiness remains unverified until a focused local audit.
Current route inventory¶
This describes code and proxy configuration, not a successful deployed request. Next.js route groups do not appear in public URLs.
| Current path/family | Current behavior and owner | Migration implication |
|---|---|---|
/, /portfolio |
Same Spanish portfolio page in portfolio app. | / becomes landing; /portfolio redirects to /arquitectura. |
/en/portfolio |
English portfolio in portfolio app. | Redirect to /en/arquitectura. |
/cementos, /en/cementos |
Simulated CementStore in portfolio app. |
Redirect to real Guanza destination in matching language. |
/cementos/co, /cementos/co/store |
Real catalog via Nginx/Next; both render StoreTemplate; /store accepts listing state. |
/guanza becomes selector; decide catalog-root fallback after auditing old links/query intent. |
/cementos/<country>/collections/<handle> |
Real Medusa collection route. | Map verified collection identity to /guanza/origenes or /guanza/piezas; define unknown behavior. |
/cementos/<country>/categories/<path...> |
Real category route. | Map only with an equivalent destination; retain supported filters/sort/page. |
/cementos/<country>/products/<handle> |
Real product details. | /guanza/productos/<handle>; retain handle and supported query state. |
/cementos/<country>/cart |
Real cart. | /guanza/carrito; retain cart identity and contents. |
/cementos/<country>/account..., /verify-account |
Account, verification, profile, address, and order routes. | If retained after verification, map to /guanza/cuenta... and localized verification route. |
/cementos/<country>/checkout, /order/... |
Checkout/order/transfer route files exist. Path presence does not establish paid-order behavior; purchasing principally hands off an inquiry. | Audit each workflow; preserve inquiry semantics, never represent inquiry as paid order. |
/api/..., /_next/..., static assets, server actions |
Next internal surfaces; matcher excludes API and static/image paths. | Inventory during routing design; page redirects must not capture POST/API requests; prevent app asset collisions. |
deploy/nginx.conf and deploy/nginx-vps.conf.example route exact
/cementos and /cementos/ to port 3100; other paths go to portfolio on
port 3000. Compose health checks and deployment templates also assume
/cementos/co. This is checked-in configuration, not live service state.
Approved destination contract¶
Spanish is unprefixed; English always has /en first. Both initially use
Colombia and COP; language does not select market. Display “Orígenes” with
ASCII route slug origenes.
| Experience | Spanish | English | Owner |
|---|---|---|---|
| Personal landing | / |
/en |
Portfolio |
| Architecture | /arquitectura |
/en/arquitectura |
Portfolio |
| Guanza selector | /guanza |
/en/guanza |
Storefront |
| Orígenes | /guanza/origenes |
/en/guanza/origenes |
Storefront |
| Piezas Intervenidas | /guanza/piezas |
/en/guanza/piezas |
Storefront |
| Product | /guanza/productos/<handle> |
/en/guanza/productos/<handle> |
Storefront |
| Cart | /guanza/carrito |
/en/guanza/carrito |
Storefront |
| Account, if exposed | /guanza/cuenta |
/en/guanza/cuenta |
Storefront |
| Journal | Existing Journal Spanish destination | Existing Journal English destination | External Journal app |
The storefront has one build-time base path and country-prefixed filesystem
routes. basePath: /guanza alone cannot also support /en/guanza. The tested
decision is one storefront build with an empty base path and application-owned
locale routes. Nginx dispatches both /guanza... and /en/guanza... to that
same Next.js service. The region remains Medusa co/COP for both languages;
co is an internal commerce parameter, not part of the new public URL. The
portfolio continues to own /, /en, and architecture paths. No second shop
instance or Nginx HTML rewriting is involved.
Tested local routing slice¶
The opt-in compose.redesign-spike.yaml and
deploy/nginx.redesign-spike.conf apply only when explicitly selected alongside
normal Compose. They do not alter the
checked-in production Nginx configuration or its /cementos routing. New
App Router entries /guanza and /en/guanza share one StoreTemplate backed
by Medusa's Colombia region. The proxy accepts these exact public roots without
redirecting to /co; existing country-prefixed routes continue to work in the
local Next.js service while deeper public paths are built in later steps.
The Next build uses an empty base path for this spike. Its static chunks get
the /guanza/_next/ public asset prefix, which local Nginx strips before
forwarding to Next. This avoids claiming the portfolio's framework assets.
The local-only /guanza/api/ location similarly forwards to the existing
Next.js BFF /api/ without claiming any portfolio API route. Media remains on
the separate Garage media host. Server actions, image optimization, metadata,
and canonical URLs need end-to-end checks as actual deeper routes are moved;
do not assume assetPrefix alone settles them.
The local media hostname resolved and returned HTTP 200 from WSL, but did not resolve from the Windows host during this check. Headless Windows screenshots of the new routes therefore showed product text with blank media tiles. This is a local preview hostname issue, not evidence of missing Medusa media; verify Windows browser hostname resolution before visual review in Step 4.
Local checks through Nginx at localhost:8080 returned HTTP 200 for /,
/portfolio, /guanza, and /en/guanza. Both Guanza responses contained the
real Medusa product “Organizador Doble.” A namespaced Next static chunk returned
200 and a GET to /guanza/api/inquiries/whatsapp returned 405 (the existing
POST-only handler), showing the request reached the BFF. The Medusa cache cookie
used Path=/ and survived a Spanish-to-English request in one browser session.
This proves route ownership and reachability, not a completed English
translation, cart/account journey, or production-ready proxy configuration.
Future public links must be generated by application-owned route builders:
locale prefix first, then /guanza/...; never let existing /co links leak
from the old LocalizedClientLink. Step 2 should define the small shared route
API before independent UI work. Keep cross-app navigation as normal anchors
where needed so Next's client router does not claim the Vinext portfolio.
Cookies for cart/auth should remain same-origin and path /; language state
must not change market or cart. Locale-aware responses and cache keys must be
separated before translated content is enabled. The two new roots currently use
dynamic rendering and identical Spanish content, so they do not yet establish
English content or final cache behavior.
From the WSL repository root, the disposable routing overlay can be reproduced
with docker compose -f compose.yaml -f compose.redesign-spike.yaml --profile
commerce up -d --build. Open http://localhost:8080/guanza and
http://localhost:8080/en/guanza. Stop it with the same file/profile arguments
and down without --volumes; that leaves existing local commerce data
intact. This overlay runs the storefront development server and is not the
production build or production Nginx template.
Legacy migration inventory to finalize¶
These are intended relationships, not existing redirects. The user's transition allowance means old routes may keep serving their current content locally until the new journey is ready; no legacy redirect is activated by Step 1. At cutover, final redirects must avoid chains/loops, retain supported query parameters, exclude POST/API requests, and leave unknown paths as a helpful 404.
| Legacy path | Intended resolution |
|---|---|
/portfolio, /en/portfolio |
/arquitectura, /en/arquitectura. |
/cementos, /en/cementos |
Real Guanza entry in corresponding language. |
/cementos/co, /cementos/co/store, country catalog roots |
Guanza selector unless a verified old link/filter identifies a collection. |
/cementos/<country>/collections/<handle> |
Read-only Medusa audit; known identities map to new collection slugs. |
/cementos/<country>/categories/<path...> |
Preserve category/filter intent only with a valid target. |
/cementos/<country>/products/<handle> |
/guanza/productos/<handle> in current language, keeping supported query state. |
/cementos/<country>/cart |
/guanza/carrito, retaining cart identity and contents. |
| Account and verification paths | Map only flows verified and retained in the journey. |
Checkout and /order/... |
Preserve or retire after audit; never imply inquiry completed a paid order. |
/en/cementos#collection |
Fragment is client-side and not sent to server; consider saved-link compatibility. |
Step 1 exit and remaining gates¶
The baseline screenshots, overlap reproduction, existing route inventory,
read-only local catalog audit, and dual-language local integration slice satisfy
the Step 1 route decision. The local overlay is deliberately not a production
cutover. Before Step 4, identify the real collection IDs, handles, and product
assignments in the intended non-production/production catalog without changing
them. Before release, finish the legacy migration table with live equivalents,
verify deep links and supported query state, eliminate /co leakage, and test
actions, BFF requests, image/asset paths, metadata/canonicals, cart/auth cookies,
locale cache isolation, and rollback against the finished journey. Production
mutation is not a shortcut for any of these checks.