| const { withContentlayer } = require('next-contentlayer'); |
| |
| const withBundleAnalyzer = require('@next/bundle-analyzer')({ |
| enabled: process.env.ANALYZE === 'true' |
| }); |
| |
| // You might need to insert additional domains in script-src if you are using external services |
| const ContentSecurityPolicy = ` |
| default-src 'self'; |
| script-src 'self' 'unsafe-eval' 'unsafe-inline' giscus.app analytics.umami.is www.youtube.com www.googletagmanager.com www.google-analytics.com; |
| style-src 'self' 'unsafe-inline'; |
| img-src * blob: data:; |
| media-src *.s3.amazonaws.com; |
| connect-src *; |
| font-src 'self'; |
| frame-src www.youtube.com youtube.com giscus.app youtu.be; |
| `; |
| |
| const securityHeaders = [ |
| // https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP |
| { |
| key: 'Content-Security-Policy', |
| value: ContentSecurityPolicy.replace(/\n/g, '') |
| }, |
| // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy |
| { |
| key: 'Referrer-Policy', |
| value: 'strict-origin-when-cross-origin' |
| }, |
| // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options |
| { |
| key: 'X-Frame-Options', |
| value: 'DENY' |
| }, |
| // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options |
| { |
| key: 'X-Content-Type-Options', |
| value: 'nosniff' |
| }, |
| // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-DNS-Prefetch-Control |
| { |
| key: 'X-DNS-Prefetch-Control', |
| value: 'on' |
| }, |
| // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security |
| { |
| key: 'Strict-Transport-Security', |
| value: 'max-age=31536000; includeSubDomains' |
| }, |
| // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy |
| { |
| key: 'Permissions-Policy', |
| value: 'camera=(), microphone=(), geolocation=()' |
| } |
| ]; |
| |
| /** |
| * @type {import('next/dist/next-server/server/config').NextConfig} |
| **/ |
| module.exports = () => { |
| const plugins = [withContentlayer, withBundleAnalyzer]; |
| return plugins.reduce((acc, next) => next(acc), { |
| output: 'export', |
| // distDir: 'dist', |
| reactStrictMode: true, |
| pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'], |
| eslint: { |
| dirs: ['app', 'components', 'layouts', 'scripts'] |
| }, |
| images: { |
| remotePatterns: [ |
| { |
| protocol: 'https', |
| hostname: 'picsum.photos' |
| } |
| ] |
| }, |
| // async headers() { |
| // return [ |
| // { |
| // source: '/(.*)', |
| // headers: securityHeaders |
| // } |
| // ]; |
| // }, |
| webpack: (config, options) => { |
| config.module.rules.push({ |
| test: /\.svg$/, |
| use: ['@svgr/webpack'] |
| }); |
| |
| return config; |
| } |
| }); |
| }; |