By Hamza Makraz · · 7 min read

Building Farblieferant: a Sto paint dealer's shop on Symfony

How we took a certified Sto paint dealer from phone-and-email orders to a full online shop — a guided product finder, exact paint pricing, Stripe checkout, and a live link into Sto's ERP.

  • case-study
  • e-commerce
  • symfony
  • stripe

Putting a paint catalogue online is not the same problem as putting t-shirts online. Farblieferant is a certified Sto partner in Germany, and Sto products are technical: a façade render behaves nothing like an interior silicate paint, colours carry per-litre surcharges, and the price a customer pays has to match — to the cent — what the manufacturer’s ERP will invoice. The team had been selling the traditional way: phone, e-mail, trade contacts. They wanted a real shop. Not a template.

Here is what that actually took.

The challenge: a technical catalogue, non-expert buyers

Two things made this more than a generic storefront.

First, the buyers are mixed. Some are professional painters who know exactly which Sto product they want. Just as many are ambitious DIY customers who know the job — “I’m repainting a damp bathroom” — but not the product. A search bar serves the first group and abandons the second.

Second, this is Germany. The legal surface area — AGB, Widerrufsbelehrung, Impressum, Datenschutz, GDPR-conform cookie consent — is not a “phase two” item. It ships with release one or it doesn’t ship.

So the centrepiece of the storefront isn’t search — it’s a guided Produktberater. The buyer answers a short series of questions (where are you painting, which surface, which finish) and the shop narrows the catalogue to what actually fits.

Under the hood it’s a small recommendation engine. Each answer is linked to a set of product tags; each product carries tags of its own. When the buyer finishes the journey, we score every product by how many of the selected tags it matches and rank by that overlap — so the most relevant products surface first rather than an unordered filter result. The final step can even carry its own heading and copy, so a “damp bathroom” path lands on a page that reads like advice, not a query.

It’s built as a Symfony UX Live Component, so each answer updates the results in place — no full page reload, no single-page-app framework to maintain.

Pricing that has to be exact

Paint pricing is deceptively hard. A variant has a base price, a colour can add a per-litre or per-kilogram surcharge depending on its colour class, and a margin sits on top — then 19% VAT. Do that with floating-point arithmetic and you will, eventually, be one cent off on an invoice. In German retail, one cent off is a real problem.

So there is no float arithmetic in the money path. Every amount is stored as integer cents and computed with a precise decimal money library. The price the finder shows, the price in the cart, and the price the customer is charged are the same number, derived the same way.

Wired into Sto’s ERP

The prices and availability aren’t guesses, either. The shop talks to Sto’s ERP (SAP, via its Cloud Platform Integration layer) in two phases:

  1. Simulate — before an order is placed, ask the ERP to confirm current price and availability.
  2. Create — once payment succeeds, book the real order back into SAP.

That two-step flow is the difference between a shop that looks connected and one that won’t sell something it can’t fulfil.

Checkout, invoices, and the German essentials

Checkout runs on Stripe Checkout Sessions — cards, PayPal, and Klarna in one flow, with the order reference and any coupon carried through as metadata. On a paid order, an asynchronous job generates a PDF invoice and e-mails it to the customer; the heavy work happens off the request, so checkout stays fast.

Around that sit the things a German shop simply must have: the legal pages managed as editable CMS content, a free-shipping threshold and coupon engine, and Google Consent Mode v2 wired to the analytics layer so GTM only fires once the customer has actually consented.

The stack, and why

  • Symfony 8 / PHP 8.5 for the backend — a boring, durable choice the team can run for years.
  • Live Components + Stimulus for interactivity (cart, finder, search) — rich UX without shipping and maintaining a separate front-end app.
  • Asset Mapper + Tailwind CSS v4 — no Webpack, no bundler config to babysit.
  • A two-firewall security model — customers and back-office staff are fully separated, with a third, unauthenticated path reserved for the Stripe webhook.
  • EasyAdmin for the back office, so the team runs the catalogue, orders, and coupons without a developer in the loop.

Nothing exotic. The interesting parts are the paint-specific pieces — the finder, the cent-exact pricing, the ERP link — not the framework.

What it adds up to

BeforeAfter
Orders by phone, e-mail, trade contactsA full self-serve shop: browse, configure, pay, ship
Buyers had to already know the productA guided finder that maps a job to the right product
Prices quoted manuallyCent-exact pricing, validated live against Sto’s ERP
No web presenceGerman-compliant from the first release

If this sounds like your problem

We designed and built Farblieferant end to end — brand, storefront, pricing engine, ERP integration, and the back office the team runs day to day. We didn’t read about cent-precise pricing or two-phase ERP order flows; we shipped them.

If you’re a dealer or a brand sitting on a technical catalogue and a phone number where a shop should be, that’s exactly the kind of work we like. Tell us what you’re trying to build — we reply within one business day.

After you read

No list, no newsletter — just a feed

We don't collect email for a newsletter. If you want new pieces in your reader, the RSS feed is the canonical channel. If there's a topic you want us to cover, say so — we reply within one business day.