import type { NextConfig } from "next"; const isProd = process.env.NODE_ENV === "production"; const csp = [ "default-src 'self'", // Next.js needs inline bootstrap scripts; nonces are not used because pages are statically cached. No eval in production. isProd ? "script-src 'self' 'unsafe-inline'" : "script-src 'self' 'unsafe-inline' 'unsafe-eval'", "style-src 'self' 'unsafe-inline'", "img-src 'self' data: blob:", "font-src 'self' data:", "connect-src 'self'", "object-src 'none'", "base-uri 'self'", "form-action 'self'", "frame-ancestors 'none'", "upgrade-insecure-requests", ].join("; "); const securityHeaders = [ { key: "X-Content-Type-Options", value: "nosniff" }, { key: "X-Frame-Options", value: "DENY" }, { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" }, { key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=(), browsing-topics=()" }, { key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains" }, { key: "Cross-Origin-Opener-Policy", value: "same-origin" }, { key: "Content-Security-Policy", value: csp }, ]; const nextConfig: NextConfig = { poweredByHeader: false, reactStrictMode: true, serverExternalPackages: ["postgres", "@node-rs/argon2"], async headers() { return [ { source: "/(.*)", headers: securityHeaders }, { source: "/admin/:path*", headers: [{ key: "X-Robots-Tag", value: "noindex, nofollow" }, { key: "Cache-Control", value: "no-store" }] }, { source: "/login", headers: [{ key: "X-Robots-Tag", value: "noindex, nofollow" }, { key: "Cache-Control", value: "no-store" }] }, { source: "/api/admin/:path*", headers: [{ key: "X-Robots-Tag", value: "noindex" }, { key: "Cache-Control", value: "no-store" }] }, ]; }, }; export default nextConfig;