Overview
The catalog system manages the curated index of all published entries. It provides a centralized manifest, featured spotlight content, and editorial controls for staging and publishing changes to test/production environments.The catalog data lives in
data/catalog.editorial.json (editorial staging) and data/catalog.entries.json (build artifacts).Catalog Architecture
Catalog Editorial File
Thecatalog.editorial.json is the source of truth for staged catalog changes:
Manifest Entry Schema
Entry slug/identifier (must match entry folder name).
Canonical entry path (e.g.,
/entry/john-doe-piano/). Must start with /entry/ and end with /.Display title for catalog listings.
Lookup code from entry (e.g.,
"A.Pl S4 01").Season identifier (e.g.,
"S4"). Must match pattern S\d+.Primary artist/performer name.
Primary instrument name.
Entry status:
active: Visible in catalogdraft: Hidden from public catalogarchived: Retired but preserved in manifest
Spotlight Schema
Entry to feature in spotlight. Must exist in manifest.
Spotlight headline (e.g.,
"ARTIST SPOTLIGHT").Subheading text (usually entry title).
Spotlight body copy (up to 640 characters).
Call-to-action button label (e.g.,
"VIEW COLLECTION").Spotlight image URL or asset path.
Catalog Entries File
Thecatalog.entries.json is generated from scraping the catalog HTML page:
This file is generated by
scripts/lib/catalog-model.mjs from HTML scraping. It’s used for validation and as a staging source.Catalog CLI Commands
Manifest Management
List Manifest
Add Entry to Manifest
--entry flag accepts:
- Entry slug:
john-doe-piano - Entry href:
/entry/john-doe-piano/ - Entry ID:
john-doe-piano
If the entry exists in
catalog.entries.json, metadata is auto-populated from that source.Edit Manifest Entry
Retire Entry
status: "archived" without removing from manifest.
Remove Entry
Staging Entries
Thestage command adds an entry from catalog.entries.json to the editorial manifest:
manifest add but pulls all metadata from the entries file.
Spotlight Management
The spotlighted entry must exist in the manifest. Validation checks this constraint.
Validation
- Schema compliance: All fields match Zod schemas
- Linkage: Every manifest entry has a corresponding entry page in
entries/ - Spotlight reference: Spotlight
entry_idexists in manifest - Cross-manifest consistency: Home featured entries are in catalog manifest
- Duplicate detection: No duplicate
entry_idorentry_hrefvalues
Diff and Publish
Diff Local vs Remote
+3: 3 entries added locally-1: 1 entry removed locally~2: 2 entries modified locally
Publish to Environment
Pull from Environment
catalog.editorial.json with the remote version.
Catalog Model Extraction
The catalog model is built by scraping HTML from the live catalog page:- Entry hrefs and titles from carousel slides
- Instrument families from accordion sections
- Lookup numbers from anchor text
- Season identifiers from lookup patterns
- Spotlight content from special sections
See
scripts/lib/catalog-model.mjs for the full extraction logic including normalization and deduplication.Season Management
Seasons group entries chronologically:data/catalog.seasons.json.
Linkage Validation
The catalog enforces entry page linkage: every manifest entry must have a corresponding entry page:Symbol Classification
The catalog includes a symbol legend with auto-classification:- Instrument:
A,Pl,Dr, etc. - Collection:
AV,A-E, etc. - Quality:
[4K],[Stereo], etc. - Qualifier:
[Loud],[Clean], etc.
Best Practices
Stage Before Publish
Always use
dex catalog stage to add entries, ensuring metadata consistency with entry pages.Validate Early
Run
dex catalog validate before publishing to catch linkage and schema errors.Test Environment First
Publish to
--env test and verify in staging before promoting to production.Retire vs Remove
Use
retire to preserve history. Only remove --force-remove when absolutely necessary.Troubleshooting
Linkage Validation Failed
If you see “entry page not found”:- Verify the entry folder exists:
ls entries/entry-slug - Check for
index.html:ls entries/entry-slug/index.html - Regenerate if missing:
dex update entry-slug