Ctrl K
ComunidadGuías…

apps/landing/next.config.ts

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

Archivo original ↗Preguntar a KiBot
// SPDX-License-Identifier: Apache-2.0

import { existsSync } from "node:fs";
import path from "node:path";

import type { NextConfig } from "next";

const HOISTED_ROOT = path.resolve(__dirname, "../../..");

const output = process.env.NEXT_OUTPUT === "standalone" ? "standalone" : undefined;

const securityHeaders = [
  { key: "Strict-Transport-Security", value: "max-age=31536000" },
  { key: "X-Content-Type-Options", value: "nosniff" },
  { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
  { key: "X-Frame-Options", value: "DENY" },
  { key: "Content-Security-Policy", value: "frame-ancestors 'none'" },
];

const nextConfig: NextConfig = {
  output,
  // Local-dev only, and a no-op anywhere else. In this checkout the apps sit in
  // an npm workspace whose `node_modules` is hoisted to a parity-rebuild root
  // ABOVE `community/` — but `community/` is its own git repository, so
  // Turbopack stops its workspace-root search at that boundary and never
  // reaches the hoisted tree, leaving `next` itself unresolvable.
  //
  // The guard matters: in the published standalone repo there is no ancestor
  // workspace, so `../../..` would point outside the repository. We only take
  // the override when that ancestor really is the tree holding `next`, which is
  // true in the monorepo checkout and false everywhere else.
  ...(existsSync(path.join(HOISTED_ROOT, "node_modules", "next")) ? { turbopack: { root: HOISTED_ROOT } } : {}),
  images: { unoptimized: true },
  trailingSlash: true,
  headers: async () => [{ source: "/:path*", headers: securityHeaders }],
  // The public dataset listing moved /bounties -> /pools (owner-ratified
  // vocabulary change, see the decision register). These are permanent (308)
  // rather than a silent 404: the old paths were public, linked from
  // /domains and the footer, listed in sitemap.xml and llms.txt, and may be
  // indexed or bookmarked. A 308 also transfers ranking signal to the new
  // path, which a 404 or a client-side rewrite would discard.
  redirects: async () => [
    // Destinations carry the trailing slash to match `trailingSlash: true`
    // above; without it each hit pays an extra 308 (/pools -> /pools/).
    { source: "/bounties", destination: "/pools/", permanent: true },
    { source: "/bounties/:id", destination: "/pools/:id/", permanent: true },
  ],
};

export default nextConfig;