Adding Components

Step-by-step workflows for extending the design system

Troubleshooting

Error: Cannot read properties of undefined (reading 'track')

Problem

The component breaks the entire page with a runtime error when rendering styles based on a prop (e.g., size).

// Error encountered in Switch.tsx
const { track } = sizes[size]; // size is undefined or invalid -> CRASH

Root Cause

This usually happens when a prop is passed as undefined (despite TypeScript types) or an invalid string value, and used directly as a key to access an object without validation. In compiled JS, this results in trying to access a property on undefined.

Solution

Always validate keys before using them to access style objects. Implement a "safeguard" or fallback mechanism.

Robust Implementation:

// Design pattern for safe property access
const safeSize = (size && sizes[size]) ? size : 'md';
const { track } = sizes[safeSize]; // Safe access guaranteed

Complex Build Failures (CSS, Types, Dependencies)

Symptoms

  • Build passes locally but fails on Vercel with generic "Webpack errors".
  • Errors pointing to globals.css or css-loader.
  • TypeScript errors like TS2742: The inferred type cannot be named.

Solutions

1. Fix Phantom Dependencies

If a config file (e.g., tailwind.config.ts) imports a workspace package, it MUST be listed in devDependencies.

// package.json in the app
"devDependencies": {
  // Tailwind config is bundled within @thesage/ui
}

2. Simplify CSS

Strict build environments may fail on experimental CSS (like font-named-instance) or complex variable font ranges (200 700). Use standard syntax.

3. Explicit Type Annotations

For library re-exports, explicit types prevent portability issues.

// Instead of: const Form = FormProvider;
// Use:
const Form: typeof FormProvider = FormProvider;

4. Allow Build Scripts

Ensure binaries like esbuild are allowed to run.

// Root package.json
"pnpm": {
  "onlyBuiltDependencies": ["esbuild", "sharp"]
}

Vercel Build Failures in Monorepo

Problem

Vercel build fails with error: error: unknown option '--filter=...'

> @ecosystem/web@0.1.0 build
> next build --filter=@ecosystem/web
error: unknown option '--filter=@ecosystem/web'
ELIFECYCLE Command failed with exit code 1.

Root Cause

When using pnpm build --filter=... in vercel.json, Vercel runs the build script from package.json and appends the filter flag. This results in next build --filter=..., but Next.js doesn't recognize the --filter flag (it's a Turborepo flag).

Incorrect (runs through package.json):

{
  "buildCommand": "pnpm build --filter=@ecosystem/web"
}

Solution

Use turbo build directly instead of pnpm build. This invokes Turborepo's build orchestration, which will build the design-system package first, then the app.

Correct (runs turbo directly):

{
  "buildCommand": "turbo build --filter=@ecosystem/web",
  "installCommand": "pnpm install --frozen-lockfile"
}

How It Works

  1. 1.Turbo reads the dependency graph from turbo.json
  2. 2.Sees that web depends on design-system (via dependsOn: ["^build"])
  3. 3.Builds @thesage/ui first (runs tsup to generate dist files)
  4. 4.Then builds @ecosystem/web (runs next build)

Preventing This Issue

  • Always use turbo directly for monorepo builds in Vercel
  • Test the vercel.json buildCommand locally before deploying
  • Remember: pnpm [script] looks for package.json scripts, turbo [task] uses Turborepo

Vercel Build Command Failure (Modules Not Found)

Problem

  • Build fails immediately on Vercel but works locally.
  • Error: Module not found: Can't resolve '@thesage/tokens' (or similar workspace package).

Root Cause

The default Vercel build command (or a simple next build) builds only the app. It does not automatically build the upstream workspace dependencies (like design-system or tokens) that the app depends on.

Because the upstream dist/ files don't exist in the CI environment, the app build crashes when trying to resolve them.

Solution

Update the Build Command in Vercel settings to use Turborepo with the dependency-inclusive filter syntax (...).

Correct Build Command:

pnpm turbo build --filter=creative-powerup...

The ... suffix tells Turbo to "build this package AND all its dependencies first".

Component Changes Not Appearing on Deployed Site

Problem

You've updated a component in the design-system package (e.g., Breadcrumbs hover states), but the changes don't appear on the deployed site, even after committing and pushing.

Root Cause

The examples in the studio app DO pull from the actual component code via imports. The issue is that Vercel isn't rebuilding the design-system package properly, so it's using stale dist files from a previous build.

Understanding the Build Chain:

  1. Component source: packages/ui/src/components/[category]/Component.tsx
  2. Built to: packages/ui/dist/index.mjs (via tsup)
  3. Exported by: packages/ui/package.json exports field
  4. Imported by: component-registry.tsx from '@thesage/ui'
  5. Rendered in: Studio app examples

How to Diagnose

  1. 1.Verify source code has your changes: Check the actual .tsx component file
  2. 2.Check local dist build has changes: grep "your-change" packages/ui/dist/index.mjs
  3. 3.Verify examples import correctly: Check component-registry.tsx imports from '@thesage/ui'
  4. 4.If all above check out → It's a deployment build issue, not a code issue

Solution

  1. 1.

    Ensure vercel.json uses turbo build:

    {
      "buildCommand": "turbo build --filter=@ecosystem/web",
      "installCommand": "pnpm install --frozen-lockfile"
    }
  2. 2.

    Ensure package.json exports dist files:

    "exports": {
      ".": {
        "types": "./dist/index.d.ts",
        "import": "./dist/index.mjs",
        "require": "./dist/index.js",
        "default": "./dist/index.js"
      }
    }
  3. 3.Build locally to verify: pnpm build --filter=@thesage/ui
  4. 4.Push changes: git push
  5. 5.Clear Vercel build cache: Project Settings → Clear Cache
  6. 6.Redeploy in Vercel

Preventing This Issue

  • Always rebuild design-system locally after component changes
  • Verify dist files contain your changes before pushing
  • Remember: Examples use real components, not hardcoded props
  • If source is correct but deployed site is wrong → It's always a build/deployment issue