The stack is Next.js + TypeScript + Tailwind + Radix
Dialog, DropdownMenu, etc.) are used ad hoc across apps/packages.className, another wraps Radix with local variants; discriminated unions and slot patterns are inconsistent.Introduce shadcn/ui not as “another UI library,” but as a codified component boundary: copy-in components that wrap Radix + Tailwind with stable props, variants, and composition slots—aligned with your monorepo and design system.
Success looks like: fewer one-off wrappers, predictable APIs, faster feature work, safer refactors, and a single place to evolve tokens and interaction patterns.
components.json, aliases, Tailwind theme extensions).Button, Input, Dialog, DropdownMenu, Form (often paired with react-hook-form + zod).class-variance-authority (CVA) or tailwind-variants so visual states are data (variant, size) not string soup.components/ui/* as internal SDK: apps import from @/components/ui/... (or package path), not from Radix directly except inside those files.asChild + Slot patterns are typed once. Form field errors bind to schema types end-to-end (zod → inferred types → field components).