| /** @type {import('next').NextConfig} */ | |
| const nextConfig = { | |
| reactStrictMode: true, | |
| swcMinify: true, | |
| env: { | |
| NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000', | |
| }, | |
| // Enable experimental features for better performance | |
| experimental: { | |
| optimizePackageImports: ['lucide-react', '@radix-ui/react-icons'], | |
| }, | |
| // Image optimization | |
| images: { | |
| remotePatterns: [ | |
| { | |
| protocol: 'https', | |
| hostname: 'res.cloudinary.com', | |
| }, | |
| ], | |
| }, | |
| // Webpack configuration | |
| webpack: (config) => { | |
| config.externals = [...(config.externals || []), { canvas: 'canvas' }]; | |
| // Handle Windows case sensitivity issues | |
| config.resolve.symlinks = false; | |
| config.snapshot = { | |
| ...config.snapshot, | |
| managedPaths: [/^(.+?[\\/]node_modules[\\/])/], | |
| }; | |
| return config; | |
| }, | |
| // Headers for security | |
| async headers() { | |
| return [ | |
| { | |
| source: '/:path*', | |
| headers: [ | |
| { | |
| key: 'X-DNS-Prefetch-Control', | |
| value: 'on' | |
| }, | |
| { | |
| key: 'X-Frame-Options', | |
| value: 'SAMEORIGIN' | |
| }, | |
| { | |
| key: 'X-Content-Type-Options', | |
| value: 'nosniff' | |
| }, | |
| { | |
| key: 'Referrer-Policy', | |
| value: 'origin-when-cross-origin' | |
| }, | |
| { | |
| key: 'Content-Security-Policy', | |
| value: "default-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.vercel.app https://*.hf.space https://huggingface.co https://*.googleapis.com; img-src 'self' data: https: https://*.cloudinary.com; connect-src 'self' https://*.hf.space https://*.vercel.app https://huggingface.co;" | |
| }, | |
| { | |
| key: 'Strict-Transport-Security', | |
| value: 'max-age=31536000; includeSubDomains' | |
| }, | |
| { | |
| key: 'X-XSS-Protection', | |
| value: '1; mode=block' | |
| }, | |
| ], | |
| }, | |
| ]; | |
| }, | |
| }; | |
| module.exports = nextConfig; | |