Appearance
The product catalog
What the Systems, Attributes, Categories, and Factors screens manage — and why NanaSelect owns this model instead of borrowing Drupal's.
What it is
The catalog is NanaSelect's own structured model of the NanaWall product line:
- Systems — the products themselves (NW Aluminum 640, SL45, …), each carrying its attribute values and its links back to nanawall.com (PDP path, imagery).
- Attributes — the dimensions systems differ on (operation type, thermal performance, sightlines, …). These are the rows of the public comparison view.
- Categories — admin-only grouping that orders attributes into legible sections; categories never surface to buyers directly.
- Factors — the questions of the guided flow. Each factor asks about one buyer-relevant criterion and maps onto the attributes that answer it.
Systems × attributes say what each product is; factors turn those same dimensions into decisions a novice can make one at a time.
Why it exists
nanawall.com (Drupal) already has product pages — but its model is built for presentation, not selection. Recommending a system requires knowing, structurally, which attributes matter, how systems compare on them, and which question teaches each trade-off. That selection-oriented shape doesn't exist in Drupal and would be painful to retrofit there.
So NanaSelect owns a clean catalog tuned for selection, and stays connected rather than forked: the Drupal sync pulls product data in on demand, and deep links carry buyers back out to nanawall.com's PDPs and configurator. This is the "standalone, but connected" principle — see why it works.
How controlled vocabularies are identified
Two of the catalog's structures are controlled vocabularies — closed sets an operator curates, that other data points at: an enum attribute's allowed values, and the global cost-tier ladder.
Both originally keyed on their label. That is the natural first design and it has one severe consequence: the name is the identity, so renaming a value in use would orphan every stored payload and every reference pointing at it. The catalog's answer was to forbid the rename — an in-use value was locked, and fixing a typo meant a migration.
That is reversed. Each row now carries an opaque surrogate id, minted once at creation and never recomputed, and everything that refers to a value refers to that id. label became display-only, so renaming is a single-column update that breaks nothing. Alongside sits an alias table holding every name a value has ever worn — which is what makes a rename durable rather than merely safe: a stored payload, an older reference, or a Drupal sync still carrying the old spelling all resolve to the same row. A rename is one UPDATE; a re-sync afterwards recognises its own value instead of re-creating it.
Removal is still guarded, and always will be. Indirection makes renaming safe because the row survives; a delete takes the row — and the identity every reference points at — away with it. That is a referential problem, not a naming one.
The two vocabularies are asymmetric, deliberately. The enum catalog was fully contracted: its label column is gone and the id is the primary key. The tier ladder keeps tier as its key, frozen — written once at creation, never rewritten, with label carrying display. It behaves as a surrogate that happens to have originated as a label, which delivers the same guarantee; four consumers (stored tier payloads, tier rule thresholds, the systems tier facet, and the right-sizing ordinals) still speak that string, so dropping it would be a second high-risk engine migration bought for spelling alone. The asymmetry is recorded in schema.ts on both tables, and a contract check in npm run check enforces the invariant that actually matters on both: no code may construct an identity from a label.
In the admin
| Screen | How-to |
|---|---|
| Systems | Managing systems |
| Attributes · Categories | Managing attributes |
| Factors | Managing factors |
Learn more
- Drupal product contract — the fields synced from nanawall.com.
- Category ordering and factor ordering / factor dependencies — the ordering semantics.
- Recommendation matching — how the catalog feeds the engine.
- Managing attributes — what renaming and removing a value actually do, from the operator's side.