| Server IP : 35.80.110.71 / Your IP : 216.73.216.221 Web Server : Apache/2.4.58 (Ubuntu) System : Linux ip-172-31-21-44 6.17.0-1019-aws #19~24.04.1-Ubuntu SMP Tue Jun 23 18:53:06 UTC 2026 x86_64 User : ubuntu ( 1000) PHP Version : 8.3.31 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/elite-events-nextjs/current/ |
Upload File : |
import type { NextConfig } from "next";
import withPWAInit from "next-pwa";
// Conditionally load bundle analyzer only when ANALYZE=true (dev dependency)
const withBundleAnalyzer = process.env.ANALYZE === "true"
// eslint-disable-next-line @typescript-eslint/no-require-imports
? require("@next/bundle-analyzer")({ enabled: true })
: (config: NextConfig) => config;
/**
* Security headers config for Next.js
* Inline to avoid path alias resolution issues at runtime
*/
function getNextConfigSecurityHeaders(): Array<{
source: string;
headers: Array<{ key: string; value: string }>;
}> {
const securityHeaders = [
{ key: 'X-DNS-Prefetch-Control', value: 'on' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'X-XSS-Protection', value: '1; mode=block' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=(), interest-cohort=()' },
];
return [
{
source: '/:path*',
headers: securityHeaders,
},
];
}
const withPWA = withPWAInit({
dest: "public",
disable: process.env.NODE_ENV === "development",
register: true,
skipWaiting: true,
// Fallback for offline pages
fallbacks: {
document: "/offline",
},
// Runtime caching strategies
runtimeCaching: [
// Google Fonts - Cache First (rarely changes)
{
urlPattern: /^https:\/\/fonts\.(?:googleapis|gstatic)\.com\/.*/i,
handler: "CacheFirst",
options: {
cacheName: "google-fonts",
expiration: {
maxEntries: 4,
maxAgeSeconds: 365 * 24 * 60 * 60, // 1 year
},
},
},
// Static font assets
{
urlPattern: /\.(?:eot|otf|ttc|ttf|woff|woff2|font\.css)$/i,
handler: "StaleWhileRevalidate",
options: {
cacheName: "static-font-assets",
expiration: {
maxEntries: 4,
maxAgeSeconds: 7 * 24 * 60 * 60, // 1 week
},
},
},
// Images - Stale While Revalidate for quick loading
{
urlPattern: /\.(?:jpg|jpeg|gif|png|svg|ico|webp|avif)$/i,
handler: "StaleWhileRevalidate",
options: {
cacheName: "static-image-assets",
expiration: {
maxEntries: 64,
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
},
},
},
// JavaScript files
{
urlPattern: /\/_next\/static.+\.js$/i,
handler: "CacheFirst",
options: {
cacheName: "next-static-js-assets",
expiration: {
maxEntries: 64,
maxAgeSeconds: 24 * 60 * 60, // 24 hours
},
},
},
// CSS files
{
urlPattern: /\.(?:css|less)$/i,
handler: "StaleWhileRevalidate",
options: {
cacheName: "static-style-assets",
expiration: {
maxEntries: 32,
maxAgeSeconds: 24 * 60 * 60, // 24 hours
},
},
},
// API routes - Network First for fresh data
{
urlPattern: /\/api\/.*/i,
handler: "NetworkFirst",
options: {
cacheName: "api-cache",
networkTimeoutSeconds: 10,
expiration: {
maxEntries: 32,
maxAgeSeconds: 60 * 60, // 1 hour
},
cacheableResponse: {
statuses: [0, 200],
},
},
},
// Next.js data fetching
{
urlPattern: /\/_next\/data\/.+\/.+\.json$/i,
handler: "StaleWhileRevalidate",
options: {
cacheName: "next-data",
expiration: {
maxEntries: 32,
maxAgeSeconds: 24 * 60 * 60, // 24 hours
},
},
},
// All other requests - Network First
{
urlPattern: /.*/i,
handler: "NetworkFirst",
options: {
cacheName: "others",
networkTimeoutSeconds: 10,
expiration: {
maxEntries: 32,
maxAgeSeconds: 24 * 60 * 60, // 24 hours
},
},
},
],
});
const nextConfig: NextConfig = {
// Enable gzip compression
compress: true,
// Empty turbopack config to silence the warning about webpack config
// (next-pwa plugin adds webpack config, but Next.js 16+ defaults to Turbopack)
turbopack: {},
// Experimental features for bundle optimization
experimental: {
// Optimize imports for better tree-shaking
optimizePackageImports: [
'lucide-react',
'@radix-ui/react-icons',
'recharts',
'framer-motion',
'date-fns',
],
},
// Exclude server-only packages from bundling (prevents Turbopack from trying to bundle test files)
serverExternalPackages: [
'pino',
'pino-pretty',
'thread-stream',
// OpenTelemetry packages with Node.js-only dependencies
'@opentelemetry/auto-instrumentations-node',
'@opentelemetry/instrumentation-net',
'@opentelemetry/instrumentation-dns',
'@opentelemetry/instrumentation-fs',
'@opentelemetry/sdk-node',
],
images: {
// Configure remote patterns for external image sources
remotePatterns: [
{
protocol: 'https',
hostname: 'res.cloudinary.com',
pathname: '/**',
},
{
protocol: 'https',
hostname: '*.cloudinary.com',
pathname: '/**',
},
],
// Note: Custom loader is available at @/lib/images/cloudinary-loader
// Use it via the `loader` prop on individual Image components that need Cloudinary optimization
// Do NOT set global loader: 'custom' as it breaks local images
// Optimize images with these device sizes
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
// Sizes for responsive images
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
// Image formats to use - include AVIF for better compression
formats: ["image/avif", "image/webp"],
// Cache optimized images for 1 year
minimumCacheTTL: 60 * 60 * 24 * 365,
},
// Remove console logs in production (except errors)
compiler: {
removeConsole: process.env.NODE_ENV === "production" ? {
exclude: ["error", "warn"],
} : false,
},
// Redirects for URL changes (SEO-friendly permanent redirects)
async redirects() {
return [
{
source: '/shop-with-sidebar',
destination: '/shop',
permanent: true, // 308 redirect for SEO
},
{
source: '/shop-with-sidebar/:path*',
destination: '/shop/:path*',
permanent: true,
},
];
},
// HTTP headers for caching static assets
async headers() {
return [
{
// Cache static images for 1 year (immutable)
source: "/images/:path*",
headers: [
{
key: "Cache-Control",
value: "public, max-age=31536000, immutable",
},
],
},
{
// Cache Cloudinary proxy images for 1 year
source: "/api/images/:path*",
headers: [
{
key: "Cache-Control",
value: "public, max-age=31536000, s-maxage=31536000, stale-while-revalidate=86400",
},
],
},
{
// Cache Next.js static files for 1 year (immutable)
source: "/_next/static/:path*",
headers: [
{
key: "Cache-Control",
value: "public, max-age=31536000, immutable",
},
],
},
{
// Cache fonts for 1 year
source: "/fonts/:path*",
headers: [
{
key: "Cache-Control",
value: "public, max-age=31536000, immutable",
},
],
},
{
// Service worker should not be cached
source: "/sw.js",
headers: [
{
key: "Cache-Control",
value: "no-cache, no-store, must-revalidate",
},
],
},
// Security headers for all routes
...getNextConfigSecurityHeaders(),
];
},
};
export default withBundleAnalyzer(withPWA(nextConfig));