Every page in the template needs the same boilerplate: strip the trailing slash fromDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Ozcaar/real-estate-template/llms.txt
Use this file to discover all available pages before exploring further.
siteUrl, build an absolute URL for the canonical link, resolve the social image, set the Twitter card type, and read the active locale for og:locale. usePageSeo() centralizes all of that infrastructure so pages never duplicate it. Each page still calls useSeoMeta() and useHead() itself — keeping the title, description, and any page-specific overrides (like ogType: 'article' on the property detail page) explicitly readable at the call site. useJsonLd() is a thin companion that handles the <script type="application/ld+json"> boilerplate so pages just pass their schema.org payload.
usePageSeo is not added to Nuxt’s auto-import imports.dirs in nuxt.config.ts. It must be imported explicitly on every page. This is intentional: SEO setup is a page-level concern and the explicit import makes every call site auditable. useJsonLd is in ~/core/composables/ which is listed in imports.dirs, but the same convention of explicit imports is recommended.usePageSeo()
Signature
Options
The social image for Open Graph and Twitter cards. Accepts a static string or a
ref / computed so a per-record page (e.g. the property detail page) can pass a reactive coverImage. When omitted, usePageSeo() falls back to the agency logo, and then to the defaultSeoConfig.ogImage placeholder (/images/logo.svg) when the logo is also empty.Return Value
The normalized site base URL from
runtimeConfig.public.siteUrl, with any trailing slash stripped. Empty string when NUXT_PUBLIC_SITE_URL is not set (e.g. during local development).Converts a public path or relative URL into an absolute URL by prepending
siteUrl. Returns the input unchanged when the input is already an absolute http(s):// URL, when siteUrl is empty, or when path is an empty string.The absolute canonical URL for the current route:
siteUrl + route.path. Returns null when siteUrl is not configured — callers should omit the <link rel="canonical"> and og:url tags in that case rather than emitting a broken relative URL.The absolute URL for the Open Graph social image. Resolves through
options.image → agency.logo → defaultSeoConfig.ogImage, then makes the path absolute via toAbsoluteUrl.The absolute URL for the Twitter card social image. Follows the same resolution chain as
ogImage.The Twitter card type from
defaultSeoConfig.twitterCard. Currently 'summary_large_image' for the entire site.The active locale code from
useI18n().locale (e.g. 'en', 'es'). Used as the og:locale value.The agency display name from
useSiteConfig().value.agency.name. Used as the og:site_name value.Full Page SEO Pattern
usePageSeo() provides the building blocks; each page assembles the final tags with useSeoMeta() and useHead(). This separation keeps page-specific options — like ogType, a custom description, or a per-property cover image — explicitly visible at the call site.
Property detail page — per-record social image
The detail page passes the property’s owncoverImage as the image option so every listing gets a unique Open Graph share preview:
siteUrl and development environments
siteUrl is populated from the NUXT_PUBLIC_SITE_URL environment variable. It is intentionally empty by default so the project builds and runs without any configuration. When siteUrl is empty:
canonicalUrlreturnsnulltoAbsoluteUrl()returns the input path unchangedog:urland<link rel="canonical">are omitted from the rendered HTML
localhost is worse than no canonical at all.
Set
NUXT_PUBLIC_SITE_URL=https://yourdomain.com in your production environment (or .env file) to enable canonical links and absolute Open Graph URLs.useJsonLd()
<script type="application/ld+json"> block into the page <head>. It wraps Nuxt’s useHead with the correct innerHTML callback pattern so the JSON is serialized at SSR time, matching Nuxt’s head-management lifecycle.
Signature
The schema.org JSON-LD payload. Accepts a plain object, a
ref, or a getter function (() => ({ ... })) so callers can compose the payload reactively from computed values without ceremony. The value is serialized with JSON.stringify at render time.Usage
CalluseJsonLd once in the page <script setup> block with a computed that builds the schema.org payload:
JSON-LD Schemas by Page
Each page in the template emits a schema.org structured data block appropriate to its content. The table below maps every route to its schema type, matching the actual@type values in the source.
| Route | Schema @type | Notes |
|---|---|---|
/ (home) | RealEstateAgent | Agency identity node — @id set to toAbsoluteUrl('/') for cross-page graph consistency |
/properties | ItemList (of ListItem) | One ListItem per visible property in the current filtered result set |
/properties/[slug] | RealEstateListing + ItemList (of ListItem) | Detail page: RealEstateListing with floorSize as a QuantitativeValue carrying an explicit UN/CEFACT unitCode, plus a separate ItemList of ListItem for the related properties (one per related card; itemListElement is [] when there are no related properties) |
/agents | ItemList (of Person) | Each Person has a worksFor: RealEstateAgent back-reference to the agency home page |
/contact | ContactPage | mainEntity is a RealEstateAgent node with the same @id as the home page |
/about | AboutPage | mainEntity is a RealEstateAgent node consistent with the home and contact pages |
Cross-page entity consistency
The home page, contact page, and about page all emit aRealEstateAgent node whose @id is toAbsoluteUrl('/'). This tells Google’s knowledge graph that all three nodes refer to the same agency entity, allowing it to merge the information (address from the contact page, social links from the home page, description from the about page) into a single rich result.
Agents page — ItemList of Person
Each agent is wrapped in a ListItem with a Person item. The worksFor field points back to the agency’s home-page node: