Klient miał Shopify Advanced za 280 EUR / miesiąc, 12 000 SKU, 4 magazyny, B2B + B2C dual pricing, 65 % organicznego traffic ze słowackiego i czeskiego Google. Headless migracja na Medusa.js skończyła się po 4 miesiącach, dwa tygodnie przed Black Friday. Żaden organic ranking nie został stracony, żadne niedokończone zamówienie nie zostało stracone, a integracja Stripe przeszła z 14 ręcznych kroków przy każdym nowym produkcie na zero. Niniejszy artykuł jest o tym, co robiliśmy, co spartoliliśmy i co zrobilibyśmy inaczej.
Dlaczego headless — i kiedy NIE
Headless commerce ma dwa ważne powody:
- 1.Elastyczność custom checkout / B2B / multi-storefront. Shopify (zarówno Advanced, jak i Plus) ma stałą pipeline checkout. Dla B2B z terminem płatności net-60, custom pricing tiers, multi-warehouse splitting lub complex tax rules (PL-DE-AT cross-border) Shopify staje się walką z limitami API i szablonami Liquid.
- 2.Performance storefront + UX. Storefront Next.js z ISR (Incremental Static Regeneration) + edge caching osiąga LCP < 1,2 s na 4G. Shopify Liquid-rendered storefront ma LCP 2,5–4,0 s. Dla biznesu SEO-driven to mierzalna różnica w przychodach.
Kiedy NIE headless: - Katalogi < 500 SKU + standardowy checkout B2C → Shopify lub BigCommerce pozostaje tańszy i szybszy - Zespół nie ma kapacity na własny storefront Next.js (custom CMS, custom checkout, integracje) - Roadmapa płatności/księgowości/marketingu jest cała Shopify-native (Shopify Payments, Shopify Tax, Shopify Email)
Dla tych klientów płynniejszy jest istniejący „semi-headless" — Shopify Hydrogen + Oxygen, który daje frontend headless storefront bez opuszczania ekosystemu Shopify.
Stack decyzji w 2026
Backend: Medusa.js vs Saleor vs Commerce.js
Medusa.js v2.x - Node.js, PostgreSQL, Redis - Modułowy, plugin architecture - Najlepszy developer experience w 2026 - Słabszy zestaw funkcji B2B out-of-the-box (potrzebny plugin lub własny kod dla quotes, approvals, customer hierarchy) - Cena: open source self-hosted lub Medusa Cloud od 200 EUR / miesiąc - Kiedy: B2C + light B2B, zespół dev z doświadczeniem Node
Saleor - Python, Django, GraphQL-first - Najsilniejszy zestaw funkcji B2B (customer groups, channel-based pricing, quote requests) - Multilanguage + multi-currency natywnie - Wyższa learning curve, narzut GraphQL - Cena: open source self-hosted lub Saleor Cloud od 500 EUR / miesiąc - Kiedy: B2B-first, multi-storefront, complex pricing
Commerce.js / Swell.is - Hosted-only, żadnego self-host - Szybki setup, ale vendor lock-in - Kiedy: PoC / MVP, mały katalog
Dla 12 k SKU retailera słowackiego z 30 % udziałem B2B wybraliśmy Medusa.js v2 — własny hosting przez Hetzner Cloud (CCX23, 4 vCPU + 16 GB RAM, 35 EUR / miesiąc), PostgreSQL 16 na oddzielnym node, Redis dla cache + queue.
Frontend: Next.js 16 z App Router
- ISR (Incremental Static Regeneration) dla stron produktowych — revalidate every 60s
- Edge runtime dla /api routes (Cloudflare Workers lub Vercel Edge)
- Tailwind 4 + shadcn/ui dla szybkiego rozwoju UI
- Server Components dla product detail (szybki TTFB), Client Components dla cart / interactive elements
- Bundle size target: < 180 KB shipped JS dla home page
Usługi peryferyjne
| Funkcja | Wybór 2026 | Cena |
|---|---|---|
| Search | Algolia | 0,50 EUR / 1k search ops, ~180 EUR / miesiąc dla 12k SKU + 400k miesięcznych searches |
| Płatności | Stripe (Standard + Connect dla B2B) | 1,4 % + 0,25 EUR per transakcja EU, B2B Connect 0,5 % flat |
| Email / Marketing | Klaviyo | 90 EUR / miesiąc dla 10k profili |
| Observability | Sentry + PostHog | Sentry 26 EUR / miesiąc, PostHog 0 EUR (free tier do 1M events) |
| Image CDN | Cloudflare Images | 5 EUR / miesiąc + 1 EUR / 100k delivery |
| DAM (Digital Asset Management) | Cloudinary lub self-hosted Imgproxy | 90 EUR / miesiąc lub 15 EUR self-hosted |
| Tax | Avalara AvaTax (PL + EU OSS) | 250 EUR / miesiąc |
| Shipping | InPost API + DHL API | 0 EUR (consumption-based) |
| Reviews | Trustpilot Business | 200 EUR / miesiąc |
Całkowity OPEX: ~750 EUR / miesiąc (vs Shopify Advanced 280 EUR + nadmiarowe Shopify Apps 350 EUR = 630 EUR pierwotnie).
Plan migracji — 4 miesiące, 6 faz
Miesiąc 1: Audyt + przygotowanie danych
Tydzień 1–2: Audyt katalogu - Eksport Shopify product CSV + Metafields export - Mapping Shopify product schema → Medusa product schema (variants, options, prices, tax_rates) - Identyfikacja data quality issues (brakujące SEO descriptions, duplicate handles, broken images) - 12 000 SKU rozłożyło się na: 9 200 unique products × średnio 1,3 wariantu = 12 100 product_variants w Medusa
Tydzień 3: Audyt URL dla 301 mapping - Crawl wszystkich Shopify URL przez Screaming Frog → 14 800 unique URLs - Categorize: product pages (12 000), collection pages (240), CMS pages (45), pagination URLs (2 200), other (300) - Plan: zachować product handle (URL slug) → Medusa ten sam handle → 0 redirect potrzebny dla 11 800 URL - Plan: collection pages mapping → większość 1:1, ale Shopify smart collections nie mapują się na Medusa product categories bezpośrednio → 80 ręcznych mappings - Pagination URLs (?page=2) → Medusa ta sama struktura, naturalnie zachowane
Tydzień 4: Eksport klientów + zamówień - 18 400 customers z aktywnością z ostatnich 24 miesięcy → import do Medusa - 47 000 historycznych zamówień → migracja do read-only archiwum w Medusa (nie potrzebne w aktywnym systemie, ale potrzebne dla legal compliance + customer support) - B2B customer groups + pricing tiers (Bronze/Silver/Gold) → Medusa customer_group + price_list
Miesiąc 2: Build backendu + integracje
Tydzień 5–6: Setup Medusa + custom moduły - Setup Hetzner Cloud, Coolify dla Docker orchestration, GitHub Actions CI/CD - Medusa modules: product, order, customer, fulfillment, payment (Stripe), tax (Avalara plugin) - Custom moduły: - PL-specific tax handling (VAT 23 %, obniżony 8 %, 5 %, zwolnione) - PL-specific invoicing (wymaga NIP, REGON, daty wystawienia, daty dostawy, terminu płatności) - B2B quote request flow (custom Medusa workflow + admin UI)
Tydzień 7–8: Integracje peryferyjne - Algolia: products + variants index, faceting (kategoria, cena, marka, dostępność), synonyms (PL + CZ) - Klaviyo: customer + order webhook → Klaviyo events (cart_abandoned, ordered_product, etc.) - Avalara: order_placed webhook → AvaTax calculation → store tax breakdown na order - Sentry: backend + frontend error tracking, source maps upload
Miesiąc 3: Build frontend + ciągłość SEO
Tydzień 9–10: Storefront core pages - Setup Next.js 16, Tailwind 4, shadcn/ui - Home, Category, Product Detail, Cart, Checkout (multi-step), Account, Order History - ISR dla Product + Category (revalidate 60s) - Server Components default, Client Components tylko dla cart/wishlist state
Tydzień 11: Migracja SEO - Sitemap continuity: Next.js sitemap.xml generuje te same URL co Shopify, plus nowe URL, jeśli powstały - 301 redirect map: /apps/customer-portal/* → /account/*, /collections/ → /c/* (zmieniliśmy strukturę url kategorii) - Structured data: Product schema (price, availability, sku, brand, aggregateRating, review), Offer schema, BreadcrumbList, Organization - Open Graph + Twitter Card: og:image generowany przez Next.js dynamic OG image route (1200×630, branding, product hero, cena) - robots.txt + meta robots: zachować noindex dla /account/*, /cart, /checkout - Canonical URLs: explicit canonical na każdą stronę produktową, powód: Shopify używał go z parametrem ?variant=, Medusa robi to przez separate URL lub client-side state, potrzeba canonical na base product URL
Tydzień 12: Plan cutover - DNS cutover plan (TTL 60s 24h przed cutoverem) - Database snapshot Shopify → Medusa import (last delta) - Stripe webhook switch (Shopify Stripe → Medusa Stripe) - Klaviyo webhook switch - Powiadomienie klientów: „w sobotę nocą od 02:00 do 04:00 e-sklep niedostępny"
Miesiąc 4: Cutover + stabilizacja
Tydzień 13: Soft launch - Subdomena shop-new.domain.pl → Next.js storefront + Medusa backend - 5 % traffic routowane przez Cloudflare Workers split test - Sentry watch: zero new errors przez 48 h - Klaviyo monitoring: cart abandonment rate stable
Tydzień 14: Pełny cutover - DNS cutover (apex domain → new infra) - 301 redirect map wdrożony na Cloudflare Workers (pre-DNS-cutover już running) - Shopify pozostaje w read-only mode przez 30 dni (legal archive of past orders) - Customer support ticket spike monitor
Tydzień 15: Post-launch fix - 12 godzin bug fixing w pierwszych 72 h (żaden critical, ale 8 minor — checkout edge cases, B2B quote workflow, kilka issues z Algolia synonym)
Tydzień 16: Performance tuning + SEO check - Audit Lighthouse, LCP target < 1,5 s (osiągnięte 1,1 s) - Search Console: indexing status check, żadnych nowych 404 errors, żadnego rank dropu ponad 5 % na top 50 keywords - A/B test new product detail page vs Shopify-style → +14 % conversion rate
Co nas raniło (i co zrobilibyśmy inaczej)
Wolno: SK/PL-specific invoicing
Plan: 4 dni rozwoju na custom invoicing module.
Realność: 3 tygodnie.
Polskie wymaganie ustawowe na fakturę zawiera kilkanaście obowiązkowych pól (Ustawa o VAT art. 106e), plus electronic invoicing dla B2B powyżej określonej kwoty ma własne EDI requirements (KSeF — Krajowy System e-Faktur od 2026). Plus VAT OSS dla cross-border EU sales potrzebuje per-transaction reporting do KAS. Plus JPK_V7 (Jednolity Plik Kontrolny VAT) ma własne wymagania struktury.
Lekcja: szacować PL/EU compliance overhead na 3× pierwotny szacunek. Żadna funkcja EU compliance nie jest „2-day implementation".
Szybko: Algolia sync
Plan: 5 dni na Algolia integration + indexing.
Realność: 2 dni.
Medusa ma first-party Algolia plugin (@medusajs/algolia), który emituje webhook events (product.created, product.updated, product.deleted) → Algolia reindex. Setup to była konfiguracja API kluczy + index schema. Realnie 2 dni.
Lekcja: najpierw szukać first-party / community plugin. Jeśli istnieje i ma 1k+ GitHub stars, nie zaczynać custom integration.
Wolno: B2B quote workflow
Plan: 1 tydzień.
Realność: 3 tygodnie.
B2B customer chce „quote request" dla zamówienia powyżej 5 000 EUR. Workflow: 1. Customer dodaje produkty do koszyka → klika „Wnioskuj o wycenę" (zamiast „Dodaj do koszyka") 2. Quote powstaje w panelu admin, sales rep zatwierdza, ewentualnie modyfikuje cenę / shipping / payment terms 3. Customer dostaje email z linkiem na quote → może accept (utworzy order z dostosowanymi conditions) lub reject
Medusa v2 ma quote module w wersji alpha w 2026, ale workflow + UI musieliśmy zbudować custom. Plus admin permissions dla różnych sales repów. Plus email templates w PL.
Lekcja: B2B-specific workflows w headless commerce zawsze są custom. Saleor by tu może zaoszczędził 1 tydzień (ma built-in quote module w stable), ale Medusa decision był uzasadniony developer experience dla reszty stacka.
Szybko: zachowanie SEO przez 301 redirect
Plan: 1 tydzień na 301 mapping + monitoring.
Realność: 3 dni.
Klucz: zachować product handle (URL slug) z Shopify do Medusa. Shopify URL był /products/produkt-handle, Medusa ten sam pattern. 11 800 z 14 800 URL pozostało identycznych — żaden redirect potrzebny.
Dla reszty (collections, customer portal, kilka CMS pages) wdrożyliśmy 301 map na Cloudflare Workers (URL Rewrite Rules) — 280 explicitnych reguł + 12 regex patterns. Zero indexed URL straconych w Search Console po 60 dniach.
Lekcja: jeśli mogą Państwo zachować URL pattern, zróbcie to. Jeśli musicie zmieniać, zbudujcie redirect map *przed* cutoverem, nie po.
SEO checklist — co zweryfikować przed cutoverem
- 1.Sitemap parity: Next.js sitemap.xml musi zawierać wszystkie URL z pierwotnej Shopify sitemap. Diff przez skrypt
sitemap-diffw CI. - 2.301 redirect map: każda non-trivial zmiana URL zaindeksowana w
redirects.json, validated przeciw production load testom. - 3.Canonical URLs: explicit canonical na każdą stronę, powód: Shopify używał query params (?variant=), nowy stack może używać path-based URLs — canonical zapobiegnie penalizacji za duplicate content.
- 4.Structured data continuity: Product schema (offers, availability, price, sku) parytet z pierwotnym Shopify. Test przez Google Rich Results Test przed cutoverem.
- 5.Open Graph migration: og:image, og:title, og:description per page. Dynamic OG image generation przez Next.js dynamic route + edge runtime.
- 6.robots.txt: zachować noindex dla admin, account, cart, checkout. Dodać directive
Sitemap:. - 7.Internal linking: breadcrumbs, related products, category navigation. Spider crawl przez Screaming Frog dla potwierdzenia, że żadna strona nie jest orphan.
- 8.Core Web Vitals: LCP, FID/INP, CLS target dla top 50 landing pages. Lighthouse CI w deployment pipeline.
- 9.Search Console reverification: new property dla new infra (jeśli DNS się nie zmienia, żadna nowa verification needed, ale URL property się rekomenduje).
- 10.Monitoring: 30-dniowy post-launch watch dla indexing status, ranking changes na top 100 keywords, delta organic traffic.
ROI cutoff — kiedy migracja jest tego warta
Headless migracja tej skali kosztuje 40–80 k EUR w nakładach engineering (łącznie z internal time + external dev shop), plus 4 miesiące timeline.
Zwrot przez 3 lata:
| Korzyść | Oszczędność roczna |
|---|---|
| Shopify Advanced + Apps savings | 4 200 EUR |
| Poprawa LCP → +6 % conversion | 12k SKU × 20 EUR AOV × 1,2k orders/mies × 0,06 = ~17 280 EUR |
| Eliminated Shopify Plus upgrade (would be next, 25k+ USD / year) | 23 000 EUR |
| Faster B2B quote handling | 12 000 EUR (1 FTE dzień × 24 miesiące) |
| Razem oszczędności 3 lata | 170 940 EUR |
ROI: ~2,5 roku przy inwestycji 60 k EUR.
Dla kogo się NIE zwróci: - < 2 000 SKU, < 500 orders / miesiąc → Shopify pozostaje tańszy - Nie mają Państwo zespołu dev lub committed external partner dla 3-letniej konserwacji - Roadmapa nie mówi o B2B / multi-storefront / custom checkout
Praktyczna rada
Migracja to nie „kupimy Medusa, programiści to zrobią". To projekt business + tech + SEO + ops na 3–6 miesięcy. Największe niepowodzenia, które widzieliśmy:
- 1.Underestimated EU compliance. PL invoicing, OSS VAT, GDPR — wszystko zżera więcej czasu niż obiecuje PoC z danymi testowymi.
- 2.No 301 plan = lost rankings. 90 dni strat w organic traffic = 30–50 % straty przychodów. Wystarczy jeden zły cutover.
- 3.No customer support runbook. Cutover bez 24/7 incident planu = paniczny restart na Shopify po pierwszym kryzysie.
- 4.Underestimated data migration. 47k historycznych zamówień to nie „CSV import za weekend".
---
*Wykonujemy migracje headless commerce dla katalogów 2k–50k SKU, full-stack (Medusa.js / Saleor + Next.js + integracje + SEO continuity). Jeśli rozważają Państwo opuszczenie Shopify lub BigCommerce, pierwszy project assessment (4-godzinny warsztat) przejdzie stack decyzji, timeline, budżet i 301 redirect plan dla Państwa konkretnego katalogu zanim zobowiążą się do migracji.*
