Skip to content

Architecture

┌─────────────────────┐
│ Nginx Reverse │
│ Proxy (Port 80/443)│
└──────────┬──────────┘
┌────────────────────────┼────────────────────────┐
│ │ │
┌─────▼─────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ Portal │ │ Tenants │ │ PIM │
│ Vite+React│ │ (x11) │ │ Backend │
│ :5173 │ │ │ │ :4002 │
└────────────┘ │ ┌─────────┐ │ └──────┬──────┘
│ │Backend │ │ │
│ │:4010-40+│ │ ┌──────▼──────┐
│ └────┬────┘ │ │ PostgreSQL │
│ │ │ │ magic_pim │
│ ┌────▼────┐ │ └─────────────┘
│ │Storefront│ │
│ │:10010+ │ │
│ └─────────┘ │
│ │ │
│ ┌────▼────┐ │
│ │ Redis │ │
│ │:6310+ │ │
│ └─────────┘ │
└──────┬──────┘
┌────────▼────────┐
│ PostgreSQL │
│ (Shared Instance)│
│ │
│ magic_b2b_brinxx │
│ magic_b2b_default│
│ magic_b2b_logo.. │
│ magic_b2b_bovi.. │
│ ...per tenant │
└──────────────────┘
Supplier Feeds ──► Connectors ──► PIM Database ──► Tenant Databases
(Spranz, XD, (CSV/Excel/ (Master (Per-tenant
PF Concept) JSON parse) Products) aplt_products)
Customer ──► Storefront ──► Backend API ──► APLT Database
(Browser) (Next.js) (Medusa) (PostgreSQL)
├──► PDF Generation (PDFKit)
├──► AI Assistant (Claude API)
└──► Invoice Storage (/mnt/data/brinxx_invoices/)

The ecosystem runs 42 Docker containers in total, including 11 tenants, shared services (PostgreSQL, MySQL, PIM, N8N, NextCloud, OnlyOffice, RemBG, Preflight), and per-tenant Redis instances.

Each tenant is a self-contained stack of 3 Docker containers sharing a network:

┌─────────────────────────────────────────────┐
│ Tenant: magic_brinxx │
│ │
│ ┌─────────────┐ ┌──────────────────────┐ │
│ │ Redis │ │ Backend (Medusa) │ │
│ │ Port: 6340 │ │ Port: 4040 (API) │ │
│ │ │◄─│ Port: 7040 (Admin) │ │
│ └──────────────┘ │ │ │
│ │ Volumes: │ │
│ │ - /mnt/data/pim_data│ │
│ │ - /mnt/data/magic_ │ │
│ │ omniverse │ │
│ └──────────┬───────────┘ │
│ │ │
│ ┌────────────────────────────▼────────────┐ │
│ │ Storefront (Next.js 15) │ │
│ │ Port: 10040 │ │
│ │ Connects to Backend via internal URL │ │
│ └─────────────────────────────────────────┘ │
│ │
│ Network: magic_brinxx_network_dev │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ Shared PostgreSQL (magic_pim_postgres_dev) │
│ Port: 5432 │
│ Database: magic_b2b_brinxx │
└─────────────────────────────────────────────┘

The system uses two separate databases per tenant:

  1. Medusa Database — Standard Medusa e-commerce data (products, carts, orders, customers)
  2. APLT Database — Custom B2B ERP data (quotations, invoices, CRM, access control)
PostgreSQL Instance (magic_pim_postgres_dev)
├── magic_pim ← PIM master product data
├── magic_b2b_brinxx ← Brinxx APLT data
├── magic_b2b_default ← Default APLT data
├── magic_b2b_development ← Development APLT data
├── magic_b2b_logohorloge ← Logohorloge APLT data
├── magic_b2b_bovisales ← Bovisales APLT data
├── magic_b2b_demo ← Demo APLT data
├── magic_b2b_desluis ← De Sluis APLT data
├── magic_b2b_jodasign ← Jodasign APLT data
├── magic_spranz_logo ← Spranz designer data
└── master_magic ← Master Magic data
MySQL Instance (mysql container)
├── magic_doc ← Portal documentation
└── aplt_flow ← Workflow data
aplt_order_headers ◄──── aplt_order_lines
│ (document_relations)
aplt_quotation_headers ◄── aplt_quotation_lines
│ (converted_to)
aplt_invoice_headers ◄──── aplt_invoice_lines
aplt_credit_notes_headers ◄── aplt_credit_note_lines
aplt_products ◄──── aplt_techniques
└──── aplt_product_variants
aplt_customers ◄──── aplt_access_requests
aplt_leads ◄──── aplt_lead_activities
◄──── aplt_lead_tasks
aplt_cms_settings aplt_discount_groups
aplt_cms_pages aplt_vat_codes
aplt_cms_modules aplt_number_sequences
aplt_audit_log aplt_document_relations
Internet ──► Nginx (:80/:443)
├──► portal.magiceverse.online ──► :5173 (Portal)
├──► pim.magiceverse.online ──► :4002 (PIM Backend)
├──► admin-development.magiceverse ──► :4010 (Dev Backend)
├──► admin-demo.magiceverse ──► :4020 (Demo Backend)
├──► demo.magiceverse.online ──► :10020 (Demo Storefront)
├──► admin-default.magiceverse ──► :4030 (Default Backend)
├──► default.magiceverse.online ──► :10030 (Default Storefront)
├──► admin-brinxx.magiceverse ──► :4040 (Brinxx Backend)
├──► brinxx.magiceverse.online ──► :10040 (Brinxx Storefront)
├──► admin-spranz.magiceverse ──► :4091 (Spranz Backend)
├──► admin-master.magiceverse ──► :4059 (Master Magic Backend)
├──► n8n (3 instances) ──► :8090-8092 (Workflow Automation)
└──► ... (same pattern for all tenants)
/mnt/data/
├── magic_pim/ # PIM system
│ ├── backend/ # Medusa backend for PIM
│ └── storefront/ # PIM frontend
├── magic_omniverse/
│ ├── magic_portal/ # Central portal (Vite + React)
│ └── magic_commerce/ # All e-commerce tenants
│ ├── magic_development/ # MASTER codebase
│ ├── magic_brinxx/ # Brinxx tenant
│ ├── magic_default/ # Default tenant
│ └── ... (8 more tenants)
├── pim_data/ # Product images
│ ├── spranz/ # Spranz supplier images
│ ├── langenberg/ # Langenberg supplier images
│ └── svg/ # SVG logos for personalization
└── brinxx_invoices/ # Generated invoice PDFs
magic_development (MASTER)
│ cp / rsync
├──► magic_brinxx
├──► magic_default
├──► magic_logohorloge
├──► magic_bovisales
├──► magic_demo
├──► magic_desluis
├──► magic_jodasign
├──► magic_spranz
└──► master_magic

All code changes are made in magic_development first. After testing, files are copied to the other tenants. Each tenant then rebuilds its Docker containers to apply the changes.

Three N8N instances run for workflow automation:

InstancePortPurpose
N8N #18090Primary workflows
N8N #28091Secondary workflows
N8N #38092Additional workflows
ServicePortPurpose
PIM Backend4002Product Information Management
PIM API7992PIM API endpoint
PIM Redis6380PIM cache
PostgreSQL5432Shared database instance
MySQL3306Portal docs & workflow data
NextCloud8580File management
OnlyOffice8581Document editing
RemBG5050Background removal service
Preflight5051Preflight check service