> How to build a B2B product configurator headless: rule engine or solver, where rules live, server-side pricing, Nuxt on a commerce API, TYPO3 and 100k+ variants.
>
> Web page: https://balazscsorba.com/blog/headless-product-configurator-b2b · Language: English · Also available in: [Deutsch](https://balazscsorba.com/de/blog/headless-product-configurator-b2b.md) · [Magyar](https://balazscsorba.com/hu/blog/headless-product-configurator-b2b.md)
> Author: Balázs Csorba · Published: 2026-10-02 · Keywords: B2B product configurator, Produktkonfigurator, Produktkonfigurator TYPO3, B2B Konfigurator, headless product configurator, CPQ configure price quote, rule engine vs constraint solver, Nuxt Spryker Glue API, product configurator 100000 variants, accessible product configurator

[Blog](https://balazscsorba.com/blog)/Web engineering

# Headless B2B product configurator: rules, pricing and Nuxt on a commerce API

How to build a B2B product configurator headless: rule engine or solver, where rules live, server-side pricing, Nuxt on a commerce API, TYPO3 and 100k+ variants.

[Balázs Csorba](https://balazscsorba.com/about)·October 2, 2026·12 min read

-   Product configurator
-   B2B e-commerce
-   Nuxt
-   Headless commerce

![Diagram: a Nuxt front end talks to a configuration service that reads rules from the PIM and prices from the ERP, then hands a validated configuration to the commerce API.](https://balazscsorba.com/images/blog/headless-product-configurator-b2b/cover.webp?v=7334d81671)

## Key takeaways

-   Treat the configurator as a small service with three jobs (what is allowed, what it costs, what the shop needs to sell it), not as a front-end widget with rules baked in.
-   Start with a declarative rule engine; reach for a constraint solver only when rules interact so much that you cannot enumerate valid combinations or explain a conflict.
-   Rules belong where the product data is maintained (usually the PIM), prices where they are governed (usually the ERP), and the shop only receives a validated result.
-   The browser may preview, but the server must validate and price again at add-to-cart and at quote time, because client-side validation is trivially bypassed.
-   With 100,000+ variants you never ship the variant list: you ask the server for the next valid options, and you make that dialogue keyboard- and screen-reader-friendly.

On this page

1.  [What a B2B configurator actually has to do](https://balazscsorba.com/#what-it-does)
2.  [Rule engine or constraint solver](https://balazscsorba.com/#rule-engine-or-solver)
3.  [Where the rules live: PIM, ERP or shop](https://balazscsorba.com/#where-rules-live)
4.  [Pricing logic without leaking it](https://balazscsorba.com/#pricing)
5.  [The Nuxt front end on a commerce API](https://balazscsorba.com/#nuxt-front-end)
6.  [Integrating TYPO3 or another CMS](https://balazscsorba.com/#typo3-cms)
7.  [Performance with 100,000+ variants](https://balazscsorba.com/#performance)
8.  [Server-side validation, saving and quoting](https://balazscsorba.com/#validation-quotes)
9.  [Accessibility is a configurator requirement](https://balazscsorba.com/#accessibility)
10.  [A launch checklist](https://balazscsorba.com/#checklist)
11.  [Where this leaves you](https://balazscsorba.com/#outlook)
12.  [Sources](https://balazscsorba.com/#sources)

A product configurator looks like a front-end problem until the first real catalogue arrives. Then it turns out to be a data problem (where do the rules come from?), a pricing problem (who is allowed to say what this costs?) and a trust problem (can the shop sell exactly what the buyer configured?). In B2B, where a wrong combination means a wrong part on a machine, the last one matters most.

This is how I would build a **B2B product configurator** (a "CPQ-lite": configure, price, quote, without the full CPQ suite) headless in 2026. It draws on a guided configurator for more than 100,000 precision engineering articles with automated pricing, built in Nuxt.js on the Spryker Glue API (see [the Meusburger reference](https://balazscsorba.com/references)). The article stays at the level of architecture and trade-offs and does not describe that project beyond that.

## What a B2B configurator actually has to do

Strip away the UI and a configurator does four things. It **constrains** choices so that only valid combinations are reachable. It **derives** values the buyer should not type (article number, weight, lead time). It **prices** the result, often with tiered or contract prices. And it **hands over** a configuration the rest of the business can use: a cart line, a quote, a drawing request.

The recurring mistake is putting all four inside the front end, because that is where the demo is built. The result is rules that cannot be tested without a browser, prices the client can see and, worse, influence, and a shop that has to trust whatever arrives. I would split the system into a thin UI and a **configuration service** that owns the first three jobs, and let the commerce platform own the fourth.

## Rule engine or constraint solver

Historically, configurators started with production rules; the model-based, constraint-based approaches that followed separate product knowledge from the problem-solving strategy, so that changes to one do not break the other, as the [Wikipedia article on knowledge-based configuration](https://en.wikipedia.org/wiki/Product_configurator) describes. That separation is the practical point: whichever technique you pick, the rules should be data, not code paths.

A **declarative rule engine** evaluates conditions such as "if material is X, then diameters above Y are not allowed" against the current selection. It is easy to explain to product managers, easy to unit-test (selection in, allowed options out) and fast. A **constraint solver** such as [OR-Tools CP-SAT](https://developers.google.com/optimization/cp/cp_solver) treats the product as variables and constraints and searches for valid assignments; note that it works over integers, so decimal dimensions need scaling. It shines when constraints interact in ways you cannot order by hand, and when you want to answer "what is the closest valid configuration?".

My default is the rule engine, with the rules in a format that a solver could consume later. Most catalogue products are really families with a few dozen interacting parameters, and the explainability of a rule ("this option is disabled because of rule 42") is worth more to a support team than the generality of a solver. The table is the decision aid I would use.

Situation

Use

Why

Watch out for

Product families with parameter ranges and a few dozen dependencies

**Rule engine**

Transparent, testable, maintainable by product management

Rule order and overlapping rules; keep them declarative and unit-tested

Many interacting options, no clear evaluation order

**Constraint solver**

Finds valid assignments and conflicts without hand-written order

Integer modelling, response time, explaining failures to users

"Nothing is valid, what is closest?" must be answered

**Constraint solver**

Can relax constraints and search for alternatives

Needs a clear objective for what "closest" means

Mostly fixed variants, selection is a filter

**Faceted search, no engine**

The variants already exist as articles; filter and sort them

Do not build a configurator where a search page works

Rules owned by non-developers who change them weekly

**Rule engine with an editor**

Rules as data with versioning and review

Governance: who may publish a rule, and how is it tested

Before building anything, check that you need a configurator at all. If the variants exist as sellable articles, a good filterable catalogue is cheaper and more robust. A configurator earns its cost where the combination space is too large to enumerate or where values are derived, not chosen.

## Where the rules live: PIM, ERP or shop

The question that decides maintenance cost in year two is not which engine, but **who owns each kind of knowledge**. My rule of thumb: rules sit next to the product data that justifies them (typically the PIM), prices sit where they are governed (typically the ERP, with the shop caching them), and the shop never owns configuration logic. It owns the cart, the checkout and the customer relationship.

The architecture below puts a configuration service between the Nuxt front end and the commerce API. The service reads attributes and rules from the PIM, prices and availability from the ERP, and returns options, derived values, price and a validation result. The commerce API only ever receives a configuration that this service has validated.

The configuration service is the only place that combines rules, prices and validation. The browser previews; the commerce API receives validated configurations only.

Three consequences follow from this split.

-   **One source per fact.** If a rule exists in the PIM and again in the shop, one of them will be wrong within a quarter. Publish rules from the PIM into the service (for example as a versioned artefact) instead of re-entering them.
-   **The service is stateless over a selection.** Every call carries the full selection and the context (customer, price list, language). That makes it cacheable, testable and horizontally scalable.
-   **The shop sees a result, not a process.** Spryker, for instance, documents a Product Configuration feature with Glue API modules that carry configuration data on cart items ([Spryker documentation](https://docs.spryker.com/docs/scos/dev/feature-integration-guides/202108.0/glue-api/glue-api-product-configuration-feature-integration.html)). Whatever platform you use, check how it stores a configuration on a cart line and whether it can price it, before you design your own format.

## Pricing logic without leaking it

B2B prices are rarely a single number. They combine a base price, option surcharges, quantity tiers, customer-specific agreements and sometimes machining or setup costs. I would keep the **price calculation on the server, in the configuration service**, as a pure function of selection, quantity and customer context, and have it call the ERP or the price list the ERP maintains.

The front end then shows a price that the server returned and labels it as such. If the buyer changes quantity, ask again. Never compute the final price from numbers that were sent to the browser; those numbers are inputs for display, not for ordering.

**Make price reproducible**

Store, with every saved configuration and quote, the **rule-set version**, the **price-list version** and the **inputs** to the price function. When a customer disputes a quote three weeks later, you must be able to recompute it, or at least explain which rules and prices applied. Without this, "automated pricing" becomes a support problem.

Two practical points. First, decide early whether the configurator shows a binding price or an indicative one; if some items need manual quoting (special tolerances, large quantities), model that as an explicit outcome ("request a quote") rather than a missing price. Second, keep rounding, currency and tax rules in one place, otherwise the configurator, cart and invoice will disagree by cents and you will spend days finding out why.

## The Nuxt front end on a commerce API

On the front end I would build the configurator as a **guided dialogue over the server**, not as a client-side state machine that knows the rules. Each step sends the current selection to the configuration service and renders the options that come back, with disabled options carrying a reason. Nuxt fits well because server routes (Nitro) can act as a backend-for-frontend: the browser talks to your own endpoints, which in turn call the configuration service and the commerce API with credentials that never reach the client.

-   **Selection in the URL.** Encode the selection in the query string so a configuration can be shared, bookmarked and restored. It also makes testing easy: a URL is a test case.
-   **Server-driven steps.** The server returns the next step, the valid options and the reasons for disabled ones. Adding a parameter becomes a data change, not a release.
-   **Optimistic preview, authoritative result.** Show cheap local feedback instantly, but treat the server response as the truth and reconcile.
-   **Hand-off through the commerce API.** At the end, call the BFF, which validates once more and then writes the configuration to the cart or quote through the platform API (for Spryker, the Glue API).

If you also want an AI assistant that helps buyers describe what they need ("a plate for a mould, hardened, 300 mm"), let it propose a selection and then run that selection through the same service. The model suggests; the rules decide. For the agent side of this, see [agentic commerce protocols](https://balazscsorba.com/blog/agentic-commerce-protocols-ucp-acp-guide), and for exposing the flow to browser agents, [WebMCP](https://balazscsorba.com/blog/webmcp-agent-ready-website-guide). If you ship an assistant, evaluate it like any other product feature, as in [LLM evals for product features](https://balazscsorba.com/blog/llm-evals-for-product-features).

## Integrating TYPO3 or another CMS

Searches for "Produktkonfigurator TYPO3" usually come from a company that already runs TYPO3 for its marketing site and wants the configurator inside it. The clean pattern is a division of labour: **the CMS owns content, navigation, landing pages and SEO; the configurator owns configuration**. TYPO3 renders the page and mounts the configurator, either as an embedded Nuxt app or as an extension plugin that calls the same configuration service.

What TYPO3 should pass in is context only: the language, the customer group, the product family identifier. What it should not do is hold rules or prices. The moment a rule lives in a content element or a TypoScript condition, product managers cannot test it and developers cannot find it. The same applies to any other CMS, and to the choice between embedding and a fully headless front end: the more of the page the configurator owns, the more consistent the experience, but the more you give up the CMS preview workflow your editors like.

## Performance with 100,000+ variants

A catalogue of 100,000+ articles changes how you think about performance, because there is no list to render. The principle is simple: **never ship the variant list to the browser; ask the server for what is valid next**.

-   **Model the product, not the variants.** Attributes plus rules describe the space; variants are materialised only when needed (the article number, the price).
-   **Index for lookup.** Searchable attributes go into a search engine so that "which options remain?" is an index query, not a table scan.
-   **Cache by selection.** Option lookups for the same selection and context are identical; cache them at the edge or in the service, and key the cache by rule-set and price-list version.
-   **Keep payloads small.** Return only the next step, not the whole tree, and compress it.
-   **Virtualise what is long.** If a step does need a long list (hundreds of diameters, for example), render only the visible window: [virtualisation](https://web.dev/articles/virtualize-long-lists-react-window) recycles DOM nodes that leave the viewport so the number of rendered elements follows the window, not the data.
-   **Measure the whole dialogue.** The metric is "time from click to updated, valid options", p95, including the ERP price call. Budget it and test it with real selections.

## Server-side validation, saving and quoting

Everything the browser enforces, the server must enforce again. The [OWASP Input Validation Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html) is explicit that input validation must be implemented on the server because client-side validation is easily bypassed, and it favours allow-lists: define exactly what is permitted. For a configurator that means the server accepts only selections that are valid under the current rule set, and recomputes derived values and price instead of trusting any it receives.

Treat a configuration as an **immutable, versioned document**. A compact shape works well:

-   **Identity:** a configuration id, product family, created-by customer and timestamp.
-   **Selection:** the chosen parameter values, nothing derived.
-   **Versions:** rule-set version and price-list version used at creation.
-   **Result:** derived values, price breakdown, and the article number or a "needs manual review" flag.

Saving then means writing that document; **quoting** means freezing it, with a validity period, and linking it to the quote. When a quote is accepted, re-validate against the current rules before ordering: if a rule changed in the meantime, the buyer should hear about it before production does. Whether you keep the document in the configuration service or on the commerce platform is secondary to keeping it complete and replayable.

## Accessibility is a configurator requirement

A configurator is a dense, dynamic form, which is where accessibility usually breaks. The practical reason is simple: a buyer who cannot operate your configurator cannot order. These are the checks I apply, mapped to WCAG 2.2:

-   **Say what is wrong, in text.** [Success criterion 3.3.1](https://www.w3.org/WAI/WCAG22/Understanding/error-identification.html) requires that an input error is identified and described in text. "This diameter is not available with hardened steel" beats a red border.
-   **Announce changes without stealing focus.** When the price or the option list updates, [4.1.3 Status Messages](https://www.w3.org/WAI/WCAG22/Understanding/status-messages.html) expects the change to be programmatically determinable, for example with role="status" for updates and role="alert" for errors, so screen readers announce it without moving focus.
-   **Big enough targets.** [2.5.8](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html) sets a minimum of 24 by 24 CSS pixels for pointer targets, with exceptions; swatches and small steppers are where configurators fail.
-   **Use proven patterns.** Prefer native radio buttons, selects and number inputs; where you need a searchable option list, follow the [ARIA combobox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) including its keyboard support.
-   **Disabled options need reasons.** An option that is simply greyed out is a dead end for a screen-reader user; expose the reason in text.

Automated checkers find only part of this. Run the complete flow with a keyboard and at least one screen reader before you call it done.

## A launch checklist

Before a configurator goes live, I would want a yes to each of these:

1.  Every rule is data with an owner, a version and a unit test.
2.  Rules come from one source (usually the PIM), and publishing a rule set is a reviewed step.
3.  Prices are computed on the server from a versioned price list; the browser never decides a price.
4.  Add-to-cart and quote re-validate and re-price; a tampered request is rejected.
5.  Every saved configuration records rule-set version, price-list version and inputs, and can be recomputed.
6.  Cases that cannot be priced automatically end in an explicit "request a quote", not an error.
7.  The 95th-percentile "click to valid options" time is measured against real selections.
8.  The whole flow works with keyboard and screen reader, and errors and status changes are announced in text.

If you can only do three things first, do the first, third and fourth.

## Where this leaves you

The recurring theme is separation. Rules as data, owned in one place; prices governed by the system that is accountable for them; a thin front end that asks rather than knows; a commerce platform that receives validated results. That is also what makes the configurator stable enough to extend, whether the next step is a new product family, a quote workflow or an assistant on top.

The guided configurator I built in Nuxt.js on the Spryker Glue API is listed in [my references](https://balazscsorba.com/references). If you are planning one and want to talk through the rule engine versus solver decision or the PIM and ERP split, my [B2B e-commerce developer page](https://balazscsorba.com/expertise/b2b-ecommerce-developer) has the details.

## Sources

1.  [Wikipedia: Knowledge-based configuration (product configurator)](https://en.wikipedia.org/wiki/Product_configurator)
2.  [Google OR-Tools: The CP-SAT solver](https://developers.google.com/optimization/cp/cp_solver)
3.  [Spryker documentation: Glue API, Product Configuration feature integration](https://docs.spryker.com/docs/scos/dev/feature-integration-guides/202108.0/glue-api/glue-api-product-configuration-feature-integration.html)
4.  [OWASP: Input Validation Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html)
5.  [web.dev: Virtualize large lists](https://web.dev/articles/virtualize-long-lists-react-window)
6.  [W3C: Understanding SC 3.3.1 Error Identification (WCAG 2.2)](https://www.w3.org/WAI/WCAG22/Understanding/error-identification.html)
7.  [W3C: Understanding SC 4.1.3 Status Messages (WCAG 2.2)](https://www.w3.org/WAI/WCAG22/Understanding/status-messages.html)
8.  [W3C: Understanding SC 2.5.8 Target Size (Minimum) (WCAG 2.2)](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html)
9.  [W3C WAI-ARIA Authoring Practices: Combobox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/)

## Frequently asked questions

What is a B2B product configurator?

A B2B product configurator guides a buyer through choosing a valid combination of options for a configurable product, such as dimensions, materials and tolerances, shows the price and lead time, and passes the result to a cart or quote. Compared with consumer configurators, the rules are stricter, the catalogue is larger, and the price often depends on contract terms.

Rule engine or constraint solver for a product configurator?

Start with a declarative rule engine: it is easy to explain, test and let product managers maintain. Move to a constraint solver when rules interact so heavily that valid combinations cannot be enumerated or hand-ordered, or when you need to explain why a selection is impossible and find the nearest valid alternative.

Where should configurator rules live: PIM, ERP or shop?

Keep the rules next to the product data that justifies them, which is usually the PIM, and keep prices where they are governed, usually the ERP. The shop should consume a validated configuration, not own the rules, otherwise rules end up duplicated in the shop and the ERP and drift apart.

How do you build a Produktkonfigurator with TYPO3?

Let TYPO3 own content, landing pages and navigation, and mount the configurator as a headless app or a plugin that talks to a separate configuration service. TYPO3 passes only context such as language, customer group and a product identifier; rules, prices and validation stay out of the CMS.

How do you handle 100,000+ variants in a configurator?

Do not load or render all variants. Model the product as attributes and rules, let the server return only the options that are still valid for the current selection, index searchable attributes in a search engine, cache the option lookups, and virtualise any long list you do have to show.

How do you make a configurator accessible?

Use native form controls or well-tested ARIA patterns, announce price and validation changes as status messages without moving focus, describe errors in text next to the field, and keep targets at least 24 by 24 CSS pixels. Test the whole flow with a keyboard and a screen reader, not only with an automated checker.

Written by Balázs Csorba

Senior fullstack & AI engineer in Styria, Austria – 10+ years of Vue, Nuxt, Node.js and PHP, now building tooling for AI agents.

[B2B e-commerce & PIM →](https://balazscsorba.com/expertise/b2b-ecommerce-developer)[About me →](https://balazscsorba.com/about)

## More articles

-   [European Accessibility Act for B2B shops: what Spryker, Pimcore and TYPO3 teams must fix](https://balazscsorba.com/blog/european-accessibility-act-b2b-shop)
-   [Pimcore ERP delta sync: syncing product data between SAP or Infor, PIM and shop](https://balazscsorba.com/blog/pimcore-erp-delta-sync)
-   [Core Web Vitals for Nuxt sites and shops: fixing LCP, INP and CLS](https://balazscsorba.com/blog/nuxt-core-web-vitals-performance)
-   [Charging on EPEX Austria prices: what my Home Assistant app saves](https://balazscsorba.com/blog/home-assistant-ev-charging-energy-manager)

## Sounds like what you need?

Tell me about your project or role – I’d love to hear from you.

[Book a call](mailto:contact@balazscsorba.com) [Connect on LinkedIn](https://www.linkedin.com/in/balazs-csorba)
