<!-- source-hash: b76130e377c5c19a3a90e82e946098da -->
Provides fallback `ProgramConfig` defaults for the chat dispatch layer, ensuring `<ProgramCard size='sm'>` renders correctly without requiring embedders to supply hub-side catalog configuration.

## Key Components

### `makeDefault<T>`
Generic factory function that constructs a minimal `ProgramConfig<T>` for a given program type. Populates only the fields the compact chat card actually reads (`type`, `labels.singular`) plus safe placeholder values for catalog-page fields (`dateField`, `table`, `apiEndpoint`, `icon`, `detailRoute`, `externalLinkLabel`) so TypeScript type-checking passes without binding embedders to hub-internal imports.

### `DEFAULT_PROGRAM_CONFIGS`
Exported `const` map of ready-to-use defaults for all three program types:

| Key | `type` | `labels.singular` | `labels.plural` |
|--------|---------|-------------------|-----------------|
| `podcast` | `"podcast"` | `"Episode"` | `"Episodes"` |
| `webinar` | `"webinar"` | `"Webinar"` | `"Webinars"` |
| `event` | `"event"` | `"Event"` | `"Events"` |

## Usage Example

The chat dispatch reads `extras.programConfigs.X ?? DEFAULT_PROGRAM_CONFIGS.X`, so overriding is opt-in:

```typescript
import { DEFAULT_PROGRAM_CONFIGS } from './program-card-defaults'

// Use defaults — no hub-side config required
const config = DEFAULT_PROGRAM_CONFIGS.podcast
// config.labels.singular → "Episode"
// config.type            → "podcast"

// Override only what you need; fallback handles the rest
const customConfigs = {
  podcast: {
    ...DEFAULT_PROGRAM_CONFIGS.podcast,
    icon: MyPodcastIcon,
    externalLinkLabel: 'Listen Now',
    detailRoute: '/podcasts',
  },
}
```

> **Why this exists:** Previously, missing `extras.programConfigs` caused the dispatch to return `null`, falling back to a bare text chip. These defaults decouple non-hub embedders (e.g. the validation app) from `currentPlatform()` and `buildContentURL` — hub-internal dependencies they cannot safely import.