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";
import { LEGACY_SETTINGS_REDIRECTS } from "./lib/settings/tabs";

const nextConfig: NextConfig = {
  images: {
    // 75 is next/image's default; 85 is the title page's full-bleed backdrop
    // (components/title-hero.tsx), where 75 bands the long fades and shows
    // blocks in dark skies at 2560px.
    qualities: [75, 85],
    remotePatterns: [
      {
        protocol: "https",
        hostname: "image.tmdb.org",
        pathname: "/t/p/**",
      },
      // TheTVDB's own artwork CDN — used as a poster/backdrop fallback when
      // TMDb doesn't have one yet, for titles that have a TVDB API key
      // connected.
      {
        protocol: "https",
        hostname: "artworks.thetvdb.com",
      },
    ],
  },
  // Settings' pages that moved when it was regrouped into tabs
  // (lib/settings/tabs.ts): bookmarks and the apps' links still land.
  async redirects() {
    return LEGACY_SETTINGS_REDIRECTS.map((entry) => ({ ...entry, permanent: false }));
  },
  // Every /api/v1 route handler sets X-Marquee-API itself; this also covers
  // the responses Next.js generates on its own for those paths (405 Method
  // Not Allowed, automatic OPTIONS), so native clients can always tell a v1
  // server's answer apart from something else on the same host.
  async headers() {
    return [
      // Baseline hardening for every response. Framing is deliberately left
      // alone: plenty of self-hosters embed Marquee in Organizr or Homarr,
      // and a frame-ancestors rule would break that.
      {
        source: "/:path*",
        headers: [
          { key: "X-Content-Type-Options", value: "nosniff" },
          { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
          { key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=()" },
        ],
      },
      // The pages the Mac and Windows apps open for single sign-on: "Continue"
      // there hands an app a session, so it's never shown inside someone
      // else's frame (clickjacking). They're opened in the browser directly,
      // never embedded, so this costs the Organizr/Homarr case nothing.
      {
        source: "/login/sso/:path*",
        headers: [
          { key: "X-Frame-Options", value: "DENY" },
          { key: "Content-Security-Policy", value: "frame-ancestors 'none'" },
        ],
      },
      // The push service worker (public/sw.js): never cached, so a fix to
      // it reaches every browser on its next visit, and scripts only from
      // this site.
      {
        source: "/sw.js",
        headers: [
          { key: "Content-Type", value: "application/javascript; charset=utf-8" },
          { key: "Cache-Control", value: "no-cache, no-store, must-revalidate" },
          { key: "Content-Security-Policy", value: "default-src 'self'; script-src 'self'" },
        ],
      },
      { source: "/api/v1", headers: [{ key: "X-Marquee-API", value: "1" }] },
      { source: "/api/v1/:path*", headers: [{ key: "X-Marquee-API", value: "1" }] },
    ];
  },
};

export default nextConfig;