Keep runtime assets available in Next.js and Workflow server bundles.
Next.js uses @vercel/nft during production builds to emit an .nft.json file for every server route. Each trace lists the files that must be available when that route runs in a Vercel function or another minimal deployment.
Every CentraKit app passes the repository root to the shared config factory as outputFileTracingRoot. This is explicit even though Next.js can infer the same root from the workspace lockfile.
The explicit root is required for two repository conventions:
node_modules/.pnpm/ directory.Do not move the root back to an inferred default. A lockfile or build invocation change could otherwise make valid workspace dependencies fall outside the trace.
Normal static import, require, and recognizable fs calls should be left to nft. Add outputFileTracingIncludes only when runtime code deliberately prevents static discovery, or when a deployment treats the file separately from the server function.
Current examples:
apps/api/public/openapi.json at request time. Vercel serves public/ separately, so /api/mcp explicitly includes the file in its function trace.CHANGELOG.md files outside apps/docs. Its server traces include those sibling files.zxing_reader.wasm.Include keys are route globs and include values are resolved from the app directory, not the monorepo root. Keep both as narrow as possible. Fully static routes do not produce server trace files, so includes do not apply to them.
@react-pdf/renderer and qrcode stay in serverExternalPackages. Their runtime require graphs are visible to nft, and the monorepo tracing root lets nft follow those graphs into pnpm's store. Do not add a broad PDF package include unless a build trace proves a required asset is missing.
Workflow v5 owns transpilation for workflow and @workflow/*; do not add those packages to serverExternalPackages. withWorkflow generates app/.well-known/workflow/v1/flow/route.js, which Next.js traces like any other server route. Step-only imports therefore belong in the flow trace, including React PDF when an invoice or quote step renders a document.
Keep app/.well-known/workflow/** in apps/saas/turbo.json and apps/api/turbo.json build outputs
(Workflow SDK Turborepo caching).
Local builds resolve @workflow/world-local; Vercel builds resolve @workflow/world-vercel.
Because both services ship Workflow consumers in one Vercel project, pin distinct
WORKFLOW_QUEUE_NAMESPACE values (saas / api) so queue topics become __saas_wkf_workflow_*
and __api_wkf_workflow_* instead of colliding on __wkf_workflow_* / consumer default.
Only exclude a package when the server can never execute it. Streamdown performs syntax highlighting during SSR, so Shiki language and theme assets are real server dependencies and must not be excluded.
CentraKit instead overrides @streamdown/code to the catalog Shiki version. This prevents pnpm and nft from carrying two complete grammar bundles while preserving server-side highlighting.
Build the traced apps and run the regression guard:
pnpm test:tracingThe task builds all five Next.js apps, then checks:
outputFileTracingRoot;The guard lives in tests/build/output-file-tracing.test.ts. It resolves every path relative to its .nft.json file, matching Next.js trace semantics. For manual investigation, inspect:
apps/<app>/.next/required-server-files.json for the serialized tracing configuration;apps/<app>/.next/server/app/**/route.js.nft.json for route dependencies;apps/saas/.next/server/app/.well-known/workflow/v1/flow/route.js.nft.json for the combined Workflow step bundle.