open-prompt / next.config.ts
anky2002's picture
perf: add Three.js and Recharts to optimizePackageImports + document dynamic import pattern
034a841 verified
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
// Image optimization – whitelist only known-safe domains (no wildcard **)
images: {
remotePatterns: [
// GitHub avatars (OAuth)
{ protocol: "https", hostname: "avatars.githubusercontent.com" },
// Google avatars (OAuth)
{ protocol: "https", hostname: "lh3.googleusercontent.com" },
{ protocol: "https", hostname: "lh4.googleusercontent.com" },
{ protocol: "https", hostname: "lh5.googleusercontent.com" },
// Stack Auth CDN
{ protocol: "https", hostname: "*.stackauth.com" },
// Prompt preview / gallery images (Cloudflare R2 / storage)
{ protocol: "https", hostname: "imagedelivery.net" },
{ protocol: "https", hostname: "images.unsplash.com" },
// AI image CDNs
{ protocol: "https", hostname: "oaidalleapiprodscus.blob.core.windows.net" },
{ protocol: "https", hostname: "cdn.midjourney.com" },
{ protocol: "https", hostname: "image.civitai.com" },
],
formats: ["image/avif", "image/webp"],
},
// Security headers
async headers() {
return [
{
source: "/(.*)",
headers: [
{ key: "X-Frame-Options", value: "SAMEORIGIN" },
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
{ key: "X-DNS-Prefetch-Control", value: "on" },
{ key: "X-Permitted-Cross-Domain-Policies", value: "none" },
{ key: "Strict-Transport-Security", value: "max-age=31536000; includeSubDomains; preload" },
{ key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=()" },
{
key: "Content-Security-Policy",
value: [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://challenges.cloudflare.com https://www.googletagmanager.com",
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
"font-src 'self' https://fonts.gstatic.com",
"img-src 'self' data: blob: https:",
"frame-src 'self' https://challenges.cloudflare.com",
"connect-src 'self' https://api.openai.com https://api.anthropic.com https://generativelanguage.googleapis.com https://challenges.cloudflare.com wss: ws:",
"media-src 'self' blob:",
"worker-src 'self' blob:",
].join("; "),
},
],
},
{
source: "/logos/(.*)",
headers: [
{ key: "Cache-Control", value: "public, max-age=31536000, immutable" },
],
},
{
source: "/(.*\\.(?:svg|png|jpg|jpeg|gif|ico|woff2|woff|ttf))",
headers: [
{ key: "Cache-Control", value: "public, max-age=86400, stale-while-revalidate=3600" },
],
},
];
},
// Performance optimizations – tree-shake large packages
experimental: {
optimizePackageImports: [
"lucide-react",
"react-icons",
"framer-motion",
"recharts",
"three",
"@react-three/fiber",
"@react-three/drei",
"@radix-ui/react-dropdown-menu",
"@radix-ui/react-select",
"@radix-ui/react-tabs",
"@radix-ui/react-tooltip",
"@radix-ui/react-checkbox",
"react-markdown",
"zustand",
],
},
};
export default nextConfig;