UI Standalone Consolidation
Status: ✅ Complete · Priority: High · Created: 2025-11-18 · Tags: ui, architecture, simplification
Project: lean-spec
Team: Core Development
Overview
Problem: Current @leanspec/ui tries to package @leanspec/web's Next.js standalone build, which creates symlink and node_modules distribution failures. When users run lean-spec ui via pnpm dlx @leanspec/ui, the published package can't resolve next dependency because:
- Standalone build uses pnpm symlinks that break when packaged
- Symlink rewriting logic is complex and error-prone
- Materializing symlinks hits broken symlink targets
- The two-package separation adds unnecessary indirection
Solution: Merge @leanspec/web directly into @leanspec/ui as a single publishable Next.js app package.
Design
Architecture Changes
Before:
@leanspec/web (workspace-only)
└─> Next.js app with standalone output
@leanspec/ui (published)
└─> CLI wrapper + copies @leanspec/web standalone build
After:
@leanspec/ui (published)
└─> Next.js app + CLI entry point
Implementation Strategy
-
Move all
@leanspec/websource to@leanspec/ui:packages/ui/src/← all web app sourcepackages/ui/public/← static assetspackages/ui/next.config.ts, etc.
-
Update
@leanspec/ui/package.json:- Add Next.js dependencies
- Keep existing CLI bin entry
- Add Next.js build script
- Set
output: "standalone"in Next config
-
Simplify CLI launcher (
packages/ui/bin/ui.js):- Production: Just run
node dist/standalone/server.js - No complex copying or symlink rewriting
- Dependencies bundled by Next.js standalone output
- Production: Just run
-
Update monorepo references:
- Remove
@leanspec/webfrom workspace - Update
lean-spec ui --devto use local@leanspec/ui - Update build pipelines
- Remove
Dev vs Prod Modes
Dev mode (monorepo): lean-spec ui --dev
- Runs
next devdirectly inpackages/ui - No standalone build needed
Prod mode (published): npx @leanspec/ui or lean-spec ui
- Runs pre-built standalone server
- All dependencies bundled by Next.js
Plan
- Create
packages/ui/src/app/and move all web app source - Move
next.config.ts,tailwind.config.ts, etc. topackages/ui/ - Update
packages/ui/package.jsonwith Next.js deps - Simplify
packages/ui/bin/ui.jslauncher - Remove
packages/ui/scripts/prepare-dist.mjscomplexity - Update
packages/cli/src/commands/ui.tsfor new structure - Update monorepo build scripts
- Archive/remove
packages/web/ - Test
pnpm dlx @leanspec/uiflow - Update documentation
Test
-
lean-spec ui --devworks in monorepo -
pnpm packproduces valid tarball -
pnpm dlx file:./tarballsuccessfully launches UI - Published
@leanspec/uiresolves all dependencies - No "Cannot find module 'next'" errors
- Ctrl+C/Ctrl+D stop the UI cleanly (from earlier fix)
- UI connects to filesystem specs correctly
Notes
Rationale: The two-package split was premature optimization. Next.js standalone output is designed to be self-contained and portable. Trying to repackage it breaks that model. By making @leanspec/ui the Next.js app itself, we leverage Next.js's built-in bundling and eliminate all symlink/node_modules issues.
Breaking Changes: None for users. The lean-spec ui command and npx @leanspec/ui usage remain identical. Only internal package structure changes.