/** @type {import('next').NextConfig} */ const { buildSecurityHeaders, normalizeAssetPrefix } = require('../../config/nextSecurityHeaders') const toStoragePattern = (rawUrl) => { try { const u = new URL(rawUrl.replace(/\/api\/v1\/?$/, '')) return { protocol: u.protocol.replace(':', ''), hostname: u.hostname, ...(u.port ? { port: u.port } : {}), pathname: '/storage/**', } } catch { return null } } const storagePatterns = [ process.env.API_INTERNAL_URL ?? 'http://localhost:4000', process.env.API_URL, process.env.NEXT_PUBLIC_API_URL, ] .filter(Boolean) .map(toStoragePattern) .filter(Boolean) .filter((p, i, arr) => arr.findIndex((q) => q.hostname === p.hostname && q.port === p.port) === i) const DASHBOARD_BASE_PATH = '/dashboard' // basePath is required so the client-side router knows it's mounted at /dashboard. // Without it, React cannot hydrate because the URL (/dashboard/sign-up) doesn't // match the route (/sign-up). The Turbopack double-basePath prefetch bug is // handled by the Carplace middleware (307 redirect /dashboard/dashboard → /dashboard). // // In local development the dashboard is often viewed through the Carplace // proxy on port 3000 while the dashboard dev server runs on port 3001. Next // rewrites do not reliably proxy HMR WebSocket upgrades, so emit absolute // dashboard asset/HMR URLs directly to the dashboard dev server. const dashboardAssetPrefix = process.env.DASHBOARD_ASSET_PREFIX ?? (process.env.NODE_ENV !== 'production' ? 'http://localhost:3001' : undefined) const assetPrefix = normalizeAssetPrefix(dashboardAssetPrefix, DASHBOARD_BASE_PATH) const securityHeaders = buildSecurityHeaders({ assetSources: [assetPrefix].filter(Boolean), }) const nextConfig = { basePath: DASHBOARD_BASE_PATH, ...(assetPrefix ? { assetPrefix } : {}), images: { remotePatterns: [ { protocol: 'https', hostname: 'res.cloudinary.com', }, ...storagePatterns, ], }, transpilePackages: ['@rentaldrivego/types'], async headers() { return [ { source: '/_next/static/media/:path*', headers: [ { key: 'Access-Control-Allow-Origin', value: '*', }, ], }, { source: '/:path*', headers: securityHeaders, }, ] }, async redirects() { return [ { source: `${DASHBOARD_BASE_PATH}/:path*`, destination: '/:path*', permanent: false, }, { source: DASHBOARD_BASE_PATH, destination: '/', permanent: false, }, { source: '/', destination: DASHBOARD_BASE_PATH, permanent: false, basePath: false, }, ] }, async rewrites() { const apiOrigin = (process.env.API_INTERNAL_URL ?? process.env.API_URL ?? 'http://localhost:4000').replace(/\/api\/v1\/?$/, '') return [ { source: '/api/:path*', destination: `${apiOrigin}/api/:path*`, }, { source: '/storage/:path*', destination: `${apiOrigin}/storage/:path*`, }, ] }, } module.exports = nextConfig