# Your own components

OODS Foundry supports your own components by **substitution** in React and Vue. A mapping says which implementation replaces
one shipped OODS Foundry component. Composition keeps using OODS Foundry's component ids and traits; generation imports your implementation,
and the preview bundles it. New components beyond the shipped catalog are not supported.

## Map an implementation

Install or unpack your component package outside the runtime. Give `map` a shipped component id (from `catalog_list`),
its exact package version and export, and translations for any props whose names or values differ. For example:

```json
{
  "action": "create",
  "apply": true,
  "externalSystem": "my-team",
  "externalComponent": "TeamButton",
  "oodsTraits": ["Stateful"],
  "substitution": {
    "component": "Button",
    "react": {
      "package": "@my-team/components/react",
      "version": "1.0.0",
      "export": "TeamButton",
      "localPath": "/absolute/path/to/my-team-components",
      "props": {
        "content": { "name": "caption" },
        "intent": { "name": "appearance", "values": { "neutral": "quiet", "primary": "prominent", "danger": "danger" } }
      }
    }
  }
}
```

Add a `vue` entry with the same shape for Vue. Untranslated props, children/slots and event handlers pass through.
Set `passthrough: false` to drop unlisted optional props; every required OODS Foundry prop then needs a translation. An unknown
OODS Foundry component or prop, or an uncovered required OODS Foundry prop, is reported before a mapping is saved. The team's component still has to implement the
expected semantics; translating a name does not establish compatibility.

The launcher defaults mappings to `~/.oods-foundry/mappings/component-mappings.json`. `OODS_MAPPINGS_DIR` selects another
folder; the existing `MCP_MAPPINGS_PATH` selects a file and takes precedence. Team traits resolve from your trait folder.
Mappings and local packages belong outside the unpacked runtime so upgrades and readiness checks leave them intact.
`localPath` must be absolute and point at the package root. Without it the preview looks for an installed package. The
package manifest's name/version must match, and its export must resolve. Local paths are not emitted into consumers.

### Map several at once

A checked mapping file contains a `mappings` array. Each entry has the same fields as the single call above, without
`action` or `apply`:

```json
{
  "mappings": [
    {
      "externalSystem": "my-team",
      "externalComponent": "TeamButton",
      "oodsTraits": ["Stateful"],
      "substitution": {
        "component": "Button",
        "react": {
          "package": "@my-team/components/react",
          "version": "1.0.0",
          "export": "TeamButton",
          "localPath": "/absolute/path/to/my-team-components",
          "props": { "content": { "name": "caption" } }
        }
      }
    }
  ]
}
```

Call `map` once for the file:

```json
{"action":"create","mappingsPath":"/absolute/path/to/mappings.json","apply":true}
```

You can instead pass the array as `mappings` in that call. Omit `apply` to check every entry without saving it.
The response lists each entry's zero-based `index`, generated `id`, validation `status` and whether it was `applied`.
All entries must pass before anything is written: mapping ids must be distinct; each shipped component can be
substituted only once across the list and the existing store; all component and prop checks still apply. With
`localPath`, the package manifest must match the package name and exact version, and its entry file must statically
export the named identifier. OODS Foundry reads these files without running package scripts. An invalid entry is
named with `OODS-V219`; no entry is saved. A valid list is saved in one atomic write.

The package ships `quickstart/team-components/mappings.json`, the Harbor walkthrough's Button mapping in this
file shape. Copy the example set to your workspace and replace both `<team-components>` values with that folder's
absolute path before calling `map`. The placeholder is documentation, not a path that the tool expands. Your own
file uses your package names, exact versions, exports and prop translations.

## Compose, preview and generate

Use `design_compose` or `design_preview` with your object as usual. Only components present in the screen are replaced.
A preview records package content hashes and freezes compiled output per version; reopening an explicit version retains
its original bytes. Opening the latest version after package bytes change creates a new version. Missing or unbundleable
packages produce `OODS-V217`. Package CSS can be inlined, but external CSS assets, unsafe paths and symlinks are refused.

`code_generate` imports the mapped package and declares its exact dependency version. Set `options.output` to
`"application"` for a single screen with a package manifest, entry, HTML and Vite configuration. The default remains a
component. Follow the response's install block: the `@oods` libraries install from npm at exact versions, and a team
package from your registry, or from its own tarball or folder when it is not on one. Then run `npm run build` and
`npm run dev`.
No package is published by generation. Sample data is labelled, and actions needing your application show an integration
notice; wire your data, navigation and persistence handlers before shipping.

## shadcn/ui

A React project using shadcn/ui's **Radix base and Tailwind 4** can map its own copied components. Keep `components.json`, the TypeScript path aliases, the CSS entry, and the installed dependencies in the project. Base UI, React Aria and Vue are not supported by this route.

Install the eight adapters from your installed `@oods/foundry` package in one call, from your shadcn project:

```bash
npx shadcn@4.21.1 add ./node_modules/@oods/foundry/shadcn/oods-button.json ./node_modules/@oods/foundry/shadcn/oods-card.json ./node_modules/@oods/foundry/shadcn/oods-status-badge.json ./node_modules/@oods/foundry/shadcn/oods-tabs.json ./node_modules/@oods/foundry/shadcn/oods-select.json ./node_modules/@oods/foundry/shadcn/oods-search-input.json ./node_modules/@oods/foundry/shadcn/oods-pagination-bar.json ./node_modules/@oods/foundry/shadcn/oods-banner.json -y
```

Copy `shadcn/mappings.json` from that package into your workspace and replace every `<shadcn-project>` with your project's absolute path. If the project's component alias differs from `@/components`, edit the eight `module` values to match the paths the CLI wrote. Apply the file in one call:

```json
{"action":"create","mappingsPath":"/absolute/path/to/mappings.json","apply":true}
```

Each React implementation uses this source form instead of `package`, `version` and `localPath`:

```json
{"shadcn":{"project":"/absolute/path/to/team-app","module":"@/components/oods/button"},"export":"OodsButton"}
```

Create and update check the named export, local imports, aliases, CSS entry, Tailwind version and installed bare dependencies without executing the component. Use `design_compose`, `design_preview` and `code_generate` as above. Preview compiles the project's Tailwind and theme; changes to mapped source files, their imports, configuration or CSS create a new latest version. Unrelated project files do not. Explicit old versions retain their compiled output.

Component output imports the project's module. Place its files in the project, supply its declared props and action callbacks, and set the surrounding container's `data-brand` and `data-theme` for the chosen OODS brand and theme. Application output copies the needed source files and CSS, configures aliases and Tailwind, and pins dependencies to their installed versions. The emitted metadata records project-relative paths and closure hashes, with no absolute project path. Workflow generation refuses shadcn mappings with a named reason. See [BRANDS.md](./BRANDS.md) to derive an OODS brand from the same CSS theme.

The adapters preserve the data-driven OODS props. They use `data-oods-adapter` markers so OODS component CSS does not override the team's shadcn styles. The contract report still lists each obligation as met, unmet or not checked, with a reason; the adapter is not a claim of complete component equivalence. These differences are also named in each registry item's description:

| Adapter | Explicit limits |
| --- | --- |
| Button | Success and warning intents use the secondary variant; there are no separate success/warning palettes. |
| Card | A semantic `as` element wraps the shadcn Card. |
| StatusBadge | OODS supplies status labels and icons. Critical/danger uses destructive; other tones use default or secondary, without separate status colours. `compact` and `readOnly` retain OODS's no-op behavior. |
| Tabs | The list scrolls horizontally; `overflowLabel` and the OODS overflow menu are not implemented. |
| Select | The visible control is a Radix combobox. A hidden native select keeps form values and native change events. Use `options`; native option children, `multiple`, native `size` and native-select keyboard behavior are unsupported. |
| SearchInput | Value, debounce, minimum query length and clear events retain their meanings. |
| PaginationBar | Page links are anchors; disabled links prevent navigation and leave the tab order. |
| Banner | Critical/danger uses destructive. Other tones use the team's default Alert palette; separate success/warning/info colours and solid emphasis are unsupported. |

## What the report means

Mapped components carry `component-contracts.json` in the generated artifact and reports in the preview's Measurements.
OODS Foundry runs its shared scenarios through the actual generated prop adapter when a browser is available to the preview
host. It uses an installed Chromium browser, `OODS_CONTRACT_BROWSER_EXECUTABLE`, or `OODS_PLAYWRIGHT_WS_ENDPOINT`; it does
not download a browser. Every declared obligation is **met**, **unmet** or **not checked**, with a reason. Unsupported
probes and unavailable browsers remain not checked. Warnings (`OODS-V218`) are advisory and do not refuse generation.
A passing subset is not full compatibility, accessibility certification or a claim about every state of a component.

The packed journey proves the bundled test team's Button and StatusBadge in Warehouse screens in both frameworks and
three themes. Separate browser checks cover its Input and deliberately broken Button. Material UI, Ant Design and
Chakra UI are not proven by these fixtures; a library needs its own adapter and receipt.
