Catalyzer
Architecture

UI Package

Design system primitives, global styles, and theme infrastructure.

The design system layer. shadcn/ui components, Tailwind themes, global styles, and the cn() utility. Both apps/native and apps/web consume this package for visual primitives.

Directory Structure

button.tsx, card.tsx, command.tsx, dialog.tsx, drawer.tsx, tabs.tsx, ... (25+ primitives)

Components

25+ shadcn/ui components (radix-vega style) in the root of src/components/:

avatar, breadcrumb, button, card, collapsible, command, dialog, drawer, dropdown-menu, input, input-group, kbd, label, radio-group, scroll-area, select, separator, sheet, sidebar, skeleton, sonner, tabs, textarea, tooltip

Most are built on Radix UI primitives. Exceptions: card, input, breadcrumb (native HTML), skeleton (CSS animation), sidebar (custom compound component), command (cmdk), drawer (vaul), sonner (toast library).

Hooks

HookWhat it does
use-mobile.tsReturns true below the mobile breakpoint (required by sidebar.tsx)

Utilities

FileWhat it provides
utils.tscn() — Tailwind class merge utility (clsx + tailwind-merge)

Exports

Wildcard exports in package.json. No barrel files.

package.json (exports)
{
  "./globals.css": "./src/styles/globals.css",
  "./postcss.config": "./postcss.config.mjs",
  "./components/*": "./src/components/*.tsx",
  "./lib/*": "./src/lib/*.ts",
  "./hooks/*": "./src/hooks/*.ts"
}
// Usage
import { Button } from "@workspace/ui/components/button";
import { Sidebar } from "@workspace/ui/components/sidebar";
import { cn } from "@workspace/ui/lib/utils";

Direct path imports (no barrel index). Tree-shaking works out of the box and circular dependency issues are avoided.

Global Styles

packages/ui/src/styles/globals.css
@import "tailwindcss";
@import "tw-animate-css";
@import "./themes.css";

@source "../../../../apps/**/*.{ts,tsx}";
@source "../../../core/src/**/*.{ts,tsx}";
@source "../**/*.{ts,tsx}";

@custom-variant dark (&:is(.dark *));

The @source directives tell Tailwind to scan the UI package, the core package, and all apps for class usage. Both apps import this stylesheet via @workspace/ui/globals.css.

Don't create separate Tailwind entry points in the apps. Use the shared globals.css so all workspaces share the same design tokens and utilities.

On this page