# Compra Linda — WooCommerce to Headless Migration (Medusa + Next.js)

> WooCommerce migration to its own headless ecommerce, without losing catalog, customers or SEO

- Human version: https://www.augustosalazar.com.ar/project/compra-linda-migraci-n-de-woocommerce-a-headless-medusa-next-js
- Author: Augusto Salazar — https://www.augustosalazar.com.ar/llms.txt
- Tags: Full Stack, MedusaJS, NextJS, TypeScript, PostgreSQL, MercadoPago, Headless Commerce, Migración, SEO

## The brief

A store running on WordPress + WooCommerce + the WoodMart theme. Hosting was getting expensive, the architecture was hard to maintain and every customization was a fight with the CMS. The goal was not to "build a new store": it was to migrate the one that already existed — its catalog, its customers and its Google rankings — to a headless platform of its own, without breaking anything along the way.

**My role:** Full Stack, AI/UI Engineer  
**Scope:** Desktop, mobile responsive  
**Context:** Migration from WordPress to an end-to-end custom platform  
**Tech stack:** Next.js + MedusaJS + Railway + Sentry + Supabase + Vercel  
**URL:** [compralinda.com.ar](https://compralinda.com.ar)

**Caption:** The starting point (WordPress + WooCommerce + WoodMart) and the destination: a custom-built Next.js storefront.

## Architectural decisions

Every decision aimed at the same thing: separating responsibilities and never again being tied to a CMS.

**Truly headless: backend and storefront decoupled.** Medusa.js v2 (Node + TypeScript + Postgres) runs on Railway with Docker and exposes the API and the admin. The storefront is a standalone Next.js 15 app (App Router, React 19) on Vercel. Each layer is deployed, scaled and reasoned about separately.

**Custom modules for Argentina.** Medusa doesn't ship with MercadoPago or Correo Argentino out of the box, so I built them as custom modules: a MercadoPago payment provider (with its confirmation webhook) and a Correo Argentino fulfillment provider that calculates real shipping rates. I also added bank transfer payments with a discount and an in-house reviews module.

**Rating denormalized into product metadata.** Instead of computing the review average with joins on every listing, a job syncs the rating into the product's metadata. Listings stay cheap to render and the stars show up without N+1 queries.

**Home page content managed from the admin.** Hero slides, featured products (as a collection), best-sellers (custom endpoint), the popup and the flash sale are all configurable from the panel, without touching code. The client edits their own store; I'm not a bottleneck.

![](https://www.augustosalazar.com.ar/images/compralinda-producto.jpg)

**Caption:** Product page on the Next.js storefront: sticky gallery, reviews with ratings and structured data for Google rich results.

![Headless architecture: Next.js storefront on Vercel and Medusa v2 on Railway, with custom modules](https://www.augustosalazar.com.ar/images/compralinda-arquitectura-en.png)

**Caption:** Storefront and backend decoupled, with the modules Argentina needed built in-house.

## Shipping it to production

Migrating a live store is where the project gets serious. These were the hard parts:

**1\. Migrating the catalog from WooCommerce without losing the images.** I wrote a script that pulls products and categories from the WooCommerce REST API and recreates them in Medusa, mapping slugs 1:1. The treacherous detail: after the first pass, the images were still pointing to the old WordPress CDN. The second pass downloads them and re-uploads them to our own storage (Cloudflare R2), so we wouldn't stay tied to a server we were about to shut down.

**2\. Preserving SEO through the domain cutover.** The new site had to take over the same domain ([compralinda.com.ar](https://compralinda.com.ar)) that was serving the WordPress site. Google had hundreds of old URLs indexed (`/producto/*`, `/categoria-producto/*`). I generated 112 pattern-based 301 redirects plus an exceptions map, lowered the DNS TTL to 300s days in advance, and choreographed the switch: DNS → SSL first, then the env var flip on the storefront and the backend. With a documented rollback, just in case.

**3\. Running seeds and migrations against production, carefully.** I ran the data migrations against the production database through a public proxy, and the image uploads to R2 via `railway run` (so the network egress happened from inside the infrastructure, not from my machine). Everything idempotent, with cleanup scripts for ghost products and legacy subcategories.

**4\. Migrating existing customers.** Customers from the old Woo store were imported into Medusa with a dedicated script, coordinated with a heads-up email and a password reset link so they could get into the new site without friction.

**5\. Payment confirmation that doesn't get lost.** MercadoPago confirms via webhook, not via the user's redirect (which can be cut off). The webhook sets the order's real status; the back\_urls and the links in the emails derive from a single env var (`STOREFRONT_URL`), so they pointed to the right domain on their own at cutover.

![](https://www.augustosalazar.com.ar/images/compralinda-checkout.jpg)

**Caption:** Multi-step checkout with MercadoPago and discounted bank transfer. The order is confirmed by webhook, not by the redirect.

![Cutover steps: catalog, images, customers, 112 redirects, TTL, DNS, env vars and rollback](https://www.augustosalazar.com.ar/images/compralinda-cutover-en.png)

**Caption:** The cutover order: everything that could be prepared ahead, ahead; on day D, four steps and a written rollback.

## Craft details

-   **A single source of truth for dynamic content:** hero-slides, home-settings, payment-settings, popup and flash-sale live in the backend and are edited from the admin.
-   **On-demand revalidation:** a subscriber revalidates the storefront when a product changes, so the static catalog stays fresh without a manual rebuild.
-   **Operational crons:** abandoned cart recovery and automatic expiration of unpaid transfers, running as backend jobs.
-   **Transactional emails with Resend:** welcome, order confirmed, order shipped, password reset and review request — each with its own subscriber.
-   **Self-healing thumbnails:** a subscriber detects and repairs broken thumbnails inherited from the migration.
-   **Consent-gated analytics:** GA4 with ecommerce events (`view_item`, `add_to_cart`, `begin_checkout`, `purchase`) that only load after the cookie banner is accepted (Argentine Law 25.326).

![](https://www.augustosalazar.com.ar/images/compralinda-admin.jpg)

**Caption:** The Medusa admin extended with custom widgets: home management, pending transfers, review moderation and maintenance mode.

## Key features

**Storefront:** configurable home (hero, featured, best-sellers) · PDP with sticky gallery + reviews · multi-step checkout · MercadoPago + discounted bank transfer · account area with "buy again" · newsletter · popup · abandoned cart recovery · cookie banner.

**Admin:** hero slide management · home and payment settings · review moderation · pending transfers · abandoned cart stats · flash sale · maintenance mode.

**Migration/SEO:** catalog and customer import from WooCommerce · 112 permanent (301) redirects · dynamic sitemap + robots · structured data (Product + BreadcrumbList).

![The full Compra Linda landing page, top to bottom in three columns](https://www.augustosalazar.com.ar/images/compralinda-landing.jpg)

**Caption:** The full landing page, top to bottom: read it left to right.

![Compra Linda on a phone: three moments of the same page](https://www.augustosalazar.com.ar/images/compralinda-mobile.jpg)

**Caption:** The same page on a phone, built for the thumb.

## Results

-   Catalog and customers migrated from WooCommerce to a headless platform of their own.
-   SEO preserved through the cutover with 112 old → new 301 redirects, on the same domain.
-   Infrastructure cost stabilized at ~USD 15–25/month (Vercel + Railway + Resend free tier), down from the previous WordPress hosting.
-   Real payments with MercadoPago + bank transfer, confirmed by webhook.
-   GA4 with ecommerce events, gated by consent.
-   Maintainable architecture: the client edits their store from the admin without depending on me.

![](https://www.augustosalazar.com.ar/images/compralinda-lighthouse.jpg)

**Caption:** Lighthouse metrics after multiple rounds of refinement across the whole platform, improving every score: performance, best practices, SEO and accessibility.
