← All case studies

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

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

Full Stack · MedusaJS · NextJS · TypeScript · PostgreSQL · MercadoPago · Headless Commerce · Migración · SEO

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

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

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.

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

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) 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.

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

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).

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

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

Compra Linda on a phone: three moments of the same page

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.

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

More case studies