Who it's for

A React project on shadcn/ui, on Radix or Base UI, with Tailwind 4. Your components.json names the base: a style that starts with radix is Radix, and one that starts with base is Base UI. This site ran one project with npm and Vite; the OODS Foundry team's own receipts cover pnpm, a hoisted npm workspace and Next.js App Router.

"style": "radix-nova"

What it reads, and what it writes

It reads your components.json, your TypeScript path aliases, your CSS entry and the dependencies you have installed. It checks each adapter's export and imports without running the component.

It writes 16 adapters into components/oods/, installed with the shadcn CLI from the @oods/foundry package in your node_modules, and reads one mappings file from your workspace. Generated apps are written outside your repo, or one generated screen is written into it as a component. Your components, your theme and your CSS are not changed.

Install, add and map

  1. Install the package in your project.

    npm install -D @oods/foundry@0.10.1
  2. Add the adapters with the shadcn CLI. This writes 16 files to components/oods/ and adds the @oods libraries they import.

    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 ./node_modules/@oods/foundry/shadcn/oods-input.json ./node_modules/@oods/foundry/shadcn/oods-textarea.json ./node_modules/@oods/foundry/shadcn/oods-checkbox.json ./node_modules/@oods/foundry/shadcn/oods-date-picker.json ./node_modules/@oods/foundry/shadcn/oods-tag-input.json ./node_modules/@oods/foundry/shadcn/oods-status-selector.json ./node_modules/@oods/foundry/shadcn/oods-card-header.json ./node_modules/@oods/foundry/shadcn/oods-price-badge.json -y
  3. Map them in one call. Copy shadcn/mappings.json from the package into your workspace, replace every <shadcn-project> with your project's absolute path, and apply it. If your components alias isn't @/components, edit the module paths in the file to match where the shadcn CLI wrote the adapters.

    {"action":"create","mappingsPath":"/absolute/path/to/mappings.json","apply":true}
    This site's call

    Its input:

    {
      "action": "create",
      "mappingsPath": "<workspace>/mappings.json",
      "apply": true
    }

    Its result:

    {
      "status": "ok",
      "entries": [
        {
          "index": 0,
          "id": "shadcn-oods-button",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-button",
            "externalSystem": "shadcn",
            "externalComponent": "OodsButton",
            "oodsTraits": [],
            "substitution": {
              "component": "Button",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/button"
                },
                "export": "OodsButton",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.084Z"
            }
          }
        },
        {
          "index": 1,
          "id": "shadcn-oods-card",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-card",
            "externalSystem": "shadcn",
            "externalComponent": "OodsCard",
            "oodsTraits": [],
            "substitution": {
              "component": "Card",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/card"
                },
                "export": "OodsCard",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.120Z"
            }
          }
        },
        {
          "index": 2,
          "id": "shadcn-oods-status-badge",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-status-badge",
            "externalSystem": "shadcn",
            "externalComponent": "OodsStatusBadge",
            "oodsTraits": [],
            "substitution": {
              "component": "StatusBadge",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/status-badge"
                },
                "export": "OodsStatusBadge",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.130Z"
            }
          }
        },
        {
          "index": 3,
          "id": "shadcn-oods-tabs",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-tabs",
            "externalSystem": "shadcn",
            "externalComponent": "OodsTabs",
            "oodsTraits": [],
            "substitution": {
              "component": "Tabs",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/tabs"
                },
                "export": "OodsTabs",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.138Z"
            }
          }
        },
        {
          "index": 4,
          "id": "shadcn-oods-select",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-select",
            "externalSystem": "shadcn",
            "externalComponent": "OodsSelect",
            "oodsTraits": [],
            "substitution": {
              "component": "Select",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/select"
                },
                "export": "OodsSelect",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.155Z"
            }
          }
        },
        {
          "index": 5,
          "id": "shadcn-oods-search-input",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-search-input",
            "externalSystem": "shadcn",
            "externalComponent": "OodsSearchInput",
            "oodsTraits": [],
            "substitution": {
              "component": "SearchInput",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/search-input"
                },
                "export": "OodsSearchInput",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.167Z"
            }
          }
        },
        {
          "index": 6,
          "id": "shadcn-oods-pagination-bar",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-pagination-bar",
            "externalSystem": "shadcn",
            "externalComponent": "OodsPaginationBar",
            "oodsTraits": [],
            "substitution": {
              "component": "PaginationBar",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/pagination-bar"
                },
                "export": "OodsPaginationBar",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.178Z"
            }
          }
        },
        {
          "index": 7,
          "id": "shadcn-oods-banner",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-banner",
            "externalSystem": "shadcn",
            "externalComponent": "OodsBanner",
            "oodsTraits": [],
            "substitution": {
              "component": "Banner",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/banner"
                },
                "export": "OodsBanner",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.187Z"
            }
          }
        },
        {
          "index": 8,
          "id": "shadcn-oods-input",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-input",
            "externalSystem": "shadcn",
            "externalComponent": "OodsInput",
            "oodsTraits": [],
            "substitution": {
              "component": "Input",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/input"
                },
                "export": "OodsInput",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.195Z"
            }
          }
        },
        {
          "index": 9,
          "id": "shadcn-oods-textarea",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-textarea",
            "externalSystem": "shadcn",
            "externalComponent": "OodsTextarea",
            "oodsTraits": [],
            "substitution": {
              "component": "Textarea",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/textarea"
                },
                "export": "OodsTextarea",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.203Z"
            }
          }
        },
        {
          "index": 10,
          "id": "shadcn-oods-checkbox",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-checkbox",
            "externalSystem": "shadcn",
            "externalComponent": "OodsCheckbox",
            "oodsTraits": [],
            "substitution": {
              "component": "Checkbox",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/checkbox"
                },
                "export": "OodsCheckbox",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.212Z"
            }
          }
        },
        {
          "index": 11,
          "id": "shadcn-oods-date-picker",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-date-picker",
            "externalSystem": "shadcn",
            "externalComponent": "OodsDatePicker",
            "oodsTraits": [],
            "substitution": {
              "component": "DatePicker",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/date-picker"
                },
                "export": "OodsDatePicker",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.230Z"
            }
          }
        },
        {
          "index": 12,
          "id": "shadcn-oods-tag-input",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-tag-input",
            "externalSystem": "shadcn",
            "externalComponent": "OodsTagInput",
            "oodsTraits": [],
            "substitution": {
              "component": "TagInput",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/tag-input"
                },
                "export": "OodsTagInput",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.243Z"
            }
          }
        },
        {
          "index": 13,
          "id": "shadcn-oods-status-selector",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-status-selector",
            "externalSystem": "shadcn",
            "externalComponent": "OodsStatusSelector",
            "oodsTraits": [],
            "substitution": {
              "component": "StatusSelector",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/status-selector"
                },
                "export": "OodsStatusSelector",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.252Z"
            }
          }
        },
        {
          "index": 14,
          "id": "shadcn-oods-card-header",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-card-header",
            "externalSystem": "shadcn",
            "externalComponent": "OodsCardHeader",
            "oodsTraits": [],
            "substitution": {
              "component": "CardHeader",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/card-header"
                },
                "export": "OodsCardHeader",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.260Z"
            }
          }
        },
        {
          "index": 15,
          "id": "shadcn-oods-price-badge",
          "status": "valid",
          "applied": true,
          "mapping": {
            "id": "shadcn-oods-price-badge",
            "externalSystem": "shadcn",
            "externalComponent": "OodsPriceBadge",
            "oodsTraits": [],
            "substitution": {
              "component": "PriceBadge",
              "react": {
                "shadcn": {
                  "project": "<shadcn-project>",
                  "module": "@/components/oods/price-badge"
                },
                "export": "OodsPriceBadge",
                "passthrough": true
              }
            },
            "confidence": "manual",
            "metadata": {
              "createdAt": "2026-10-08T15:11:22.266Z"
            }
          }
        }
      ],
      "etag": "e9c4e3ed2980c78a75ec6179ad1b86ec594fa12a37ee9827e1eb1f3b38fcbeaa",
      "applied": true
    }

From here, compose, preview and generate run as they do for any object. Preview compiles your project's Tailwind and theme.

Subscription, with your components

The Subscription list and detail screens, generated with the shadcn/ui project this site made from the public commands, in light, dark and high contrast. Each theme is its own app, generated separately, with its own content hash. Each frame is the app as generated. Beside it, the same screen with the mappings removed.

Detail: Your shadcn/ui components React app, shown in light sha256:f9c8aee87c35… Open full size: Subscription detail screen generated by OODS Foundry in React, with this site's shadcn/ui components, in light
Detail: OODS Foundry's components only React app, shown in light sha256:72151a466ded… Open full size: Subscription detail screen generated by OODS Foundry in React, with OODS Foundry's components only, in light
Which parts are yours
Screen Your shadcn/ui components OODS Foundry's
Detail The header actions (Button), the status badge (StatusBadge), the body card (Card), the Billing and Details tabs (Tabs) The title, the billing summary, the payment chart, the status and payment timelines, the cycle progress and the read fields
List The search field (SearchInput), the Status and Sort selects (Select), the Active and Archived tabs (Tabs), each row (Button) and its status badge (StatusBadge), the pagination bar (PaginationBar), the empty, loading and error banner (Banner) The plan and customer text, the timestamps, the billing badges and the layout

What changes: your grey badges replace OODS Foundry's tinted status colours, a critical status such as Past Due takes your solid destructive colour, and your pill tabs replace its underline tabs.

In high contrast, OODS Foundry's own parts switch to system colours and your shadcn parts keep their light palette, because shadcn has no high-contrast theme. The high-contrast frames show that as generated.

The project behind these screens

Made with the shadcn CLI's public commands, on the Radix base with Tailwind 4. One edit by hand: a primary colour in light and in dark, so the screens have an accent. The diff is recorded. On 0.7.0, this site also ran the same mapping on a project started on Base UI; its Subscription list mapped, previewed and built the same way. That run wasn't repeated for 0.10.1, and isn't shown here.

npx -y shadcn@4.21.1 init -t vite -b radix -p nova -n shadcn-radix --no-monorepo -y
npx -y shadcn@4.21.1 add button card badge tabs select input label pagination alert -y -o
--- a/src/index.css
+++ b/src/index.css
@@ -55,7 +55,7 @@
     --card-foreground: oklch(0.145 0 0);
     --popover: oklch(1 0 0);
     --popover-foreground: oklch(0.145 0 0);
-    --primary: oklch(0.205 0 0);
+    --primary: oklch(0.55 0.2 262);
     --primary-foreground: oklch(0.985 0 0);
     --secondary: oklch(0.97 0 0);
     --secondary-foreground: oklch(0.205 0 0);
@@ -66,7 +66,7 @@
     --destructive: oklch(0.577 0.245 27.325);
     --border: oklch(0.922 0 0);
     --input: oklch(0.922 0 0);
-    --ring: oklch(0.708 0 0);
+    --ring: oklch(0.55 0.2 262);
     --chart-1: oklch(0.87 0 0);
     --chart-2: oklch(0.556 0 0);
     --chart-3: oklch(0.439 0 0);
@@ -90,7 +90,7 @@
     --card-foreground: oklch(0.985 0 0);
     --popover: oklch(0.205 0 0);
     --popover-foreground: oklch(0.985 0 0);
-    --primary: oklch(0.922 0 0);
+    --primary: oklch(0.7 0.18 262);
     --primary-foreground: oklch(0.205 0 0);
     --secondary: oklch(0.269 0 0);
     --secondary-foreground: oklch(0.985 0 0);
@@ -101,7 +101,7 @@
     --destructive: oklch(0.704 0.191 22.216);
     --border: oklch(1 0 0 / 10%);
     --input: oklch(1 0 0 / 15%);
-    --ring: oklch(0.556 0 0);
+    --ring: oklch(0.7 0.18 262);
     --chart-1: oklch(0.87 0 0);
     --chart-2: oklch(0.556 0 0);
     --chart-3: oklch(0.439 0 0);

One component, inside your project

Instead of a separate app, OODS Foundry can write one generated screen into your project as a component. It imports your adapters by your own alias, declares the props and action callbacks it needs, and leaves the wiring to you. On this site's project, the Subscription detail and list components it wrote passed the project's own build, strict type checks included. For dark, the element around the component needs your dark class as well as OODS Foundry's theme attribute.

What was checked, and what wasn't

Every generated app has a content hash and a receipt. For mapped components the receipt adds a contract report: each obligation OODS Foundry's own component carries is marked met, unmet or not checked for your adapter, with a reason. On these screens Select has 3 unmet obligations and PaginationBar 7, the same in every theme; the other adapters have none unmet. More obligations were not checked than were checked, and the report names each one. The report is advisory. It doesn't refuse generation, and a passing subset isn't full compatibility or an accessibility claim.

Read the report

Your theme, as a starting brand

OODS Foundry can derive a starting brand from your project's theme CSS. It names where each value came from and what it couldn't find, writes nothing until you create the brand, and never writes to your CSS. A default neutral shadcn theme leaves the accent as a gap for you to fill.

This site's call

Its input:

{
  "action": "derive",
  "cssPath": "<shadcn-project>/src/index.css"
}

Its result:

{
  "action": "derive",
  "recipe": {
    "neutralHue": 0,
    "neutralChroma": 0,
    "accentHue": 262,
    "primary": "accent",
    "radius": 10,
    "font": "Geist Variable",
    "status": {
      "critical": {
        "hue": 27.325
      }
    }
  },
  "provenance": {
    "neutralHue": {
      "sources": [
        {
          "path": "--background",
          "value": "oklch(1 0 0)",
          "resolvedValue": "oklch(1 0 0)"
        },
        {
          "path": "--foreground",
          "value": "oklch(0.145 0 0)",
          "resolvedValue": "oklch(0.145 0 0)"
        },
        {
          "path": "--card",
          "value": "oklch(1 0 0)",
          "resolvedValue": "oklch(1 0 0)"
        },
        {
          "path": "--muted",
          "value": "oklch(0.97 0 0)",
          "resolvedValue": "oklch(0.97 0 0)"
        },
        {
          "path": "--border",
          "value": "oklch(0.922 0 0)",
          "resolvedValue": "oklch(0.922 0 0)"
        },
        {
          "path": "--input",
          "value": "oklch(0.922 0 0)",
          "resolvedValue": "oklch(0.922 0 0)"
        }
      ],
      "rule": "Circular median OKLCH hue (cut at the widest gap) of neutral colours with chroma ≤ 0.03."
    },
    "neutralChroma": {
      "sources": [
        {
          "path": "--background",
          "value": "oklch(1 0 0)",
          "resolvedValue": "oklch(1 0 0)"
        },
        {
          "path": "--foreground",
          "value": "oklch(0.145 0 0)",
          "resolvedValue": "oklch(0.145 0 0)"
        },
        {
          "path": "--card",
          "value": "oklch(1 0 0)",
          "resolvedValue": "oklch(1 0 0)"
        },
        {
          "path": "--muted",
          "value": "oklch(0.97 0 0)",
          "resolvedValue": "oklch(0.97 0 0)"
        },
        {
          "path": "--border",
          "value": "oklch(0.922 0 0)",
          "resolvedValue": "oklch(0.922 0 0)"
        },
        {
          "path": "--input",
          "value": "oklch(0.922 0 0)",
          "resolvedValue": "oklch(0.922 0 0)"
        }
      ],
      "rule": "median OKLCH chroma of neutral colours with chroma ≤ 0.03."
    },
    "accentHue": {
      "sources": [
        {
          "path": "--primary",
          "value": "oklch(0.55 0.2 262)",
          "resolvedValue": "oklch(0.55 0.2 262)"
        }
      ],
      "rule": "Chromatic --primary, otherwise chromatic --ring; opaque OKLCH chroma > 0.03."
    },
    "primary": {
      "sources": [
        {
          "path": "--primary",
          "value": "oklch(0.55 0.2 262)",
          "resolvedValue": "oklch(0.55 0.2 262)"
        }
      ],
      "rule": "--primary with OKLCH chroma > 0.03 selects accent; otherwise primary is neutral. No accent is invented."
    },
    "radius": {
      "sources": [
        {
          "path": "--radius",
          "value": "0.625rem",
          "resolvedValue": "0.625rem"
        }
      ],
      "rule": "median dimension in px (rem × 16), clamped to 0–16."
    },
    "font": {
      "sources": [
        {
          "path": "--font-sans",
          "value": "'Geist Variable', sans-serif",
          "resolvedValue": "'Geist Variable', sans-serif"
        }
      ],
      "rule": "First matching fontFamily in document order; first family of a list, stripped of quotes."
    },
    "status.critical.hue": {
      "sources": [
        {
          "path": "--destructive",
          "value": "oklch(0.577 0.245 27.325)",
          "resolvedValue": "oklch(0.577 0.245 27.325)"
        }
      ],
      "rule": "Status colour nearest OKLCH lightness 0.5, preferring 500 or 600; error and danger map to critical."
    }
  },
  "gaps": [
    {
      "field": "fontMono",
      "reason": "No usable --font-mono family, directly or through one var() reference.",
      "candidates": [
        "--font-mono"
      ]
    }
  ],
  "warnings": [
    "--font-sans: only the first font family is used; the recipe generates its fallback stack.",
    "Ignored custom properties: --card-foreground, --popover, --popover-foreground, --primary-foreground, --secondary, --secondary-foreground, --muted-foreground, --accent, --accent-foreground, --chart-1, --chart-2, --chart-3, --chart-4, --chart-5, --sidebar, --sidebar-foreground, --sidebar-primary, --sidebar-primary-foreground, --sidebar-accent, --sidebar-accent-foreground, --sidebar-border, --sidebar-ring. They do not define this recipe."
  ]
}

What 0.10.1 doesn't cover

  • This example uses React, on Radix or Base UI, with Tailwind 4. Yarn PnP, Bun and Turbopack-only dev servers haven't been proven.
  • React Aria projects are refused with a named reason.
  • This site proved one project with npm and Vite. pnpm, a hoisted npm workspace and Next.js App Router rest on the OODS Foundry team's own receipts, not on a run of this site's, and a generated app is a Vite app even when your project is Next.js.
  • The adapters used here install from the package in your node_modules.
  • Deriving a brand from this project's CSS fills OODS Foundry's own slots; it doesn't carry your token names into generated apps.
  • In high contrast your shadcn parts keep their light palette; OODS Foundry's switch to system colours.

OODS Foundry is independent. It is not maintained by or affiliated with shadcn/ui.

Then describe one of your own objects

Start with one object: a subscription, a warehouse, whatever your product is made of. Its fields and traits go in one short file, and the screens come back with your components in them and a receipt of what was checked.

Get started · The quickstart