Context
A Shopify storefront is not an operations system. Once volume grows, packing, courier, invoicing, cash-on-delivery, returns, loyalty points and campaign prices live in different portals. The people who ship orders cannot work from five dashboards, and a mismatch between an AWB, an invoice and a payout line is expensive to find after the fact.
The engineering problem is integration with discipline: many external systems, each with its own rate limits and partial failure modes, and an internal model that has to stay reconcilable day after day rather than merely imported once.
What we built
The platform is a Symfony API as the source of truth for operations, with a React backoffice on top. Shopify remains the shop; this system is where fulfilment, finance and exceptions are handled.
- Shopify as the commercial source — orders, customers, collections, discounts, payouts and webhooks are imported incrementally, with overlap windows so a missed page does not leave a hole. The shop stays the storefront; the API owns operational state.
- Logistics — FanCourier AWBs, manifests, geography and payouts, delivery-status tracking, return cases and a warehouse integration for serial numbers, so packing and shipping are driven from one queue rather than from the courier portal.
- Invoicing and finance — SmartBill invoices and payment status (with rate limits and a read-back verifier that never re-sends a payment), expense tracking, and payout lines from both Shopify and the courier.
- Reconciliation engine — each order is classified against invoices, COD, returns and refunds. Issues are opened and closed in batches, periods can be locked, and a diagnostic surface exists for a single order when the automatic classification is not enough.
- Sync coordinator — dozens of business imports run as leased Messenger jobs with overlap, safety delays and a diagnostics UI, instead of a crontab of independent commands that can overlap or silently stall. Operational drains (webhook reclaim, COD mark-paid, notification outbox) stay separate from the hourly cycle.
- Campaign pricing — a living-price pipeline computes campaign discounts from an external feed and writes the result back to Shopify metafields, with a diff view for orphans and mismatches before anything is published.
- Adjacent operations — warranty certificate PDFs, review import, loyalty-point sync, influencer discount codes, and a role-and-permission model so warehouse, finance and admin do not share one login.
Stack
Symfony 7.4 on PHP 8.2 with Doctrine and MariaDB, Symfony Messenger over Redis for imports and outbox work, a React 19 / TypeScript / Vite backoffice with Redux Toolkit, cookie-session auth and fine-grained permissions, AWS S3 for documents, and Mailgun for transactional mail. The split is the same one we use elsewhere: PHP where the domain, queues and integrations live; React where the operators work all day.
Status
Private engagement. Detailed metrics and client references are available on request under NDA.