Files
anouma/payload.config.ts
T
maroandClaude Sonnet 5 1cd15aff25 Add email verification, personal calendar feed, and full SEO implementation
- Customer accounts now require email verification (hashed, single-use,
  time-limited tokens) before they can request/confirm bookings, with
  resend flows on login/account/booking widget and rate limiting.
- Admins get a private, rotatable iCalendar (ICS) subscription feed of
  their confirmed bookings and public events, timezone-correct for
  Europe/Berlin including DST, never exposing meeting passwords.
- Adds a full SEO layer: per-page canonical/OG/Twitter metadata with
  CMS-editable overrides and content-derived fallbacks, a dynamic
  sitemap.xml and robots.txt driven by real published content, JSON-LD
  (Organization/LocalBusiness, WebSite, WebPage, BreadcrumbList, Service,
  Event, BlogPosting) that never fabricates data, and a CMS-managed
  redirect table for changed slugs.
- Global ANOUMA-naming audit: the brand name is never used to label
  personal account/calendar areas anywhere in the app, CMS, or emails.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 22:57:31 +02:00

88 lines
2.7 KiB
TypeScript

import { postgresAdapter } from "@payloadcms/db-postgres";
import { lexicalEditor } from "@payloadcms/richtext-lexical";
import path from "path";
import { buildConfig } from "payload";
import { fileURLToPath } from "url";
import sharp from "sharp";
import { Users } from "@/collections/Users";
import { Media } from "@/collections/Media";
import { Events } from "@/collections/Events";
import { Posts } from "@/collections/Posts";
import { Offers } from "@/collections/Offers";
import { EventRegistrations } from "@/collections/EventRegistrations";
import { Customers } from "@/collections/Customers";
import { Availability } from "@/collections/Availability";
import { AvailabilityOverrides } from "@/collections/AvailabilityOverrides";
import { BookingRequests } from "@/collections/BookingRequests";
import { Redirects } from "@/collections/Redirects";
import { Home } from "@/globals/Home";
import { About } from "@/globals/About";
import { AngeboteIntro } from "@/globals/AngeboteIntro";
import { AktuellesIntro } from "@/globals/AktuellesIntro";
import { Contact } from "@/globals/Contact";
import { Booking } from "@/globals/Booking";
import { MeetingSettings } from "@/globals/MeetingSettings";
import { BookingSettings } from "@/globals/BookingSettings";
import { SEOSettings } from "@/globals/SEOSettings";
const filename = fileURLToPath(import.meta.url);
const dirname = path.dirname(filename);
export default buildConfig({
serverURL: process.env.NEXT_PUBLIC_SERVER_URL || "http://localhost:3000",
admin: {
user: Users.slug,
importMap: {
baseDir: path.resolve(dirname),
},
meta: {
titleSuffix: "— Anouma Admin",
},
components: {
afterNavLinks: ["/components/admin/CalendarNavLink#CalendarNavLink"],
views: {
kalender: {
Component: "/components/admin/AdminCalendarView#AdminCalendarView",
path: "/kalender",
exact: true,
meta: { title: "Kalender" },
},
},
},
},
collections: [
Users,
Customers,
Media,
Events,
Posts,
Offers,
EventRegistrations,
Availability,
AvailabilityOverrides,
BookingRequests,
Redirects,
],
globals: [Home, About, AngeboteIntro, AktuellesIntro, Contact, Booking, MeetingSettings, BookingSettings, SEOSettings],
editor: lexicalEditor(),
secret: process.env.PAYLOAD_SECRET || "",
typescript: {
outputFile: path.resolve(dirname, "payload-types.ts"),
},
db: postgresAdapter({
pool: {
connectionString: process.env.DATABASE_URI || "",
},
}),
sharp,
// Server-side upload size limit; the Media collection restricts formats.
upload: {
limits: {
fileSize: 10 * 1024 * 1024, // 10 MB
},
},
plugins: [],
});