Files
2026-04-29 07:20:16 -06:00

133 lines
3.0 KiB
JavaScript

import createMDX from "@next/mdx";
/* eslint-env node */
/** @type {import('next').NextConfig} */
const nextConfig = {
output: "standalone",
serverExternalPackages: ["@prisma/client"],
/**
* `next dev --turbopack` does not use `webpack()`; without this, `.svg`
* imports resolve as asset URLs and {@link app/components/asset/icon/Icon.tsx}
* cannot render them as components.
*/
turbopack: {
rules: {
"*.svg": {
condition: { not: "foreign" },
loaders: ["@svgr/webpack"],
as: "*.js",
},
},
},
// Performance optimizations
experimental: {
optimizeCss: true,
optimizePackageImports: ["react", "react-dom"],
},
// Compression
compress: true,
// Image optimization
images: {
formats: ["image/webp", "image/avif"],
minimumCacheTTL: 60,
dangerouslyAllowSVG: true,
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
remotePatterns: [
{
protocol: "http",
hostname: "localhost",
port: "",
pathname: "/**",
},
],
},
// Headers for caching
async headers() {
return [
{
source: "/(.*)",
headers: [
{
key: "X-Content-Type-Options",
value: "nosniff",
},
{
key: "X-Frame-Options",
value: "DENY",
},
{
key: "X-XSS-Protection",
value: "1; mode=block",
},
],
},
{
source: "/static/(.*)",
headers: [
{
key: "Cache-Control",
value: "public, max-age=31536000, immutable",
},
],
},
];
},
webpack(config, { dev, isServer }) {
// SVG handling
config.module.rules.push({
test: /\.svg$/,
issuer: /\.[jt]sx?$/,
use: ["@svgr/webpack"],
});
// Bundle analysis - only in production builds
if (process.env.ANALYZE === "true" && !dev) {
try {
const BundleAnalyzerPlugin =
require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
config.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: "static",
openAnalyzer: false,
reportFilename: isServer
? "../analyze/server.html"
: "../analyze/client.html",
}),
);
} catch (error) {
console.warn("Bundle analyzer not available:", error.message);
}
}
// Production optimizations
if (!dev && !isServer) {
// Tree shaking optimization
config.optimization = {
...config.optimization,
usedExports: true,
sideEffects: false,
};
}
return config;
},
async redirects() {
return [
{
source: "/create/right-rail",
destination: "/create/decision-approaches",
permanent: true,
},
];
},
};
const withMDX = createMDX({
options: {
remarkPlugins: [],
rehypePlugins: [],
},
});
export default withMDX(nextConfig);