Premium print products company
Branded dealer storefronts where each print dealer is paid into its own account
A premium print company wanted its wholesale dealers to run branded storefronts on a platform built to replace its legacy PHP system. Each dealer takes payment in its own account, the platform never holds funds, and approved orders route back for production.
Retail & E-commerceMulti-tenant dealer storefront platformModernized a live product
The challenge
The legacy system had no multi-tenant support, so dealers could not run their own storefronts. Every custom order also needs files or design help, a proof and an approval before production.
What we did
A multi-tenant platform on Saleor with dealer storefronts, dealer-owned payment accounts, four roles with tenant filtering and a handoff that sends each approved order to central fulfillment.
The outcome
We deployed the platform to production in the client's own AWS account with three CI/CD pipelines, added reusable attributes and variants, and removed our staging servers.
- Deployed
- Production stack in the client's own AWS account
- Built to replace
- The dealer side of a legacy PHP order system
- Payments
- Dealer-owned Stripe or Payflow, no card data stored
- Roles
- Super admin, dealer admin, dealer staff, customer
The starting point
The client makes premium custom business cards and print products and sells them at retail, through resellers and through a network of wholesale dealers. Each dealer sells to its own customers, and the client produces and ships every order.
What had to change
The legacy PHP system had no multi-tenant support, so dealers could not run their own storefronts, products or orders, and new products were added by duplicating old ones. The client wanted each dealer to sell under its own brand while every order still flowed back for production.
What could not break
- Dealers collect payment in their own accounts, so the platform never holds funds
- No card data is stored, which keeps the platform out of PCI scope
- Dealers see their full customer record, while central admins see only shipping details
- Every order is paid in advance, before any design or proof work starts
- The catalog stays central; dealers control only visibility, pricing and descriptions
The calls we made
We read the old system as the specification, then framed every order as two legs, the customer paying the dealer and the dealer paying for production, with the platform holding the money in neither.
- 01
Dealer-owned payment accounts
Each dealer connects its own Stripe or Payflow account and checkout is hosted and tokenized, so the customer's money goes straight to the dealer and no card data is stored.
Ruled outCollecting payments centrally and paying dealers out, which would have put the platform in the flow of funds.
- 02
Split customer data by role
Tenant filtering on backend and frontend and four roles keep each dealer's customers private: the dealer sees the full record, central admins see shipping details, and only super admins see more, mainly if a dealer has to be replaced.
Ruled outOne shared customer list visible to central admins.
- 03
The legacy system as the specification
We asked for the old code, database and current workflows so embedded rules were not lost, and the client's own corrections went into a written scope before any build.
Ruled outConnecting to the legacy system: discovery showed the client wanted to replace it, not integrate with it.
- 04
Attributes and variants, not copied products
Options such as stock, corners and foil price the same across products, so we modeled them as parent and child attributes and reusable global variants, and recommended snapshotting variant data into each order so price edits never rewrite past orders.
Ruled outAdding new products by duplicating old ones, the practice the client wanted to leave behind.
- 05
Extend an open source engine, start small
Building on Saleor let us spend our effort on multi-tenancy, dealer payments and order routing. The first release used a few storefront templates on system generated subdomains.
Ruled outBuilding commerce from scratch, and custom domains, live shipping rates and more currencies in the first release.
How the system fits together
What we built
Storefront ordering
A product journey with dynamic card configuration, design file upload, a design service option, revisions and quote requests, then checkout with Stripe, Payflow, Apple Pay, Google Pay and promo codes.
Reusable attributes and variants
Parent and child attributes, for example foil, foil color and foil type, and global variants with their own pricing and media that attach to many products, managed from a simplified admin dashboard.
Dealer onboarding
Self registration, a choice of storefront template, payment gateway setup and automatic activation on a system generated subdomain.
Order approval and routing
Advance payment before any design work, dealer review and approval, and a send to central admin handoff where the central admin charges the dealer's stored card for that order.
Dealer admin panel
Each dealer manages catalog visibility, markup, detailed promo rules, refunds, staff permissions and a sample module with tracking.
How it works
Dealer goes live
A dealer registers, picks a template, connects its own payment account, and its storefront activates on a subdomain.
Customer orders
A customer configures a card, uploads files or asks for the design service, and pays the dealer in advance.
Proof and approve
The customer approves the proof, or rejects it with comments that send it back to the dealer, before anything is produced.
Dealer sends it on
The dealer reviews the order and sends it to central admin.
Central fulfillment
The central admin charges the dealer's stored card for the order, and the client produces and ships it with tracking for the customer.
A closer look
What changed
We delivered one platform for dealer storefronts, dealer-owned payments, order approval and central fulfillment, and deployed it to production in the client's own AWS account. The attribute and variant system then answered the client's concern about keeping prices and options right across many products, and we removed our staging servers at handover.
Under the hood
- Datics role
- Modernized a live product
- Payments
- Stripe and PayPal Payflow per dealer, Apple Pay and Google Pay, with hosted, tokenized checkout and no card data stored.
- Tenant isolation
- Tenant filtering on backend and frontend, with super admin, dealer admin, dealer staff and customer roles, and shipping-only customer views for central admins.
- Engine
- Saleor with GraphQL, PostgreSQL, Redis and Celery workers in Docker Compose, a Next.js storefront and a Saleor Dashboard for central admins.
- Deployment
- Backend and storefront on separate EC2 servers, the admin on S3 and CloudFront, PostgreSQL on RDS with backups and Performance Insights, and three CI/CD pipelines.
Data and retrieval
Cloud and infrastructure
Apps and APIs
Also in the stack
How it shipped
Discovery and written scope
A discovery call with the client's founders, a proposal, and a scope document that took in the client's own annotations on roles, privacy, quotes and payments.
First milestone on staging
Setup, sign-in, role based access, storefront setup, dealer management and both admin panels, shown to the client in demo videos.
Ordering, checkout and routing
The customer journey, quotes, cart and checkout with every payment method, tenant filtering, order flows with and without files, and the handoff to central admin.
Production in the client's AWS
Backend, storefront and dashboard deployed to the client's own AWS account with three CI/CD pipelines, after which our staging servers were removed.
Attributes, variants and admin
After go live, a simpler admin dashboard, artwork in Amazon S3, email through Amazon SES, and the dynamic attribute and global variant system, demoed to the client.
Scope with the client's own corrections
The client annotated our first scope draft, and its decisions on roles, privacy, quotes, samples and payments went into the final scope before any build started.
In the client's own channels
We ran the project in the client's Slack workspace and a shared folder the client set up, and showed each milestone on staging in recorded demos.
Three repositories, handed over
Backend, Next.js storefront and admin dashboard live in three repositories with three CI/CD pipelines into the client's AWS account, and our staging servers were removed at handover.
What this unlocked
The scope was written so order routing can later move orders between the client's own entities and between dealers, and so AI reporting and AI customer support can be added on the same data.
Related work
Have a product with the same kind of constraints?
Tell us what already exists and what you want it to do. We will tell you what it takes.
