Catalogues
A catalogue is a curated subset of products designed for a specific audience or destination. Each storefront, channel, or integration has its own catalogue. Packtpub.com has a catalogue. Gamedevassembly.com has a catalogue. The Amazon Kindle store has a catalogue. Catalogues are the bridge between the full product set and the specific products that appear in any given context.
Manual and Rule-based Membership
Products can be added to a catalogue in two ways:
- Manual picks — explicitly add individual products. Useful for editorial curation, featured collections, or small catalogues where every inclusion is a deliberate choice.
- Rules — define filters that automatically include products matching specific criteria. Rules are evaluated continuously; products flow in and out of the catalogue as their attributes change.
Rules can reference any product attribute (type, language, price, lifecycle state, tags, authors) or Content Lake attribute (document tags, entity data, contract permissions). For example:
- All English-language Book products priced under $30 with Content
Lake documents tagged
source/topic/php - All published products with
contract/allow/distribution/channel/amazon - All Video Course products by a specific author
A catalogue can combine manual picks with rules. Manually picked products are always included regardless of whether they match any rule. Rules expand the catalogue dynamically.
Catalogue Structure
| Field | Type | Description |
|---|---|---|
id |
string | Catalogue ID (UUIDv7) |
name |
string | Human-readable name |
description |
string | Purpose and audience |
owner_id |
string | User ID of the catalogue owner |
rules |
rule[] | Inclusion rules (evaluated continuously) |
manual_products |
string[] | Explicitly included product IDs |
state |
string | draft, active, sealed, or archived |
Every catalogue has an owner — the person accountable for its purpose, rules, and overrides. Ownership makes it clear who to contact when a catalogue's membership looks wrong. Ownership can be transferred but never removed.
Catalogue Lifecycle
| State | Description |
|---|---|
| DRAFT | Not yet live. Rules can be configured and tested. Membership events are not emitted |
| ACTIVE | Live and accepting updates. Rules are evaluated continuously, membership events are emitted |
| SEALED | Live but frozen. No rule re-evaluation, no new picks, no override changes. Membership is fixed |
| ARCHIVED | End of life. Retained for historical reference |
ACTIVE and SEALED are reversible — a sealed catalogue can be unsealed back to active, and vice versa. This supports workflows like sealing a catalogue for a seasonal campaign, then unsealing when the campaign ends. ARCHIVED is a terminal state.
DRAFT catalogues are useful for staging. A team can configure rules, test membership, and preview overrides before making the catalogue live. Moving from DRAFT to ACTIVE starts emitting membership events, which triggers downstream distribution sync.
Catalogues and Taxonomy
Catalogues and taxonomy are complementary:
- Catalogue defines which products are available in a context (the set).
- Taxonomy defines how those products are organised within that context (the structure).
A storefront has one catalogue and one taxonomy. The catalogue might include 5,000 products; the taxonomy organises those 5,000 into categories and subcategories. Both are scoped to the client application — packtpub.com and gamedevassembly.com have different catalogues and different taxonomies.
Catalogues and Distribution
Catalogues define what products are in scope for a destination. Distribution handles how those products are delivered.
Catalogue (Product Management)
│
│ defines the product set
▼
Distribution
│
│ delivers artifacts, enforces rights
▼
Channel (Amazon, Shopify, etc.)
When a product enters or leaves a catalogue, a membership event is emitted. The Distribution service reacts — syncing inventory to Shopify, updating listings on Amazon, or refreshing a storefront's product feed.
Catalogue Overrides
Product information within a catalogue can diverge from the base product. Each catalogue entry can override any product attribute — title, description, cover images, pricing — without modifying the base product record.
Each overridable field has a sync mode:
sync(default) — the catalogue entry tracks the base product. When the base product changes, the catalogue entry changes too.override— a static replacement value that does not change when the base product changes.template— a template with$variablesyntax that resolves dynamically against the current base product state.
Templates
Templates use $variable syntax to reference base product fields:
| Template | Base Title | Resolved Value |
|---|---|---|
$title — Now 70% Off |
Go Microservices | Go Microservices — Now 70% Off |
$title (${edition}e) |
Go Microservices | Go Microservices (2e) |
Learn $title |
Kubernetes | Learn Kubernetes |
Available template variables:
| Variable | Source |
|---|---|
$title |
Base product title |
$subtitle |
Base product subtitle |
$description |
Base product description |
$authors |
Comma-separated author names |
$edition |
Edition number |
$language |
ISO 639-1 language code |
$price |
Formatted base price |
Templates are evaluated at read time. When the base product title
changes, every catalogue entry using a $title template
automatically resolves to the new title.
Override Scope
Overrides apply per catalogue entry, not globally. The same product might have:
- Base title "Go Microservices" in the product record
- Template title "$title — Now 70% Off" in the Shopify catalogue
- Override title "Microservices mit Go" in the German storefront
- Sync mode (base title) in the Amazon catalogue
Each catalogue manages its own overrides independently.
Catalogue Entry Structure
| Field | Type | Description |
|---|---|---|
product_id |
string | Reference to the base product |
source |
string | rule, manual, or both |
overrides |
map | Field name to override config |
overrides.{field}.mode |
string | sync, override, or template |
overrides.{field}.value |
string | Static value or template string |
When no override is configured for a field, it defaults to sync.