Skip to content

Storefront

The storefront is a Next.js 15 application using the App Router with React 19 RC. It supports multi-country routing, multi-language content, per-brand theming, and custom features like the Magic Logo Configurator.

Dev port: 10010 (Turbopack) Production port: 9002 (standalone)

All routes are prefixed with [countryCode] (nl, de, fr, en):

RoutePurpose
/Homepage (hero, featured products)
/storeProduct listing with filters
/products/[handle]Product detail page
/categories/[...category]Category browsing
/collections/[handle]Product collections
/cartShopping cart
/checkoutMulti-step checkout
/accountCustomer dashboard
/account/@dashboard/ordersOrder history
/quoteB2B quote request
/toegangAccess request (gatekeeper)
/contactContact form
/aboutAbout page
/serviceService page
/faqFAQ page
/privacyPrivacy policy
/retourbeleidReturn policy (Dutch)
/termsTerms and conditions
/partners/*Partner pages (Spranz, Langenberg, MOXZ, Lanyards)
RoutePurpose
/order/[id]/confirmedOrder confirmation
/order/[id]/transfer/[token]/acceptAccept order transfer
/order/[id]/transfer/[token]/declineDecline order transfer
  • @login — Login/register form
  • @dashboard — Account overview, orders, addresses, profile

The signature custom feature — lets customers upload logos and configure print techniques:

  1. User clicks “Order with logo” on a product
  2. System fetches available techniques from API
  3. Multi-step wizard: Quantity → Technique → Colors → Logo Upload
  4. Integration with Spranz Designer (designer.spranz.de) via modal
  5. Config saved with cart item

Supports SKU formats:

  • Spranz: 376-00, 376-00.005
  • XD Connect: 100804-001, P706.042

IP-based access control for B2B-only storefronts:

  • Enable: NEXT_PUBLIC_GATEKEEPER_ENABLED=true
  • Public paths always accessible: /toegang, /privacy, /terms, /contact
  • States: loading, approved, pending, rejected, none, disabled
  • Backend: /store/access-check and /store/access-request
  • Languages: Dutch (nl), German (de), French (fr), English (en)
  • Default: Dutch
  • UI labels: JSON translation files with 3-layer resolution (tenant override → storefront base → shared package)
  • Product content: Medusa metadata.translations populated during medusa-sync from APLT multi-language columns
  • Context-based with useLanguage() hook + useProductTranslation() hook
  • LocalStorage persistence (magiverse_language)

See Multi-Language (i18n) for full documentation.

ContextPurpose
BrandProviderDomain-based brand detection, CSS injection, logo/favicon
LanguageProviderLanguage selection, translation function, persistence
LogoProviderMagic Logo upload, browser fingerprinting, cached logos
ModalProviderModal dialog state
GatekeeperProviderAccess control status

Server-side data modules (src/lib/data/):

ModuleFunctions
products.tslistProducts(), getProductByHandle(), getProductsById()
cart.tsretrieveCart(), addToCart(), updateLineItem()
customer.tslogin(), register(), retrieveCustomer()
orders.tsretrieveOrder(), listCustomerOrders()
pim.tsgetProductPriceTiers(), getFullPIMProduct()
cms.tsCMS content per brand
categories.tsCategory hierarchy
regions.tsRegion/country data
  • Products: revalidate: 3600 (1 hour)
  • Categories: revalidate: 86400 (24 hours)
  • Customer/cart: no-store (always fresh)
  • ISR revalidation via /api/revalidate endpoint
RoutePurpose
/api/pim/products/[sku]Fetch PIM price tiers (direct PostgreSQL)
/api/search/suggestionsSearch autocomplete
/api/revalidateISR cache revalidation
/api/images/[...path]Image proxy to backend
/api/aplt/categoriesAPLT categories

Key features from next.config.js:

  • output: 'standalone' for Docker deployment
  • URL rewrites proxying APLT endpoints to backend
  • Image optimization with 10+ remote domains
  • React Strict Mode disabled