PRD: Product options & variants
| Module | Product (CORE-05) | PRD ID | PRD-OPT-001 |
| Status | Shipped | Owner | Product squad |
| Date | 2026-06-12 | Version | v1.0 |
| Packages | @nx/commerce · @nx/core | URD | OPT · VAR |
TL;DR
Lets a merchant describe what makes each variant different. The owner sets up the options a product varies by - size, ice level, colour - each with its list of values. Every sellable variant then takes one value per option it uses. The system keeps these combinations honest: a value must belong to the product, and no two variants may share the same combination - so the POS, online channels, and reporting can all treat a variant's combination as its identity.
1. Context & Problem
Variants say a product has several sellable forms, not why they differ. With only free-text names, nothing stops two identical variants, the POS can't tell that size and ice are separate choices, and there's no stable combination to match an external listing against. This feature makes options, their values, and each variant's combination explicit - declared by the owner and kept consistent by the system.
2. Goals & Non-Goals
Goals
- Options per product, each with an ordered list of values, shown in the owner's chosen order.
- Each variant takes one value per option it uses.
- The system guarantees a variant's combination is valid and unique among the product's variants.
- A merchant setting decides whether every variant must use options, or whether option-free variants are allowed.
Non-Goals
- No automatic generation of every possible combination - owners declare only the variants they actually sell.
- No price or stock on a value - pricing stays in fares (FAR), stock stays in Inventory.
3. Success Metrics
| Metric | Target |
|---|---|
| Duplicate combinations | Zero - a variant repeating an existing combination is always refused |
| Invalid combinations | Zero - a value that isn't part of the product is never accepted |
| Strict-options enforcement | When the setting is on, no option-free variant can be created |
4. Personas & Use Cases
| Persona | Goal |
|---|---|
| Owner / Manager | Define how a product varies and the choices offered, in display order |
| Cashier | Pick a variant by choosing size, then ice - not from one long list |
| Channel integration | Match an external listing to the right variant by its combination |
Core scenario: an owner sets up a milk tea with size (S/M/L) and ice (100/50/0), then declares the five combinations actually sold. Adding a second "Large, 50%" variant is refused; so is choosing two sizes for one variant.
5. User Stories
- As an owner, I define a product's options and values once, so every variant just picks from them.
- As an owner, I want a combination that already exists to be refused, so the catalogue never holds two entries for the same thing.
- As an owner, I choose whether option-free variants are allowed, so simple products stay simple and complex menus stay disciplined.
- As a cashier, I see variants grouped by option, so ordering is a few taps.
6. Functional Requirements
| # | Requirement | URD |
|---|---|---|
| FR-1 | Owner can define a product's options, each shown in a chosen order | URD-OPT-001 |
| FR-2 | Each option carries an ordered list of values | URD-OPT-002 |
| FR-3 | An option and its values are created or changed together in one step | URD-OPT-003 |
| FR-4 | A variant declares its value on each option it uses; an unknown option or value is refused | URD-OPT-004 |
| FR-5 | A variant takes at most one value per option | URD-OPT-005 |
| FR-6 | Every value a variant uses must belong to the product and to its option | URD-OPT-006 |
| FR-7 | No two variants of a product may share the same combination; option-free variants are exempt | URD-OPT-007 |
| FR-8 | A merchant setting can require every variant to use options, refusing option-free ones | URD-OPT-008 |
| FR-9 | An owner can change which options a variant uses | URD-OPT-009 |
| FR-10 | An option offered with no values, or a duplicated choice, is refused | URD-OPT-010 |
Every refusal returns a clear, specific reason so the owner can correct it.
7. Non-Functional Requirements
- All-or-nothing - options and a variant's values are saved together: either every change is saved or none is.
- Per-merchant isolation - options belong to one product under one merchant; never shared across products or merchants.
- Languages - option and value names are shown in multiple languages.
- Order-independent - a combination is the same regardless of the order its values are listed.
8. UX & Flows
9. Data & Domain
| Concept | Role |
|---|---|
| Option | A way a product varies (size, ice level), with an ordered list of values |
| Option value | One choice on an option (S / M / L) |
| Combination | The set of values a variant takes - its identity within the product |
An option's name is unique within its product; a value is unique within its option; a variant's combination is unique among the product's variants.
10. Dependencies & Assumptions
- Variants exist per PRD-PRD-001 - options attach to variants, they don't replace them.
- The strict-options setting is read when a variant is saved; turning it on later does not re-check variants that already exist.
11. Risks & Open Questions
- Removing a value still used by a variant follows the Commerce deletion policy.
- Turning the strict setting on leaves existing option-free variants in place - only new changes are checked.
12. Release Plan & Launch Criteria
Released together with the variant capability. Launch criteria: invalid and duplicate combinations are refused with a clear reason; uniqueness holds even when variants are created at the same time; the POS shows options in the owner's order.
13. FAQ
Why not generate every combination for me? Most merchants don't sell the full matrix. Declaring only what's sold keeps the catalogue equal to what's actually sellable - no phantom variants to hide, price, or track stock for.
Can two products share options? No - options belong to one product. Shared templates may come later if duplication becomes painful.
Where do option-dependent prices go? On the variant's fare. The combination identifies the variant; the fare prices it.
References
- URD: OPT - Product Options · VAR - Variants
- Sibling PRDs: Product catalogue, variants & identifiers · Fare system & pricing
- Developer: @nx/commerce