Two follow-ups from a fresh PageSpeed Insights run (mobile 87/100/100/100): 1. next.config.ts: enable experimental.inlineCss. Removes a ~342ms render-blocking CSS request (globals.css, ~21.6 KiB gzip -- shared by every route since Tailwind bundles the whole app's utilities into one file). Officially documented, dependency-free, and explicitly recommended for small atomic-CSS bundles like ours. Applies globally (can't be scoped per route), so hard/full page loads lose cross-page CSS caching -- soft client-side navigations are unaffected. 2. page.tsx hero image: `priority` was deprecated in Next.js 16 in favor of `fetchPriority`/`loading` as separate props -- it still emitted a <link rel=preload> but no longer set fetchpriority="high" on the <img> itself. Replaced with loading="eager" fetchPriority="high" per the bundled Next.js 16 docs. SpeedUp-Plan, Gitea #28.
67 lines
2.7 KiB
TypeScript
67 lines
2.7 KiB
TypeScript
import type { NextConfig } from "next";
|
|
import createNextIntlPlugin from "next-intl/plugin";
|
|
import { withSentryConfig } from "@sentry/nextjs";
|
|
|
|
const withNextIntl = createNextIntlPlugin("./src/i18n/request.ts");
|
|
|
|
function getSupabaseHostname(): string {
|
|
const url = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
|
if (url) {
|
|
try { return new URL(url).hostname; } catch { /* fall through */ }
|
|
}
|
|
return "*.supabase.co";
|
|
}
|
|
|
|
const nextConfig: NextConfig = {
|
|
output: "standalone",
|
|
allowedDevOrigins: ["192.168.1.92"],
|
|
experimental: {
|
|
// Inlines every route's CSS into <head><style> instead of a render-blocking
|
|
// <link>. Officially recommended for atomic CSS (Tailwind) with a small
|
|
// per-page bundle -- our globals.css is ~21 KiB gzipped, all of it shared
|
|
// by every route since Tailwind bundles the whole app's utilities into one
|
|
// file. Trade-off: no cross-page CSS caching on a hard/full page load
|
|
// (soft client-side navigations are unaffected, since they don't re-fetch
|
|
// <head> at all). SpeedUp-Plan (Gitea #28): removes a ~342ms render-blocking
|
|
// CSS request measured on throttled mobile.
|
|
inlineCss: true,
|
|
},
|
|
images: {
|
|
remotePatterns: [
|
|
{ protocol: "https", hostname: getSupabaseHostname() },
|
|
],
|
|
},
|
|
async headers() {
|
|
return [
|
|
{
|
|
source: "/(.*)",
|
|
headers: [
|
|
{ key: "X-Content-Type-Options", value: "nosniff" },
|
|
{ key: "X-Frame-Options", value: "DENY" },
|
|
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
|
|
{ key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=()" },
|
|
// HSTS intentionally NOT set here — Cloudflare (in front of the origin) already
|
|
// sends a stronger one (max-age=63072000; preload). Setting both resulted in two
|
|
// Strict-Transport-Security headers on every response; browsers only honor the
|
|
// first, so the app's weaker one was pure noise. If Cloudflare is ever removed
|
|
// from the path, re-add this header at the edge/proxy layer, not here.
|
|
],
|
|
},
|
|
];
|
|
},
|
|
};
|
|
|
|
export default withSentryConfig(withNextIntl(nextConfig), {
|
|
org: process.env.SENTRY_ORG,
|
|
project: process.env.SENTRY_PROJECT,
|
|
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
// Sourcemap upload currently fails against GlitchTip with a CSRF 403 on
|
|
// the releases API (confirmed server-side issue, not a build config
|
|
// problem — see commit history around 2026-08-14). Keeping silent so this
|
|
// known, non-fatal failure doesn't spam every build log; re-enable
|
|
// debug:true if investigating further.
|
|
silent: true,
|
|
sourcemaps: { disable: !process.env.SENTRY_AUTH_TOKEN },
|
|
disableLogger: true,
|
|
});
|