51 lines
1.6 KiB
TypeScript
51 lines
1.6 KiB
TypeScript
import type { NextConfig } from "next";
|
|
import createNextIntlPlugin from "next-intl/plugin";
|
|
|
|
const withNextIntl = createNextIntlPlugin();
|
|
|
|
const nextConfig: NextConfig = {
|
|
output: "standalone", // For Docker deployment (staging/production)
|
|
// Security headers + cache to reduce "failed to load chunk" on mobile (avoid stale HTML referencing old chunks)
|
|
async headers() {
|
|
return [
|
|
{
|
|
source: "/_next/static/:path*",
|
|
headers: [
|
|
{ key: "Cache-Control", value: "public, max-age=31536000, immutable" },
|
|
],
|
|
},
|
|
{
|
|
source: "/:path*",
|
|
headers: [
|
|
{ key: "X-DNS-Prefetch-Control", value: "on" },
|
|
{ key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains; preload" },
|
|
{ key: "X-Frame-Options", value: "SAMEORIGIN" },
|
|
{ key: "X-Content-Type-Options", value: "nosniff" },
|
|
{ key: "X-XSS-Protection", value: "1; mode=block" },
|
|
{ key: "Referrer-Policy", value: "origin-when-cross-origin" },
|
|
{ key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=()" },
|
|
// No cache for HTML so after deploy users always get fresh app (avoids "Failed to find Server Action" + 504)
|
|
{ key: "Cache-Control", value: "no-store, no-cache, must-revalidate" },
|
|
],
|
|
},
|
|
];
|
|
},
|
|
|
|
// Image optimization
|
|
images: {
|
|
remotePatterns: [
|
|
{
|
|
protocol: "https",
|
|
hostname: "**",
|
|
},
|
|
],
|
|
},
|
|
|
|
// Experimental features
|
|
experimental: {
|
|
optimizePackageImports: ["lucide-react"],
|
|
},
|
|
};
|
|
|
|
export default withNextIntl(nextConfig);
|