namespace DeepDrftPublic.Client.Common; /// /// Site-wide SEO defaults (Phase 22). These are non-secret brand constants — a single canonical origin, /// the site name/suffix, the fallback share image, the social links — sourced once and injected into /// SeoHead so no page re-declares them. Registered as a singleton in /// , which runs in both the server prerender and the /// WASM passes, so both passes resolve identical values (the double-render-identity requirement, §5/AC6). /// /// /// is the load-bearing field: absolute canonical / og:url / og:image /// origins all come from here, never from a browser API — there is no window.location during /// server prerender, and the request host is unreliable behind the nginx reverse proxy (§5, OQ1). /// /// public sealed record SeoOptions { /// Canonical production origin, no trailing slash. Absolute URLs are this + a resolved path (OQ1). public string BaseUrl { get; init; } = "https://deepdrft.com"; /// The brand name used in og:site_name, application-name, and the JSON-LD MusicGroup. public string SiteName { get; init; } = "Deep DRFT"; /// Appended to a page's bare title as "{Title} · {TitleSuffix}". Resolves the prior suffix inconsistency (OQ4). public string TitleSuffix { get; init; } = "Deep DRFT"; /// Fallback meta/OG description for pages that supply none. public string DefaultDescription { get; init; } = "Deep DRFT — an electronic music collective from Charleston, South Carolina. Studio cuts, live sessions, and DJ mixes."; /// /// Absolute or root-relative URL of the default 1200×630 share image used when a page has no cover (OQ2). /// A placeholder path until the real asset is dropped in; swapping it is a one-value change. /// public string DefaultImageUrl { get; init; } = "/img/og-default.png"; /// OG locale. Optional surface tag. public string Locale { get; init; } = "en_US"; /// The collective's primary genre, used in the MusicGroup JSON-LD node. public string Genre { get; init; } = "Electronic"; // The default robots directive is NOT a static option — it is environment-gated (Production → // index,follow; non-production → noindex,nofollow) via SeoEnvironment so the beta/staging site is // never crawled. A page's explicit SeoModel.Robots still overrides that default. /// /// Public social profile URLs for the MusicGroup sameAs array (OQ3). Instagram only — /// no Twitter/X account exists, so no twitter:site/twitter:creator handle is emitted. /// public IReadOnlyList SameAs { get; init; } = ["https://instagram.com/deepdrft.music"]; }