Ctrl K
ComunidadGuías…

next.config.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  reactStrictMode: true,
  // The React Compiler memoises components for us, which is only sound if every
  // component obeys the rules of React. That is why `eslint-plugin-react-hooks`
  // is on at its full ruleset rather than just rules-of-hooks: a component the
  // compiler cannot prove safe is silently skipped, so the lint errors are the
  // only place that shows up. It adds a Babel pass, so builds are slower.
  experimental: { reactCompiler: true },
  // pg is only used by the local preview driver. Keep it external so webpack
  // does not try to bundle its optional native bits into the production build.
  //
  // web-push for the same reason from the other direction: it is CommonJS and
  // reaches for node:crypto and node:http directly to do the ECDH and the
  // signing, none of which survives being bundled for an edge-ish target.
  serverExternalPackages: ["pg", "web-push"],

  // The OG card reads a TTF off disk at runtime. Nothing imports it, so the
  // tracer cannot see it and the file would be absent from the deployment: the
  // card would 500 in production and be fine everywhere it was tested.
  outputFileTracingIncludes: {
    "/opengraph-image": ["./assets/fonts/**"],
  },

  // Response headers, on every route.
  //
  // Deliberately the boring ones. There is no full Content-Security-Policy
  // here: Next's App Router emits inline bootstrap scripts, so a real policy
  // needs a per-request nonce through middleware, and a wrong one fails as a
  // blank page rather than as an error. `frame-ancestors` is the one directive
  // that costs nothing to get right, and it is the one that matters most,
  // because the whole app is one-click actions behind a session cookie.
  //
  // Two that are absent on purpose. `Cross-Origin-Opener-Policy` can break an
  // OAuth flow that uses a popup, and this one is a redirect today but need not
  // stay one. `preload` on HSTS is a submission to a browser list that is
  // difficult to leave, and it is not ours to make for a domain serving other
  // things.
  // Next types this as returning a promise, and there is nothing to await.
  headers: () =>
    Promise.resolve([
      {
        source: "/:path*",
        headers: [
          // Nothing may frame us: no iframes anywhere in the app, so this is
          // free, and both spellings because the old one is what some scanners
          // and some older browsers read.
          { key: "Content-Security-Policy", value: "frame-ancestors 'none'" },
          { key: "X-Frame-Options", value: "DENY" },
          // An uploaded photo is served through our own routes. A response
          // sniffed as HTML is how an image becomes a script.
          { key: "X-Content-Type-Options", value: "nosniff" },
          // A group invite link is a secret in a URL. Do not send the path to
          // another origin.
          { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
          // The camera is the app's own, on the check-in screen. Everything
          // else is off, including for anything the app ever embeds.
          {
            key: "Permissions-Policy",
            value: "camera=(self), microphone=(), geolocation=(), payment=(), usb=()",
          },
          // Honoured over HTTPS only, so localhost is unaffected.
          {
            key: "Strict-Transport-Security",
            value: "max-age=31536000; includeSubDomains",
          },
        ],
      },
    ]),
};

export default nextConfig;