import type { NextConfig } from "next"; import path from "path"; import { fileURLToPath } from "url"; import { withSentryConfig } from "@sentry/nextjs"; // This app lives in vibn-frontend; a lockfile under $HOME can make Turbopack pick the wrong root // and hydrate with a mismatched client bundle (e.g. different JustineNav markup). const turbopackRoot = path.dirname(fileURLToPath(import.meta.url)); // Google OAuth on localhost: NextAuth must build the same callback URL Google expects. // If NEXTAUTH_URL is unset in dev, default it (set explicitly if you use 127.0.0.1 or another port). if ( process.env.NODE_ENV === "development" && !process.env.NEXTAUTH_URL?.trim() ) { process.env.NEXTAUTH_URL = "http://localhost:3000"; } const nextConfig: NextConfig = { turbopack: { root: turbopackRoot, }, output: "standalone", // ssh2 ships native .node binaries; turbopack can't bundle them // ("non-ecmascript placeable asset"). Externalize so they're loaded // at runtime via Node's require, the same way @prisma/client works. serverExternalPackages: [ "@prisma/client", "prisma", "ssh2", "cpu-features", "pdf-parse", // Prevents Turbopack from bundling these packages and hitting the // import-in-the-middle version mismatch warning on every request. // Both ship a nested @opentelemetry/instrumentation@0.212 that wants // iitm@2.x, but the project root has iitm@3.x. "@fastify/otel", "@prisma/instrumentation", ], // react-markdown and its entire unified/remark/rehype ecosystem are // ESM-only (type:"module", no CJS fallback). Next.js webpack can't // resolve them without explicit transpilation — manifests as // "TypeError: Cannot read properties of undefined (reading 'z')" in // the minified production bundle. transpilePackages: [ "react-markdown", "remark-gfm", "remark-parse", "remark-rehype", "unified", "vfile", "vfile-message", "mdast-util-from-markdown", "mdast-util-to-markdown", "mdast-util-gfm", "mdast-util-gfm-table", "mdast-util-gfm-task-list-item", "mdast-util-gfm-strikethrough", "mdast-util-gfm-autolink-literal", "mdast-util-gfm-footnote", "micromark", "micromark-core-commonmark", "micromark-extension-gfm", "micromark-util-combine-extensions", "micromark-util-character", "micromark-util-chunked", "micromark-util-classify-character", "micromark-util-decode-string", "micromark-util-encode", "micromark-util-html-tag-name", "micromark-util-normalize-identifier", "micromark-util-resolve-all", "micromark-util-sanitize-uri", "micromark-util-subtokenize", "micromark-util-types", "micromark-util-symbol", "micromark-util-decode-numeric-character-reference", "hast-util-to-jsx-runtime", "hast-util-whitespace", "hast-util-from-parse5", "property-information", "space-separated-tokens", "comma-separated-tokens", "decode-named-character-reference", "character-entities", "unist-util-position", "unist-util-stringify-position", "unist-util-visit", "unist-util-is", ], typescript: { ignoreBuildErrors: true, }, }; // Wrap with Sentry: uploads source maps on every Coolify build so the // minified prod stack traces (TypeError: reading 'z' / 'j' / 'aa' etc.) // arrive in the dashboard already de-minified. Auth token is set in // Coolify env (SENTRY_AUTH_TOKEN); without it the wrapper still works // at runtime but skips source map upload at build time. export default withSentryConfig(nextConfig, { org: "vibnai", project: "vibn-ai", // Verbose during beta: we want to *see* "Bundles uploaded: N" in // Coolify's build log so we know source maps are flowing. Flip // back to `!process.env.CI` once we trust it. silent: false, // Upload source maps for every client chunk (incl. those in // unrelated dirs like node_modules); we want full coverage so // production stack traces are de-minified end to end. SDK v10 // deletes the public source maps after upload by default, so // they're only readable inside Sentry. widenClientFileUpload: true, // Prevents ad-blockers from killing client error events. Routes // them through /monitoring on our domain instead of sentry.io. tunnelRoute: "/monitoring", // Disable telemetry pings from the build wrapper itself. telemetry: false, // Don't fail the build if source map upload fails (e.g. token // missing in a preview build); errors will still capture, they // just won't be de-minified. errorHandler: (err) => { console.warn("Sentry source map upload skipped:", err.message); }, });