Build Troubleshooting
Status: Canonical, 2026-04-28 Scope: Build failures across the monorepo (root packages, docs site, demo surfaces, test app). Companion:
docs/maintenance/CI_BASELINE_AUDIT.md,docs/maintenance/DEMO_SURFACES_AUDIT.md,docs/security/SECURITY_AUDIT_REPORT.md.
Purpose
This page is the canonical reference for build problems and fixes
in Smolitux-UI. It consolidates the previous build-fix-guide.md and
the earlier build-troubleshooting.md into one problem-driven reference.
If you hit a build error, look it up here. If your error isn't listed, match the closest pattern under §"Common failures and fixes" first; fall through to §"General recovery procedures" only if no specific pattern fits.
Current baseline
The repo is configured as an npm workspaces monorepo (npm 10.x +
Node 20+). Builds use tsup for the @smolitux/* packages and
vite for the example surfaces. A separate Docusaurus build lives
under docs/.
Required toolchain:
- Node.js 20+ (see
.nvmrc). - npm 10.x (workspaces support).
- Git.
Authoritative configuration:
- Root
package.jsondeclares the workspaces and the top-levelbuild,lint,test,security:*scripts. - Each
packages/@smolitux/<name>/package.jsondeclares its ownbuildscript usingtsup. - TypeScript configs follow a
tsconfig.base.jsonpattern, with per-packagetsconfig.jsonfiles extending it. - The runtime dependency allowlist is enforced by
scripts/security/check-runtime-dependencies.mjs(rootnpm run security:runtime-deps).
Common build commands
| Command | What it does |
|---|---|
npm run build | Builds the canonical set of @smolitux/* packages (utils, theme, core) used by the rest of the monorepo. |
npm run lint | Lints all workspaces with the flat ESLint config. |
npm run test | Runs the Jest test suites. |
npm run security:runtime-deps | Verifies no new external runtime dependencies have been introduced (allowlist gate). |
npm run security:audit | Runs npm audit --audit-level=high against the root lockfile. |
cd docs && npm ci && npm run build | Builds the Docusaurus documentation site. |
cd examples/<demo> && npm install && npm run build | Builds a demo surface (basic-app, showcase-app). |
cd packages/playground/src && npm ci && npm run build | Builds the playground surface. |
Known build requirements
- The
@smolitux/chartspackage'smodulefield points atdist/index.mjs(the actualtsupESM output); make sure your package builds emit that file, notdist/index.esm.js. - The
examples/{basic-app,showcase-app}andtest-app/workspaces consume@smolitux/*viafile:../../packages/@smolitux/<name>refs. They do not consume tarballs from the repo root. - The Docusaurus site uses
defaultLocale: 'de'withlocales: ['de']only. There is noi18n/en/translation tree at the moment.
Common failures and fixes
TypeScript: Cannot find base config file "../../../../tsconfig.base.json"
A package's tsconfig.json references a base config relative path
that doesn't resolve.
Fix: correct the relative path to the canonical
tsconfig.base.json at the repo root, or extend per-package via
the local tsconfig.template.json. Example for a deep workspace:
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
}
TypeScript: duplicate / ambiguous re-exports
error TS2308: Module './components' has already exported a member
named 'ButtonSize'.
Two barrels re-export the same symbol without disambiguation.
Fix options:
// 1. Namespaced re-exports
import * as Components from './components';
import * as Types from './types';
export { Components, Types };
// 2. Or split the source so each symbol has exactly one home
// In types/index.ts
export * from './common/style';
export * from './common/responsive';
// In components/index.ts
export * from './primitives';
export * from './patterns';
TypeScript: incompatible forwardRef types between primitive and styled element
error TS2322: Type 'ForwardedRef<HTMLButtonElement>' is not assignable
to type 'LegacyRef<HTMLDivElement> | undefined'.
A polymorphic component is rendering as a different element type than
its forwardRef-d prop signature.
Fix: narrow the ref signature, or cast at the call site:
<Box
as="button"
ref={ref as React.Ref<HTMLDivElement>}
/>
TypeScript: type-inference fights against design-token shape
error TS2352: Conversion of type 'string' to type
'500 | 100 | 400 | …' may be a mistake because neither type
sufficiently overlaps with the other.
Fix: widen the lookup type at the boundary, or define a more flexible color palette interface:
const colorObj = colors[colorName as keyof typeof colors];
if (!colorObj) return color;
return (colorObj as Record<string, string>)[colorShade] || color;
interface ColorPalette {
[key: string]: { [shade: string]: string };
}
export const colors: ColorPalette = { /* … */ };
Package resolution: npm error 404 Not Found - GET https://registry.npmjs.org/@smolitux%2fcore
A consumer is trying to install @smolitux/<n> from the npm
registry, but the package has not been published there.
Fix: consumers under examples/, test-app/, and
packages/playground/src/ use file: references to the workspace
packages, e.g.:
"@smolitux/core": "file:../../packages/@smolitux/core"
If a downstream app needs a tarball, build it locally via the
package's own build script and reference the produced dist/.
Vite / rollup: Failed to resolve entry for package "@smolitux/<name>"
The linked workspace package has no built dist/, so package.json
fields (main, module, types) point at non-existent files.
Fix: build the package first:
npm run build --workspace=@smolitux/<name>
For chart-related failures, verify that
packages/@smolitux/charts/package.json's module field points at
dist/index.mjs (the actual tsup output) and not at
dist/index.esm.js (which tsup does not emit).
Test runs: useTheme must be used within a ThemeProvider
Components consuming useTheme are tested in isolation.
Fix: wrap the rendered tree in a ThemeProvider inside the
test, or supply a mock for useTheme. The shared helpers in
test-utils/ carry a default ThemeProvider-wrapped renderer for
this purpose.
Docs build: No docs found in "<dirName>": can't auto-generate a sidebar
A Docusaurus sidebar declares an autogenerated entry whose
dirName doesn't exist under the active docs source.
Fix: the wiki sidebar (docs/sidebars.ts) and the guide-plugin
sidebar (docs/sidebars.guide.ts) are kept in separate files
so that each docs source only evaluates its own sidebar entries.
If you add a new docs source, give it its own sidebar file and
wire it through docusaurus.config.ts sidebarPath.
Docs build: Duplicate routes found! /smolitux-ui/en/
The Docusaurus i18n config declares a non-default locale that has
no translation tree under i18n/<locale>/.
Fix: keep locales: ['de'] until an actual translation tree
lands. Re-add 'en' only when docs/i18n/en/... exists.
Surface-specific notes
Root packages (packages/@smolitux/*)
npm run build at the repo root builds the canonical set
(utils, theme, core). For a single package, run
npm run build --workspace=@smolitux/<name>.
Docs site (docs/)
cd docs && npm ci && npm run build. Should emit zero warnings.
Two pre-existing warnings (No docs found in "api", duplicate
/en/ route) were eliminated in PR #642 and the warnings
shouldn't return without re-introducing them.
Demo surfaces (examples/basic-app, examples/showcase-app)
Each demo has its own package.json + package-lock.json and
consumes @smolitux/* via file: refs to ../../packages/@smolitux/<name>.
See docs/maintenance/DEMO_SURFACES_AUDIT.md for
the running history of demo-surface fixes.
Playground (packages/playground/src)
cd packages/playground/src && npm ci && npm run typecheck && npm run lint && npm run build.
The typecheck step is scoped narrowly so it doesn't walk into
aliased package sources.
Test app (test-app/)
cd test-app && npm install && npm run build. The test-app is not
a CI gate; it is an integration harness. As of PR #637 it consumes
@smolitux/* via file: refs (no tarballs).
General recovery procedures
When a specific failure pattern doesn't apply, fall back to one of these in order:
1. Stepwise package build
Build packages in dependency order so each layer has the prior
layer's dist/ available:
npm run build --workspace=@smolitux/utils
npm run build --workspace=@smolitux/theme
npm run build --workspace=@smolitux/core
# then any consumer package
2. Clean reinstall
rm -rf node_modules package-lock.json
npm install
npm run build
For a per-surface reinstall (e.g. showcase-app):
cd examples/showcase-app
rm -rf node_modules package-lock.json
npm install
npm run build
3. Type-only check
npx tsc --noEmit
This isolates type errors from bundler errors.
4. Verify the workspace graph
npm ls --workspaces --depth=0
Reveals missing or mis-resolved workspace links.
Security and audit checks
After any non-trivial build change, run:
npm run security:runtime-deps # runtime dependency allowlist
npm run security:audit # npm audit --audit-level=high
Both must exit 0 before opening a PR. The runtime dependency
allowlist gate prevents accidental introduction of new external
runtime dependencies; the audit gate is enforced by CI.
When not to fix in-place
A build error is sometimes a symptom of a wider structural issue. Don't paper over it locally if any of these apply:
- The fix would require touching a publishable
packages/@smolitux/*runtime package and the PR scope forbids it. Open a separate PR with the appropriate scope. - The fix would change a public API or a design token. Route
through an ADR per
docs/architecture/CORE_PUBLIC_API_BLUEPRINT.md§6. - The fix is a stale-build artifact (e.g. someone built a package before a refactor and the dist is now wrong). Rebuild from clean rather than amending the dist.
Related docs
docs/architecture/CORE_PUBLIC_API_BLUEPRINT.md— public API governance.docs/maintenance/CI_BASELINE_AUDIT.md— current CI gates.docs/maintenance/DEMO_SURFACES_AUDIT.md— history of demo-surface build fixes.docs/security/SECURITY_AUDIT_REPORT.md— security audit ledger.docs/maintenance/DOCUMENTATION_CONSOLIDATION_PLAN.md— documentation consolidation plan.
Note on the previous content
The previous build-fix-guide.md was a step-by-step recovery runbook
for a specific historical broken state (early-2025 lerna +
@smolitux/utils types stub creation). Most of that runbook no
longer applies — the repository now uses npm workspaces, ships the
referenced types, and builds with tsup. The reusable parts of that
guide (clean reinstall, stepwise build, recovery commands) are
folded into §"General recovery procedures" above. The original
remains in git history (and as a redirect file at
docs/wiki/development/build-fix-guide.md).