@reblu/site-contracts 1.11.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @reblu/site-contracts
2
2
 
3
+ ## 1.12.0
4
+
5
+ ### Minor Changes
6
+
7
+ - fd17765: Site-level SEO (REB-651). `Config` gains optional `seoTitle`, `seoDescription` and `canonicalUrl`, all `string | null`. `seoTitle` and `seoDescription` are the site's own search title and description (the home page), apart from `siteName` and `siteDescription`; `null` means never set, so fall back to `siteName` and `siteDescription`. A set `seoTitle` is used as-is and never gets the template suffix. `canonicalUrl` is the site's https origin (no trailing slash), to use as Next's `metadataBase`. Purely additive.
8
+
3
9
  ## 1.11.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -169,6 +169,21 @@ another `"… · Brand"` template. For list/index routes, or an older API withou
169
169
  `@reblu/site-next/seo`. Both fields are optional in the types so the minor stays
170
170
  additive; `seoTitle`/`metaTitle` are unchanged.
171
171
 
172
+ ### Site SEO title, description and canonical URL (REB-651)
173
+
174
+ `Config` carries the site's own search fields, apart from the identity fields
175
+ `siteName`/`siteDescription` (which stay short for breadcrumbs and chrome):
176
+
177
+ - `seoTitle` — the home page title. When set it is used **as-is**, never
178
+ suffixed by `seoTitleTemplate`. `null` → use `siteName`.
179
+ - `seoDescription` — the home page description. `null` → `siteDescription`.
180
+ - `canonicalUrl` — the site origin, `https://…` with no trailing slash, or
181
+ `null`. Use it as Next's `metadataBase` so relative Open Graph paths resolve.
182
+
183
+ They are served raw (`null` = never set). `buildMetadata({ config, home: true })`
184
+ from `@reblu/site-next/seo` applies the fallbacks for you. All three are
185
+ optional in the types so the minor stays additive.
186
+
172
187
  ## How the types stay correct
173
188
 
174
189
  The types are re-derived from the response schemas that live in the Reblu API
package/dist/index.d.cts CHANGED
@@ -45,7 +45,7 @@ export type BlogSlug = { slug: string; updatedAt: string;}
45
45
 
46
46
  export type BlogTag = { id: string; name: string; slug: string; color: string;}
47
47
 
48
- export type Config = { siteName: string; siteDescription: string | null; language: string | null; contactEmail: string | null; keywords: string[]; businessType: string | null; isSetupComplete: boolean; logoLightExpandedUrl: string | null; logoDarkExpandedUrl: string | null; logoLightSmallUrl: string | null; logoDarkSmallUrl: string | null; ogImageUrl: string | null; owner: { name: string | null; email: string | null; jobTitle: string | null; }; business: { name: string | null; }; address: { street: string | null; city: string | null; region: string | null; postalCode: string | null; country: string | null; telephone: string | null; lat: number | null; lng: number | null; } | null; fiscal: { taxId: string | null; taxIdKind: "NIF" | "CIF" | null; legalName: string | null; registry: { name: string; number: string; } | null; } | null; social: { linkedin: string | null; twitter: string | null; facebook: string | null; instagram: string | null; youtube: string | null; } | null; metadata: unknown; openingHours: { ranges: { days: ("MON" | "TUE" | "WED" | "THU" | "FRI" | "SAT" | "SUN")[]; opens: string; closes: string; }[]; note?: string | undefined; } | null; contactFormMode: "NOT_CONFIGURED" | "DISABLED" | "DB_ONLY" | "WEBHOOK" | "RESEND"; features: Record<string, unknown>; seoTitleTemplate?: string | undefined;}
48
+ export type Config = { siteName: string; siteDescription: string | null; language: string | null; contactEmail: string | null; keywords: string[]; businessType: string | null; isSetupComplete: boolean; logoLightExpandedUrl: string | null; logoDarkExpandedUrl: string | null; logoLightSmallUrl: string | null; logoDarkSmallUrl: string | null; ogImageUrl: string | null; owner: { name: string | null; email: string | null; jobTitle: string | null; }; business: { name: string | null; }; address: { street: string | null; city: string | null; region: string | null; postalCode: string | null; country: string | null; telephone: string | null; lat: number | null; lng: number | null; } | null; fiscal: { taxId: string | null; taxIdKind: "NIF" | "CIF" | null; legalName: string | null; registry: { name: string; number: string; } | null; } | null; social: { linkedin: string | null; twitter: string | null; facebook: string | null; instagram: string | null; youtube: string | null; } | null; metadata: unknown; openingHours: { ranges: { days: ("MON" | "TUE" | "WED" | "THU" | "FRI" | "SAT" | "SUN")[]; opens: string; closes: string; }[]; note?: string | undefined; } | null; contactFormMode: "NOT_CONFIGURED" | "DISABLED" | "DB_ONLY" | "WEBHOOK" | "RESEND"; features: Record<string, unknown>; seoTitleTemplate?: string | undefined; seoTitle?: string | null | undefined; seoDescription?: string | null | undefined; canonicalUrl?: string | null | undefined;}
49
49
 
50
50
  export type ConfigAddress = { street: string | null; city: string | null; region: string | null; postalCode: string | null; country: string | null; telephone: string | null; lat: number | null; lng: number | null;}
51
51
 
package/dist/index.d.ts CHANGED
@@ -45,7 +45,7 @@ export type BlogSlug = { slug: string; updatedAt: string;}
45
45
 
46
46
  export type BlogTag = { id: string; name: string; slug: string; color: string;}
47
47
 
48
- export type Config = { siteName: string; siteDescription: string | null; language: string | null; contactEmail: string | null; keywords: string[]; businessType: string | null; isSetupComplete: boolean; logoLightExpandedUrl: string | null; logoDarkExpandedUrl: string | null; logoLightSmallUrl: string | null; logoDarkSmallUrl: string | null; ogImageUrl: string | null; owner: { name: string | null; email: string | null; jobTitle: string | null; }; business: { name: string | null; }; address: { street: string | null; city: string | null; region: string | null; postalCode: string | null; country: string | null; telephone: string | null; lat: number | null; lng: number | null; } | null; fiscal: { taxId: string | null; taxIdKind: "NIF" | "CIF" | null; legalName: string | null; registry: { name: string; number: string; } | null; } | null; social: { linkedin: string | null; twitter: string | null; facebook: string | null; instagram: string | null; youtube: string | null; } | null; metadata: unknown; openingHours: { ranges: { days: ("MON" | "TUE" | "WED" | "THU" | "FRI" | "SAT" | "SUN")[]; opens: string; closes: string; }[]; note?: string | undefined; } | null; contactFormMode: "NOT_CONFIGURED" | "DISABLED" | "DB_ONLY" | "WEBHOOK" | "RESEND"; features: Record<string, unknown>; seoTitleTemplate?: string | undefined;}
48
+ export type Config = { siteName: string; siteDescription: string | null; language: string | null; contactEmail: string | null; keywords: string[]; businessType: string | null; isSetupComplete: boolean; logoLightExpandedUrl: string | null; logoDarkExpandedUrl: string | null; logoLightSmallUrl: string | null; logoDarkSmallUrl: string | null; ogImageUrl: string | null; owner: { name: string | null; email: string | null; jobTitle: string | null; }; business: { name: string | null; }; address: { street: string | null; city: string | null; region: string | null; postalCode: string | null; country: string | null; telephone: string | null; lat: number | null; lng: number | null; } | null; fiscal: { taxId: string | null; taxIdKind: "NIF" | "CIF" | null; legalName: string | null; registry: { name: string; number: string; } | null; } | null; social: { linkedin: string | null; twitter: string | null; facebook: string | null; instagram: string | null; youtube: string | null; } | null; metadata: unknown; openingHours: { ranges: { days: ("MON" | "TUE" | "WED" | "THU" | "FRI" | "SAT" | "SUN")[]; opens: string; closes: string; }[]; note?: string | undefined; } | null; contactFormMode: "NOT_CONFIGURED" | "DISABLED" | "DB_ONLY" | "WEBHOOK" | "RESEND"; features: Record<string, unknown>; seoTitleTemplate?: string | undefined; seoTitle?: string | null | undefined; seoDescription?: string | null | undefined; canonicalUrl?: string | null | undefined;}
49
49
 
50
50
  export type ConfigAddress = { street: string | null; city: string | null; region: string | null; postalCode: string | null; country: string | null; telephone: string | null; lat: number | null; lng: number | null;}
51
51
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reblu/site-contracts",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "private": false,
5
5
  "description": "Public, dependency-free TypeScript types for the Reblu SITE API (types only — no Zod, no Prisma at runtime).",
6
6
  "license": "Apache-2.0",