import type { NextConfig } from "next"; const securityHeaders = [ { key: 'X-Content-Type-Options', value: 'nosniff' }, { key: 'X-Frame-Options', value: 'SAMEORIGIN' }, { key: 'Content-Security-Policy', value: "frame-ancestors 'self' https://*.huggingface.co https://huggingface.co", }, { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' }, { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' }, { key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload', }, ]; const computeMode = (process.env.COMPUTE_MODE || 'local').trim().toLowerCase(); const computeDisabled = computeMode === 'none'; const serverExternalPackages = [ '@napi-rs/canvas', 'ffmpeg-static', 'better-sqlite3', ...(computeDisabled ? [] : ['onnxruntime-node', '@huggingface/tokenizers']), ]; const nextConfig: NextConfig = { async headers() { return [ { // Apply security headers to all routes source: '/(.*)', headers: securityHeaders, }, ]; }, turbopack: { resolveAlias: { canvas: '@napi-rs/canvas', }, }, serverExternalPackages, outputFileTracingIncludes: { '/api/audiobook': [ './node_modules/ffmpeg-static/ffmpeg', ], '/api/audiobook/chapter': [ './node_modules/ffmpeg-static/ffmpeg', ], '/api/tts/segments/ensure': [ './node_modules/ffmpeg-static/ffmpeg', ], '/api/documents/blob/preview/ensure': [ './node_modules/pdfjs-dist/legacy/build/pdf.worker.mjs', ], '/api/documents/blob/preview/presign': [ './node_modules/pdfjs-dist/legacy/build/pdf.worker.mjs', ], '/api/documents/blob/preview/fallback': [ './node_modules/pdfjs-dist/legacy/build/pdf.worker.mjs', ], }, ...(computeDisabled ? { outputFileTracingExcludes: { '/*': [ './node_modules/onnxruntime-node/**/*', './node_modules/@huggingface/tokenizers/**/*', ], }, } : {}), }; export default nextConfig;