pounce/frontend/next.config.js
Yves Gugger 4995101dd1 fix: Frontend proxy uses pounce-backend in production
- next.config.js now detects NODE_ENV=production
- Uses http://pounce-backend:8000 in Docker instead of localhost
- Logs backend URL during build for debugging
2025-12-20 23:39:43 +01:00

182 lines
4.6 KiB
JavaScript

/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
output: 'standalone',
// Performance & SEO optimizations
poweredByHeader: false, // Remove X-Powered-By header for security
compress: true, // Enable gzip compression
// Image optimization
images: {
formats: ['image/avif', 'image/webp'], // Modern image formats
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
minimumCacheTTL: 60 * 60 * 24 * 365, // 1 year cache
dangerouslyAllowSVG: true,
contentDispositionType: 'attachment',
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
remotePatterns: [
{
protocol: 'https',
hostname: '**.pounce.com',
},
],
},
// Headers for security and caching
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'X-DNS-Prefetch-Control',
value: 'on',
},
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload',
},
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN',
},
{
key: 'X-Content-Type-Options',
value: 'nosniff',
},
{
key: 'X-XSS-Protection',
value: '1; mode=block',
},
{
key: 'Referrer-Policy',
value: 'origin-when-cross-origin',
},
{
key: 'Permissions-Policy',
value: 'camera=(), microphone=(), geolocation=()',
},
],
},
{
source: '/static/:path*',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
},
],
},
]
},
// Redirects from old routes to new Terminal routes
async redirects() {
return [
// Old Command Center routes
{
source: '/command',
destination: '/terminal/radar',
permanent: true,
},
{
source: '/command/:path*',
destination: '/terminal/:path*',
permanent: true,
},
// Dashboard → RADAR
{
source: '/terminal/dashboard',
destination: '/terminal/radar',
permanent: true,
},
// Pricing → INTEL
{
source: '/terminal/pricing',
destination: '/terminal/intel',
permanent: true,
},
{
source: '/terminal/pricing/:tld*',
destination: '/terminal/intel/:tld*',
permanent: true,
},
// Public Intel → Discover
{
source: '/intel',
destination: '/discover',
permanent: true,
},
{
source: '/intel/:tld*',
destination: '/discover/:tld*',
permanent: true,
},
// Old TLD pricing → Discover
{
source: '/tld-pricing',
destination: '/discover',
permanent: true,
},
{
source: '/tld-pricing/:tld*',
destination: '/discover/:tld*',
permanent: true,
},
// Listings → LISTING
{
source: '/terminal/listings',
destination: '/terminal/listing',
permanent: true,
},
// Auctions & Marketplace → MARKET
{
source: '/terminal/auctions',
destination: '/terminal/market',
permanent: true,
},
{
source: '/terminal/marketplace',
destination: '/terminal/market',
permanent: true,
},
// Portfolio is now a separate page (not redirected anymore)
// Alerts → RADAR (will be integrated)
{
source: '/terminal/alerts',
destination: '/terminal/radar',
permanent: true,
},
// SEO → RADAR (premium feature, hidden for now)
{
source: '/terminal/seo',
destination: '/terminal/radar',
permanent: true,
},
]
},
// Proxy API requests to backend
// This ensures /api/v1/* works regardless of how the server is accessed
async rewrites() {
// In production (Docker), use internal container hostname
// In development, use localhost
const isProduction = process.env.NODE_ENV === 'production'
const backendUrl = process.env.BACKEND_URL || (isProduction ? 'http://pounce-backend:8000' : 'http://127.0.0.1:8000')
console.log(`[Next.js Config] Backend URL: ${backendUrl}`)
return [
{
source: '/api/v1/:path*',
destination: `${backendUrl}/api/v1/:path*`,
},
]
},
}
module.exports = nextConfig