Files
EpicNext-Cms/next.config.ts
T
openhands b87c9a5b8d
CI / check (push) Failing after 14s
CI / release (push) Skipped
CI / deploy (push) Skipped
chore: remove puppeteer CF bypass (not working for Leet/Hubbly/Habblet)
Cloudflare has strengthened protection on these hotels.
Puppeteer-based bypass returns HTML instead of JSON.
cloudscraper has dependency issues with Node.js v26.

Reverted to simple HTTP fetch with clear error messages.
2026-08-04 18:45:10 +02:00

89 lines
2.3 KiB
TypeScript

import { execFileSync } from "node:child_process";
import withBundleAnalyzer from "@next/bundle-analyzer";
import type { NextConfig } from "next";
import createNextIntlPlugin from "next-intl/plugin";
function resolveDeploymentId(): string | undefined {
const configuredId = process.env.NEXT_DEPLOYMENT_ID?.trim();
if (configuredId) return configuredId;
try {
return execFileSync("git", ["rev-parse", "HEAD"], {
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
}).trim();
} catch {
return process.env.APP_VERSION?.trim() || undefined;
}
}
const securityHeaders = [
{ key: "X-DNS-Prefetch-Control", value: "on" },
{
key: "Strict-Transport-Security",
value: "max-age=63072000; includeSubDomains; preload",
},
{ key: "X-Frame-Options", value: "DENY" },
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
{
key: "Permissions-Policy",
value: "camera=(), microphone=(), geolocation=(), interest-cohort=()",
},
// CSP is set per-request in src/proxy.ts with a script nonce (no 'unsafe-inline' for scripts).
];
const nextConfig: NextConfig = {
deploymentId: resolveDeploymentId(),
turbopack: {},
serverExternalPackages: ["mariadb", "lzma", "sharp", "pino", "pino-pretty"],
// Enable React Compiler for automatic memoization
reactCompiler: true,
// Compress responses with gzip/brotli
compress: true,
// Disable Next.js telemetry and browser sourcemaps in production
productionBrowserSourceMaps: false,
experimental: {
useTypeScriptCli: true,
},
// Add caching headers for static assets
async headers() {
return [
{
source: "/(.*)",
headers: securityHeaders,
},
{
source: "/assets/(.*)",
headers: [
{
key: "Cache-Control",
value: "public, max-age=31536000, immutable",
},
],
},
{
source: "/images/(.*)",
headers: [{ key: "Cache-Control", value: "public, max-age=86400" }],
},
];
},
};
// next-intl WITHOUT i18n routing — locale comes from the NEXT_LOCALE cookie via
// src/i18n/request.ts, so URLs and the access-guard middleware stay unchanged.
const withNextIntl = createNextIntlPlugin("./src/i18n/request.ts");
const config = withNextIntl(nextConfig);
const withBA = withBundleAnalyzer({
enabled: process.env.ANALYZE === "true",
});
export default withBA(config);