spb/market-atlas
Public
TypeScript 96.7%
SQL 1.6%
CSS 0.8%
JavaScript 0.5%
1import type { NextConfig } from "next";2import { existsSync } from "node:fs";3import path from "node:path";45// Monorepo: a single `.env` lives at the repository root; Next only reads the app directory.6for (const candidate of [path.resolve(process.cwd(), "../../.env"), path.resolve(process.cwd(), ".env")]) {7 if (existsSync(candidate)) {8 try {9 process.loadEnvFile(candidate);10 } catch {11 /* ignore malformed env */12 }13 }14}1516// Dev: API on :8391 (repo .env). Production: the API process is the public edge (:8380) and proxies non-/v1 paths here (:8382).17const API_URL = (process.env.API_URL ?? "http://127.0.0.1:8391").replace(/\/$/, "");18const isDevApi = /:8391$/.test(API_URL) || /localhost|127\.0\.0\.1/.test(API_URL) && process.env.NODE_ENV !== "production";1920const nextConfig: NextConfig = {21 distDir: process.env.NEXT_DIST_DIR || ".next",22 reactStrictMode: true,23 poweredByHeader: false,24 allowedDevOrigins: ["127.0.0.1", "localhost"],25 outputFileTracingRoot: path.resolve(__dirname, "../.."),26 experimental: { optimizePackageImports: ["lucide-react"] },27 env: {28 // In development the browser talks to the API directly for WebSocket (rewrites do not proxy upgrades).29 NEXT_PUBLIC_WS_URL: process.env.NEXT_PUBLIC_WS_URL ?? (isDevApi ? API_URL.replace(/^http/, "ws") + "/v1/stream" : ""),30 NEXT_PUBLIC_SITE_URL: process.env.NEXT_PUBLIC_SITE_URL ?? process.env.MA_SITE_URL ?? "https://www.market-atlas.co",31 },32 async rewrites() {33 return [{ source: "/v1/:path*", destination: `${API_URL}/v1/:path*` }];34 },35 async headers() {36 const PUBLIC_CACHE = { key: "Cache-Control", value: "public, s-maxage=60, stale-while-revalidate=600" };37 const NO_STORE = { key: "Cache-Control", value: "private, no-store" };38 return [39 {40 source: "/(.*)",41 headers: [42 { key: "X-Content-Type-Options", value: "nosniff" },43 { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },44 { key: "X-Frame-Options", value: "SAMEORIGIN" },45 { key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=()" },46 ],47 },48 { source: "/methodology", headers: [PUBLIC_CACHE] },49 { source: "/developers", headers: [PUBLIC_CACHE] },50 { source: "/licensing", headers: [PUBLIC_CACHE] },51 { source: "/admin/:path*", headers: [NO_STORE] },52 ];53 },54};5556export default nextConfig;57