next.config.mjs

/** @type {import("next").NextConfig} */

const securityHeaders = [
  { key: "X-DNS-Prefetch-Control",    value: "on" },
  { key: "X-Frame-Options",           value: "SAMEORIGIN" },
  { key: "X-Content-Type-Options",    value: "nosniff" },
  { key: "Referrer-Policy",           value: "strict-origin-when-cross-origin" },
  {
    key: "Content-Security-Policy",
    value: [
      "default-src 'self'",
      "script-src 'self' 'unsafe-eval' 'unsafe-inline'",  // tighten for prod
      "style-src 'self' 'unsafe-inline'",
      "img-src 'self' data: https:",
      "font-src 'self'",
      "connect-src 'self' https://api.example.com",
    ].join("; "),
  },
];

const nextConfig = {
  // Standalone output bundles server + node_modules for minimal Docker images
  output: "standalone",

  // Compress responses (disable if Nginx handles it upstream)
  compress: true,

  // Disallow crawling of the dev/staging environment
  // Remove or conditionally apply in production
  // headers() controls robots.txt via meta; use middleware for HTTP header

  async headers() {
    return [
      {
        source: "/(.*)",
        headers: securityHeaders,
      },
    ];
  },

  images: {
    remotePatterns: [
      { protocol: "https", hostname: "cdn.example.com" },
      { protocol: "https", hostname: "images.unsplash.com" },
    ],
    formats: ["image/avif", "image/webp"],
    minimumCacheTTL: 3600,
  },

  // Experimental
  reactCompiler: true,
  experimental: {
    serverComponentsExternalPackages: ["pg"],
  },

  // Silence SASS deprecation warnings from Bootstrap
  sassOptions: {
    silenceDeprecations: ["import"],
    quietDeps: true,
  },

  // Redirect legacy URLs
  async redirects() {
    return [
      { source: "/docs", destination: "/blog", permanent: true },
    ];
  },
};

export default nextConfig;

Environment variable validation (env.mjs)

// Validates env vars at build time - fails fast before deploy
const requiredEnv = ["DATABASE_URL", "NEXTAUTH_SECRET"];
for (const key of requiredEnv) {
  if (!process.env[key]) {
    throw new Error(`Missing required environment variable: ${key}`);
  }
}

.env.local template

DATABASE_URL=postgres://user:pass@localhost:5432/mydb
NODE_ENV=development