import type { NextConfig } from 'next'; import createNextIntlPlugin from 'next-intl/plugin'; /** Registers the cookie-based locale resolver in src/i18n/request.ts. */ const withNextIntl = createNextIntlPlugin('./src/i18n/request.ts'); const nextConfig: NextConfig = { reactStrictMode: true, /** * Proxies API calls through this app's own origin. * * The refresh token is a `SameSite=Lax` httpOnly cookie, so the browser only * sends it first-party. Calling the API host directly from the browser would * mean `SameSite=None; Secure`, which cannot work over plain HTTP in local * development at all. Production does the same thing at the Nginx layer, so * dev and prod share one topology instead of two. */ async rewrites() { const target = process.env.API_INTERNAL_URL ?? 'http://localhost:4000'; return [{ source: '/api/:path*', destination: `${target}/api/:path*` }]; }, transpilePackages: ['@sport/ui'], typedRoutes: true, output: 'standalone', images: { /** * Media is served from R2/CDN in production and MinIO locally. * * `pathname` and `search` are specified explicitly: Next 16 matches remote * patterns strictly, and an entry without them does not authorise the URL — * the optimizer answers `"url" parameter is not allowed` and every product * image renders broken. Scoping to the bucket path also keeps this from * becoming an open image proxy. */ remotePatterns: [ { protocol: 'http', hostname: 'localhost', port: '9000', pathname: '/**', search: '' }, { protocol: 'https', hostname: '**.r2.dev', pathname: '/**', search: '' }, { protocol: 'https', hostname: 'cdn.sport-store.local', pathname: '/**', search: '' }, ], /** * DEVELOPMENT ONLY. See the storefront config for the full explanation: * Next 16 blocks upstream images on private IPs (SSRF guard) and reports it * with the same message as an unmatched pattern. Local MinIO is on * localhost, production media is on a public CDN host. */ dangerouslyAllowLocalIP: process.env.NODE_ENV !== 'production', }, // The admin is an internal tool: keep it out of every index, permanently. async headers() { return [ { source: '/:path*', headers: [ { key: 'X-Robots-Tag', value: 'noindex, nofollow' }, { key: 'Referrer-Policy', value: 'same-origin' }, ], }, ]; }, }; export default withNextIntl(nextConfig);