# Data sources for the Beam Claude Plugin

How the plugin's skills fetch authoritative Beam information at runtime.

## Source-of-truth hierarchy

Use these in order. Never skip upward.

1. **MCP server (beam)** — PRIMARY. Structured JSON, offline-capable, auto-started by plugin.
2. **Deployed `llms.txt`** at `https://react.beam.viasat.com/llms.txt` — fallback when MCP server unavailable.
3. **Local `node_modules/@viasat/beam-react`** (and `@viasat/beam-tokens` for tokens) TypeScript definitions — fallback when llms.txt is unreachable.
4. **Model knowledge** — forbidden.

## MCP server

The `@viasat/beam-react-mcp` server provides structured, offline access to Beam component APIs, props, usage examples, and concept docs. It is auto-started by the plugin via the `mcpServers` config in `plugin.json`.

Data comes from `beam-manifest.json`, bundled in the npm package. Zero network calls at runtime.

### Tool catalog

| Tool                | Purpose                                                                 |
| ------------------- | ----------------------------------------------------------------------- |
| `listComponents`    | Discover components (optional `query`/`category` filter).               |
| `getComponent`      | Full API for one component: props, story index, `pairedHooks`.          |
| `getComponentStory` | Source of a specific usage example/story.                               |
| `listIconGroups`    | Icon groups with `importPath` and `iconCount` — no names.               |
| `searchIcons`       | Find icons by name (required `query`, optional `group`/`limit`).        |
| `listConcepts`      | Discover concept docs (theming, styling, tokens, getting started, …).   |
| `getConcept`        | Full MDX content for one concept doc, by slug or title.                 |

Icons are a two-step lookup: `listIconGroups` to see which families exist, then `searchIcons('close')` — optionally scoped with `group` (full `importPath` or its last segment, e.g. `flags`). Results come back grouped by import path, best-matching group first. `matchCount` is the total before `limit` (default 50) is applied, so if it far exceeds the returned icons, narrow the query instead of paging. There is no tool that dumps the full catalog — it's several thousand names.

**The main icon set uses Material Symbols names — search for those, not industry nicknames.** `@viasat/beam-icons/icons` (2,714 of the 3,777 icons) is Material-derived: the Material name, PascalCased. `access_alarm` → `AccessAlarm`, `wb_incandescent` → `WbIncandescent`, `close_fullscreen` → `CloseFullscreen`. About half the set ships Material's filled/outlined pairs (`Delete` and `DeleteOutlined`). If you know the Material icon you want, you already know Beam's name for it.

One wrinkle: the snake_case → PascalCase conversion is inconsistent, so don't assume exact Material casing. Material's `AccountCircle` is `Accountcircle` here, and `ArrowDropDown` is `ArrowDropdown`. Search is case- and separator-insensitive precisely for this reason — type the name as words (`arrow drop down`) and let it match.

The other two families are **not** Material. `illustrative-icons` are Beam-authored spot illustrations (`AccountManagement`, `ActiveCyberDefense`, `RecycleBin`), and `logos/*` are proper nouns (`Delta`, `ApplePay`, `ViasatLogoDefault`) — search those by the brand or subject name.

**Icon search is literal, not semantic.** Matching is substring over icon names, so industry nicknames fail in two ways. Some return nothing — there is no `hamburger` (it's `Menu`), no `cog` (it's `Settings`), no `spinner`, `ellipsis`, `avatar`, or `envelope`. Others return a confident wrong answer: `mute` surfaces `Commute` before `VolumeMute`, and `bin` returns `Plumbing` before `RecycleBin`. Zero results does **not** mean Beam lacks the icon — retry with the Material name, and read the returned name to confirm it describes the glyph you want before using it.

### Concept docs (and tokens)

Concept docs are MDX guides bundled in the manifest — theming, styling, getting started, and the token reference tables. Discover them with `listConcepts`, then fetch full content with `getConcept('<slug-or-title>')` (case-insensitive; returns `{ title, slug, description, type, mdxContent }`).

**Token data is delivered as concept docs, not a dedicated tool.** The nine `Tokens/*` concepts (e.g. `tokens-color`, `tokens-space`) each carry a token table inside `mdxContent`. See `references/tokens.md` for the full slug list, table shapes, and lookup procedure.

### Paired hooks and context-driven components

Some components are driven by an imperative hook or context provider, not by props and children alone. `ToastContainer` is controlled by `useToast()`, not by passing toasts as JSX. For these, `getComponent` returns a `pairedHooks` array. Each entry has the hook or provider `name`, `kind`, full `signature` (params plus resolved return type), and `importPath`.

Before implementing any component that manages state across a tree (Toast, Dialog, Popover, Select, Menu, Stepper, SideNav), follow these steps in order:

1. Call `getComponent` and inspect `pairedHooks`.
2. If `pairedHooks` is present, read every entry's signature before writing code. The hook is the API, and props alone will produce broken usage. If the component also lists subcomponents (for example Menu with `Menu.Trigger`), use both. The hook drives state and the subcomponents build the tree.
3. If `pairedHooks` is absent and `getComponent` lists subcomponents (for example `Dialog.Trigger`, `Select.Option`), the subcomponents are the API. Build with those. Do not grep.
4. If `pairedHooks` is absent and there are no subcomponents, only then grep the installed package for sibling hook or provider exports. The package ships compiled `.d.ts` files (`export declare const …`) and re-export barrels (`export * from …`, `export { useX } from …`), so the pattern must match all three forms. Folder names do not match component names (e.g. `ToastContainer` lives under `lib/Toasts/`), so grep the whole `lib/` tree:

```bash
grep -rEn "export (declare )?(const|function) use[A-Z]|export (declare )?const [A-Z][A-Za-z]*Provider|export \{[^}]*(use[A-Z][A-Za-z]*|[A-Z][A-Za-z]*Provider)" \
  node_modules/@viasat/beam-react/lib/
```

This is a backstop for one narrow case: a hook-driven component that shipped before it was added to the manifest's curated pairings. It is not a routine step, and most components will not reach it.

Before using anything the grep finds, confirm it is public API — i.e. it resolves through the package barrel. The root `node_modules/@viasat/beam-react/index.d.ts` only re-exports wildcards (`export * from './lib'`), so a name won't appear there literally; instead confirm it is re-exported from its own component barrel, e.g. `grep -rn "useToast" node_modules/@viasat/beam-react/lib/Toasts/index.d.ts`. If a name is only in an implementation file and not re-exported from any `index.d.ts`, it is an internal detail (for example `useDialogContext`, `usePopoverContext`, `useSelectDropdown`), not public API. Do not use it.

### Usage guidelines

Some components carry designer-authored usage guidance that can't be inferred from props or JSDoc — purpose, when to use versus avoid, anatomy, and dos & don'ts. When it exists, `getComponent` returns it inline as a `usageGuidelines` field (freeform markdown). Read it before using the component — it captures intent the API surface alone doesn't.


## Fetching llms.txt (fallback) — use curl, not WebFetch

When MCP is unavailable, fall back to llms.txt. **Use `curl` via Bash. Do NOT use the WebFetch tool.** WebFetch refuses to reproduce content verbatim and returns a summarized/categorized rewrite, which destroys the exact URLs, prop names, and descriptions you need. `curl` returns the raw markdown intact.

```bash
curl -fsSL https://react.beam.viasat.com/llms.txt
```

The `-f` flag makes curl exit non-zero on HTTP errors (4xx/5xx) so failures are detectable.

### Index structure

The index page is a flat list of links per section. Each entry has a URL and a one-line description. Always fetch the index first to discover what exists, then fetch only the specific pages you need.

URL patterns:

| Section    | URL pattern                  | Example                                          |
| ---------- | ---------------------------- | ------------------------------------------------ |
| Components | `llms/components-<name>.txt` | `llms/components-button.txt`                     |
| Forms      | `llms/forms-<name>.txt`      | `llms/forms-autocomplete.txt`                    |
| Layout     | `llms/layout-<name>.txt`     | `llms/layout-pagelayout.txt`                     |
| Concepts   | `llms/concepts-<name>.txt`   | `llms/concepts-theming.txt`                      |
| Tokens     | `llms/tokens-<category>.txt` | `llms/tokens-color.txt`, `llms/tokens-space.txt` |

Sub-components use a flattened slug: `Avatar.Group` → `components-avatar-avatar-group.txt`, `Menu.Trigger` → `components-menu-menu-trigger.txt`. Confirm the exact slug from the index.

**Examples pages:** some — not all — components have a companion examples page at `llms/components-<name>-examples.txt` (e.g. `components-actionlist-examples.txt`, `components-menu-examples.txt`). Don't assume it exists for a given component — check the index entry first. If no entry, there is no examples page; rely on the main component page.

Particularly relevant: **`llms/concepts-using-beam-with-ai.txt`** — the official Beam guide on AI consumption of llms.txt. Read it once to ground all AI-driven work in Beam.

If a section or page is missing from the index, do not assume it exists. Be defensive about parsing.

## node_modules fallback

When both MCP and llms.txt are unavailable, read the installed packages' TypeScript definitions.

### Locating the packages

| Layout             | Path                                                                       |
| ------------------ | -------------------------------------------------------------------------- |
| npm / yarn classic | `node_modules/@viasat/beam-react/`                                         |
| pnpm               | `node_modules/.pnpm/@viasat+beam-react@*/node_modules/@viasat/beam-react/` |
| yarn berry (PnP)   | No flat layout — ask the user                                              |

Same patterns for `@viasat/beam-tokens`.

### Which files matter

**`@viasat/beam-react`:**

- `index.d.ts` — top-level barrel exports. Discover what components exist.
- `lib/<Component>/<Component>.d.ts` — actual prop types with JSDoc descriptions on each prop (mirrors the prop descriptions in llms.txt).
- `lib/<Component>/index.d.ts` — sub-barrel for the component.
- `lib/<Component>/<Component>.figma.d.ts` — Code Connect metadata (rarely needed).

**`@viasat/beam-tokens`** (separate package):

- `types/lib/index.d.ts` — token type declarations (entry point).
- `tokens.css`, `tokens.scss` — the actual token values as CSS custom properties / SCSS variables.
- `themes/` — per-theme overrides.

### What's extractable vs missing

| Available from node_modules                            | Missing                                |
| ------------------------------------------------------ | -------------------------------------- |
| Component names and types                              | Story / usage examples                 |
| Prop names, types, defaults, JSDoc descriptions        | Visual screenshots                     |
| Token declarations and raw values (from `beam-tokens`) | MDX concept docs (theming, a11y, etc.) |

## Fidelity caveats

When using a fallback source, tell the user which tier you're on:

**Tier 1 (MCP):** Full fidelity — structured props, stories, concept docs.

**Tier 2 (llms.txt):** Near-full fidelity — has most of the core component knowledge (props, stories, concept docs) as raw markdown, but does NOT contain design usage guidelines. When you need a component's `usageGuidelines`, use MCP (Tier 1).
> "The Beam MCP server is unavailable — falling back to llms.txt. If you weren't expecting this, please report it in **#beam-help** so the team can investigate."

**Tier 3 (node_modules):** Degraded — no stories, no concept docs.
> "MCP and llms.txt unreachable — used node_modules. Story examples and concept docs unavailable; verify visually."

The user must know when data quality drops below the primary tier.

## Error handling

If ALL data sources fail:

1. Do not proceed.
2. Tell the user explicitly what was attempted and what failed.
3. Ask the user how to proceed: install the dep, check network, switch repos, etc.
4. Do not generate code from memory.

Example user-facing message:

> I couldn't fetch Beam component data. I tried:
>
> 1. MCP server (beam) — server not running or not configured.
> 2. `https://react.beam.viasat.com/llms.txt` — fetch failed: ENETUNREACH.
> 3. Local `node_modules/@viasat/beam-react` — package not installed.
>
> Beam isn't in my training data, so I can't safely generate code. Want to install the package, check the network, or work on something else?
