IKHSAN
EN Read in EnglishID

homeio

Publik

Fork dari doctor-io/homeio

Branch
main
Commit terakhir
958d74616 Oktober 2026

next.config.mjs

Buka raw
import { createRequire } from "module";

const require = createRequire(import.meta.url);
const pkg = require("./package.json");

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    proxyClientMaxBodySize: "10gb",
    serverActions: {
      bodySizeLimit: "10gb",
    },
    // Next 16.3 made the tsc CLI the default, which type-checks test files
    // too. Keep checking only the app, as 16.2 did.
    useTypeScriptCli: false,
  },
  // "standalone" is set via NEXT_OUTPUT env var during Docker builds only
  ...(process.env.NEXT_OUTPUT === "standalone" ? { output: "standalone" } : {}),
  images: {
    unoptimized: true,
  },
  env: {
    NEXT_PUBLIC_APP_VERSION: pkg.version,
  },
  async headers() {
    return [
      {
        // Homeio controls the whole machine (shutdown, disk format, app
        // install), so the dashboard must never be embedded in another site:
        // without this a hidden iframe could clickjack an admin into acting.
        // Set at the app so the tunnel, a bare nginx and the Docker image all
        // carry it. `frame-ancestors 'none'` is the only CSP directive here —
        // a full script/style policy would need per-response nonces and risks
        // breaking the app, while framing protection costs nothing.
        source: "/:path*",
        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" },
          // The dashboard uses no camera or microphone; deny them so a future
          // XSS cannot either. Geolocation stays allowed for Homeio's own
          // pages, which use it for the weather in the top bar.
          {
            key: "Permissions-Policy",
            value: "camera=(), microphone=(), geolocation=(self)",
          },
          // Honoured only over HTTPS (the Cloudflare tunnel), ignored on a
          // plain-HTTP LAN address, so it is safe to send everywhere.
          {
            key: "Strict-Transport-Security",
            value: "max-age=63072000; includeSubDomains",
          },
        ],
      },
      {
        // Wallpapers ship with the release and never change under a given
        // name, but public/ is served with max-age=0, so every switch
        // re-downloaded ~365 KB — twice, since the accent-colour sampler
        // fetches the image again. Over a tunnel that is seconds of a click
        // doing nothing.
        source: "/images/:path*",
        headers: [
          {
            key: "Cache-Control",
            value: "public, max-age=31536000, immutable",
          },
        ],
      },
    ];
  },
};

export default nextConfig;
byte
2.828
baris
75
Jenis
mjs
Commit terakhir
16 Oktober 2026