import type { NextConfig } from "next"; /** * Freezmo is meant to be opened from a phone on the same network, so the dev * server should accept dev-asset requests coming from private hostnames. * Production builds are not affected by this option. * * Add your own hostname here if Next still warns about a cross-origin request. */ const nextConfig: NextConfig = { /** * Dev and production never share a build folder: the dev service runs with * NEXT_DIST_DIR=.next-dev (see deploy/freezmo-dev.service), while a manual * `npm run build` keeps producing .next for the test suites. A production * build can therefore never clobber the running dev server, and the other * way around. */ distDir: process.env.NEXT_DIST_DIR || ".next", /** * Releases ship as self-contained standalone output: scripts/deploy.sh * copies public/ and .next/static next to `.next/standalone/server.js` and * runs that. `next start` keeps working too, so the existing workflows and * the e2e suites are unaffected. */ output: "standalone", /** * Security headers. The app has no accounts, so these are about containment: * never framed (clickjacking), never sniffed into a script, and no camera, * microphone or location access it does not need (the camera button uses a * file input with `capture`, which is not gated by Permissions-Policy). */ async headers() { return [ { source: "/(.*)", headers: [ { key: "X-Frame-Options", value: "DENY" }, { key: "Content-Security-Policy", value: "frame-ancestors 'none'" }, { key: "X-Content-Type-Options", value: "nosniff" }, { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" }, { key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=(), payment=()" }, ], }, ]; }, allowedDevOrigins: [ "127.0.0.1", "localhost", "*.local", "**.local", "192.168.*.*", "10.*.*.*", "*.ts.net", // Tailscale ], }; export default nextConfig;