← All work

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.

  1. 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 out

    Collecting payments centrally and paying dealers out, which would have put the platform in the flow of funds.

  2. 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 out

    One shared customer list visible to central admins.

  3. 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 out

    Connecting to the legacy system: discovery showed the client wanted to replace it, not integrate with it.

  4. 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 out

    Adding new products by duplicating old ones, the practice the client wanted to leave behind.

  5. 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 out

    Building commerce from scratch, and custom domains, live shipping rates and more currencies in the first release.

How the system fits together

orders, filesapprove, pricefulfillhosted checkoutGraphQLapproved ordersend to admintenant filteredartworkDealer customersConfigure cards, uploadfiles, pay the dealerDealers and staffRun storefronts, approveordersCentral adminsCatalog, charges andfulfillmentDealer storefrontsNext.js, a subdomain perdealerDealer admin panelVisibility, markup,promos, staff, refundsCentral admindashboardSimplified SaleorDashboardMulti-tenant backendSaleor and GraphQL, tenantfiltering, four rolesOrder routingAdvance payment, approval,send to adminDealer paymentaccountsStripe or Payflow, ApplePay, Google PayPostgreSQL on RDSPlatform records, withbackupsAmazon S3Artwork and media
PeopleBuilt by DaticsOutside serviceData storeCard data never touches the platform: each dealer's own gateway hosts checkout, and the whole system was deployed in the client's own AWS account.

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.

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.

The product page configurator for size, thickness, backside print and corner style, built from the catalog.
03

Dealer onboarding

Self registration, a choice of storefront template, payment gateway setup and automatic activation on a system generated subdomain.

04

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.

05

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

Finishing options on a product page, where each choice such as foil color opens its own types and placement.
Finishing options on a product page, where each choice such as foil color opens its own types and placement.

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

PostgreSQLRedis

Cloud and infrastructure

AWS

Apps and APIs

DjangoNext.jsStripe

Also in the stack

SaleorGraphQL

How it shipped

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

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.

Book a 30-minute Product Review