Single source of truth for grouping `content_ref` types with display metadata (label, render order, layout, and card size). Consumed by the `RelatedContentSection` component and the hub's investor email builder to ensure consistent rendering and ordering across surfaces. ## Key Components ### Types - **`ContentRefLayout`** — `'list' | 'grid'`; controls whether a group renders as full-width cards or a responsive column grid. - **`ContentRefGridSize`** — `'lg' | 'default' | 'sm'`; card size variant forwarded to the entity-card dispatch. Kept in lockstep with `EntityCardSize` to avoid a config→component import cycle. - **`ContentRefGroupConfig`** — shape of each entry: `label`, `order`, `layout`, `gridSize`. ### Constants - **`CONTENT_REF_GROUPS`** — registry of all known `content_ref` types (`investor_update`, `product_release`, `podcast`, `webinar`, `case_study`, `event`, `blog_post_existing`, `customer_interview`, `onboarding_guide`, `what_i_shipped`). Adding one entry here auto-registers the type in `RelatedContentSection` and makes it a hub suggestion candidate (if resolvable via `TYPE_TO_ENTITY` → RAG config). ### Functions | Function | Description | |---|---| | `getContentRefLabel(type)` | Returns the registered label or `null` for unknown types. | | `getContentRefLabelOrTitleCase(type)` | Returns the registered label or a title-cased fallback (e.g. `"podcast_guest"` → `"Podcast Guest"`). | | `orderContentRefTypes(present)` | Sorts a set of present types into canonical `order` sequence; unregistered types are appended in insertion order. | ## Usage Example ```typescript import { CONTENT_REF_GROUPS, getContentRefLabelOrTitleCase, orderContentRefTypes, } from '@openframe-oss-lib/utils/content-ref-groups' // Render groups in canonical order const types = ['blog_post_existing', 'podcast', 'custom_type'] const sorted = orderContentRefTypes(types) // → ['podcast', 'blog_post_existing', 'custom_type'] for (const type of sorted) { const config = CONTENT_REF_GROUPS[type] const label = getContentRefLabelOrTitleCase(type) // config?.layout === 'list' | 'grid' | undefined for unregistered console.log(label, config?.layout) } // Adding a new content type — one entry is all that's needed: // CONTENT_REF_GROUPS['press_release'] = { // label: 'Press Releases', order: 11, layout: 'list', gridSize: 'lg' // } ``` > **Extending:** Add new content types directly to `CONTENT_REF_GROUPS`. Prefer `gridSize: 'lg'` for types whose card component has a large variant. No other file needs updating for `RelatedContentSection` to pick up the new group.