diff --git a/.env.example b/.env.example index 284d22e..8bc44b2 100644 --- a/.env.example +++ b/.env.example @@ -25,6 +25,11 @@ PAYLOAD_SECRET=replace-with-a-long-random-secret # Generate with: openssl rand -hex 32 MEETING_SESSION_SECRET=replace-with-a-long-random-secret +# Salts the daily-rotating, non-reversible visitor hash used for Analytics +# session grouping (kept separate from PAYLOAD_SECRET on purpose, see +# lib/analytics/salt.ts). Generate with: openssl rand -hex 32 +ANALYTICS_SALT_SECRET=replace-with-a-long-random-secret + # Sent as "Authorization: Bearer " by the external cron job that # triggers /api/cron/event-reminders. Generate with: openssl rand -hex 32 CRON_SECRET=replace-with-a-long-random-secret diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index c5d1cee..8e9eb37 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -150,7 +150,7 @@ See `.env.example` for the full, commented list. `setup.sh` writes the real file | Variable | Purpose | | --- | --- | | `DATABASE_URI`, `POSTGRES_*` | Postgres connection | -| `PAYLOAD_SECRET`, `MEETING_SESSION_SECRET`, `CRON_SECRET` | Auto-generated, never overwritten afterwards | +| `PAYLOAD_SECRET`, `MEETING_SESSION_SECRET`, `ANALYTICS_SALT_SECRET`, `CRON_SECRET` | Auto-generated, never overwritten afterwards | | `NEXT_PUBLIC_SERVER_URL` | Public URL of the site | | `SMTP_*` | The existing ANOUMA mail system | | `STUN_SERVER`, `TURN_SERVER`, `TURN_USERNAME`, `TURN_PASSWORD` | WebRTC ICE servers | diff --git a/app/(frontend)/layout.tsx b/app/(frontend)/layout.tsx index 94afb7d..2fbd36a 100644 --- a/app/(frontend)/layout.tsx +++ b/app/(frontend)/layout.tsx @@ -2,10 +2,11 @@ import type { Metadata } from "next"; import { Cormorant_Garamond, Inter } from "next/font/google"; import { Navbar } from "@/components/Navbar"; import { Footer } from "@/components/Footer"; +import { Analytics } from "@/components/Analytics"; import { siteConfig } from "@/lib/site"; import { getOffers } from "@/lib/payload/content"; import { getCurrentCustomer } from "@/lib/auth/customer"; -import { getBookingSettingsGlobal, getContactGlobal, getSEOSettingsGlobal } from "@/lib/payload/globals"; +import { getBookingSettingsGlobal, getContactGlobal, getCookieSettingsGlobal, getSEOSettingsGlobal } from "@/lib/payload/globals"; import { getSiteUrl } from "@/lib/seo/config"; import { JsonLd, organizationOrLocalBusinessJsonLd, websiteJsonLd } from "@/lib/seo/jsonld"; import "./globals.css"; @@ -30,7 +31,7 @@ export const metadata: Metadata = { metadataBase: new URL(siteConfig.domain), title: { default: siteConfig.title, - template: `%s — ${siteConfig.name}`, + template: `%s – ${siteConfig.name}`, }, description: siteConfig.description, openGraph: { @@ -51,13 +52,14 @@ export const metadata: Metadata = { }; export default async function RootLayout({ children }: LayoutProps<"/">) { - const [offers, customer, seoSettings, bookingSettings, contact, siteUrl] = await Promise.all([ + const [offers, customer, seoSettings, bookingSettings, contact, siteUrl, cookieSettings] = await Promise.all([ getOffers(), getCurrentCustomer(), getSEOSettingsGlobal(), getBookingSettingsGlobal(), getContactGlobal(), getSiteUrl(), + getCookieSettingsGlobal(), ]); return ( @@ -84,6 +86,14 @@ export default async function RootLayout({ children }: LayoutProps<"/">) { {children}