diff --git a/apps/blog/app/layout.tsx b/apps/blog/app/layout.tsx index 9575e635ace7b695380dfd300e2db9ff8d6dce7a..66710cba7cc2da3a84ecfd942de356f6547fed24 100644 --- a/apps/blog/app/layout.tsx +++ b/apps/blog/app/layout.tsx @@ -2,7 +2,7 @@ import '@hive/tailwindcss-config/globals.css'; import { ReactNode } from 'react'; import Script from 'next/script'; import { Metadata } from 'next'; -import { cookies } from 'next/headers'; +import { cookies, headers } from 'next/headers'; import MainBar from '../features/layouts/site-header/main-bar'; import ClientEffects from '../features/layouts/site-header/client-effects'; import { Providers } from '../features/layouts/providers'; @@ -11,6 +11,15 @@ import VisitLoggerClient from '../lib/visit-logger-client'; // Get basePath from build-time environment const basePath = process.env.NEXT_PUBLIC_BASE_PATH || ''; +/** + * Get the CSP nonce from the request headers. + * The nonce is generated in middleware and passed via x-nonce header. + */ +function getNonce(): string { + const headersList = headers(); + return headersList.get('x-nonce') || ''; +} + const SITE_DESC = 'Communities without borders. A social network owned and operated by its users, powered by Hive.'; @@ -48,6 +57,9 @@ export default async function RootLayout({ children }: { children: ReactNode }) const locale = cookieStore.get('NEXT_LOCALE')?.value || 'en'; const isRTL = locale === 'ar'; + // Get nonce for CSP-compliant script loading + const nonce = getNonce(); + return ( @@ -60,7 +72,7 @@ export default async function RootLayout({ children }: { children: ReactNode }) -