Sofondo
SofondoFrameworkDocs

Build System Notes - Phase 3

Current Status

Development Build ✅

  • Status: Fully functional
  • Build tool: Turbopack (via npm run dev)
  • Startup time: ~500ms
  • Hot reload: Working
  • Package resolution: Symlinked packages work perfectly

Production Build ❌

  • Status: Blocked by Turbopack limitation
  • Build tool: Turbopack (via npm run build)
  • Issue: Turbopack cannot resolve symlinked packages (file: protocol dependencies) in production builds
  • Error: “Module not found: Can’t resolve ‘@sofondo/core’” (and similar for other framework packages)

Technical Analysis

The Problem

Next.js 16 uses Turbopack as the default bundler for both development and production builds. While Turbopack handles symlinked packages fine in development mode, it fails to resolve them during production builds.

The platform uses file: protocol dependencies in package.json:

{
  "dependencies": {
    "@sofondo/core": "file:../sofondo-monorepo/packages/core",
    "@sofondo/react": "file:../sofondo-monorepo/packages/react",
    "@sofondo/styles": "file:../sofondo-monorepo/packages/styles"
  }
}

These create symlinks in node_modules/@sofondo/* pointing to the monorepo packages. Turbopack’s production bundler cannot follow these symlinks properly.

Why Webpack Doesn’t Help

  • Next.js 16 has Turbopack as the only production bundler
  • The TURBOPACK=0 environment variable is ignored during builds
  • There is no --no-turbopack flag for next build
  • Webpack is no longer available as a production build option in Next.js 16

Solutions

When to use: Production releases, public/private npm packages

Pros:

  • Standard npm workflow
  • Works with all build tools
  • Easy for external consumers
  • Semantic versioning
  • Can be private or public

Cons:

  • Requires publishing step
  • Version management overhead
  • Need npm account/organization

Implementation:

# In monorepo
cd packages/core && npm publish --access restricted
cd packages/react && npm publish --access restricted
cd packages/styles && npm publish --access restricted

# In platform, update package.json
{
  "dependencies": {
    "@sofondo/core": "^0.1.0",
    "@sofondo/react": "^0.1.0",
    "@sofondo/styles": "^0.1.0"
  }
}

When to use: Private packages during development, team collaboration

Pros:

  • Free for private repos
  • Git-based workflow
  • No need for npm account
  • Automated with GitHub Actions

Cons:

  • Requires GitHub authentication
  • Slightly more setup than npm

Implementation:

  1. Add .npmrc to monorepo root:
@sofondo:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
  1. Update package.json in each package:
{
  "publishConfig": {
    "registry": "https://npm.pkg.github.com/@sofondo"
  }
}
  1. Publish packages:
npm publish
  1. Update platform dependencies to use versions instead of file:

Solution 3: Local Verdaccio Registry

When to use: Local development, testing publish workflow

Pros:

  • Local npm registry
  • No external dependencies
  • Test publish process
  • Fast

Cons:

  • Extra service to run
  • Not suitable for production
  • Need to configure registry

Implementation:

# Install and run Verdaccio
npm install -g verdaccio
verdaccio

# Configure npm to use local registry
npm set registry http://localhost:4873

# Publish packages
cd packages/core && npm publish

When to use: Local development when symlinks don’t work

Pros:

  • Copies files instead of symlinking
  • Works with all bundlers
  • Simple workflow
  • No registry needed

Cons:

  • Manual update step
  • Not real-time like symlinks
  • Extra tool dependency

Implementation:

# Install yalc
npm install -g yalc

# In monorepo packages
cd packages/core && yalc publish
cd packages/react && yalc publish
cd packages/styles && yalc publish

# In platform
yalc add @sofondo/core @sofondo/react @sofondo/styles

# After changes to framework
cd packages/core && yalc push

Solution 5: Move Platform into Monorepo (Long-term)

When to use: When ready to consolidate

Pros:

  • Single repo for everything
  • No symlink/registry issues
  • Shared tooling
  • Easier version management

Cons:

  • Larger repo
  • Different workflow
  • Migration effort

Implementation: Move sofondo-platform to sofondo-monorepo/apps/platform and update Turborepo config to include apps.

Recommendations

For Current Development (Phase 3)

  1. Keep using symlinks for development - Works perfectly with npm run dev
  2. Accept production build limitation for now - Focus on feature development
  3. Document the limitation - Make it clear in README

For Next Steps (Phase 4+)

  1. Set up GitHub Packages - Enables production builds and team collaboration
  2. Add publish workflow - Automate with GitHub Actions
  3. Version management - Use changesets or similar tool

For v1.0 Release

  1. Publish to npm - Public or private depending on strategy
  2. Semantic versioning - Follow semver strictly
  3. Migration guide - Help users upgrade

Current Workarounds

Until we implement one of the solutions above:

  1. Development: Use npm run dev - works perfectly ✅
  2. Testing: Manual testing in dev mode
  3. Deployment: Not applicable yet (early development phase)

Next Steps for Phase 3

Since production builds are blocked by Turbopack, we’ll focus on:

  1. ✅ Document build system (this file)
  2. ⏭️ Review Turborepo caching configuration
  3. ⏭️ Analyze dev mode bundle sizes
  4. ⏭️ Optimize development experience
  5. ⏭️ Plan registry/publish strategy

References