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 -> CRASHRoot 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 guaranteedComplex Build Failures (CSS, Types, Dependencies)
Symptoms
- Build passes locally but fails on Vercel with generic "Webpack errors".
- Errors pointing to
globals.cssorcss-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.Turbo reads the dependency graph from
turbo.json - 2.Sees that web depends on design-system (via
dependsOn: ["^build"]) - 3.Builds
@thesage/uifirst (runs tsup to generate dist files) - 4.Then builds
@ecosystem/web(runs next build)
Preventing This Issue
- •Always use
turbodirectly 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:
- Component source:
packages/ui/src/components/[category]/Component.tsx - Built to:
packages/ui/dist/index.mjs(via tsup) - Exported by:
packages/ui/package.jsonexports field - Imported by:
component-registry.tsxfrom '@thesage/ui' - Rendered in: Studio app examples
How to Diagnose
- 1.Verify source code has your changes: Check the actual .tsx component file
- 2.Check local dist build has changes:
grep "your-change" packages/ui/dist/index.mjs - 3.Verify examples import correctly: Check component-registry.tsx imports from '@thesage/ui'
- 4.If all above check out → It's a deployment build issue, not a code issue
Solution
- 1.
Ensure vercel.json uses turbo build:
{ "buildCommand": "turbo build --filter=@ecosystem/web", "installCommand": "pnpm install --frozen-lockfile" } - 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.Build locally to verify:
pnpm build --filter=@thesage/ui - 4.Push changes:
git push - 5.Clear Vercel build cache: Project Settings → Clear Cache
- 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