Skip to main content

Documentation 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.

Every piece of agency-specific identity — from the display name and logo path down to the WhatsApp number and which site modules are active — lives in one place: app/config/agencies/default.agency.ts. Components never hardcode any of these values. Instead they read the config through the useSiteConfig() composable, which returns the validated, fully-typed object that site.config.ts builds at module load. The result is a clean contract: rebrand the site by editing one file, and every layout, header, footer, SEO tag, and structured-data block updates automatically.

The single-file approach

site.config.ts imports defaultAgencyConfig, runs it through validateAgencyConfig(), resolves the matching theme, and exports the combined siteConfig object. Every consumer calls useSiteConfig() — nothing is passed through props, environment variables, or hardcoded strings in templates.
app/config/site.config.ts
import { defaultAgencyConfig } from './agencies/default.agency'
import { validateAgencyConfig } from './agencies/agency.schema'
import { defaultI18nLocales } from '~/config/i18n'
import { resolveTheme, themes } from '~/themes'

const activeAgency = defaultAgencyConfig

const { agency: validatedAgency, warnings } = validateAgencyConfig(activeAgency, {
  themes,
  i18nLocales: defaultI18nLocales,
})

for (const warning of warnings) {
  console.warn(`[agency] ${warning}`)
}

export const siteConfig: SiteConfig = {
  agency: validatedAgency,
  theme: resolveTheme(validatedAgency.theme),
}

Single-agency vs. multi-agency setup

Option A — Single agency

Edit app/config/agencies/default.agency.ts in place. This is the recommended path when the deployment serves exactly one agency and you never need to switch.

Option B — Multi-agency ready

Create a new file such as acme.agency.ts, then swap the import constant in site.config.ts. No component changes required.

Option B step-by-step

1

Create a new agency file

Copy default.agency.ts and rename it after the agency:
app/config/agencies/acme.agency.ts
import type { AgencyConfig } from '~/types/agency.types'

export const acmeAgencyConfig: AgencyConfig = {
  id: 'acme',
  name: 'Acme Real Estate',
  slogan: 'The right property, every time',
  logo: '/images/logo.svg',
  favicon: '/favicon.ico',
  theme: 'default',
  defaultLocale: 'en',
  availableLocales: ['en', 'es'],
  currency: 'USD',
  measurementUnit: 'imperial',
  contact: {
    phone: '1-800-555-9999',
    whatsapp: '18005559999',
    email: 'hello@acme-realestate.com',
    address: '500 Commerce Blvd, Austin, TX 78701',
    businessHours: 'Mon–Sat 8am–6pm',
  },
  social: {
    facebook: 'https://www.facebook.com/acmerealestate',
    instagram: 'https://www.instagram.com/acmerealestate',
  },
  modules: {
    properties: true,
    developments: false,
    agents: true,
    blog: false,
    testimonials: true,
    contact: true,
  },
}
2

Update the import in site.config.ts

app/config/site.config.ts
- import { defaultAgencyConfig } from './agencies/default.agency'
+ import { acmeAgencyConfig } from './agencies/acme.agency'

- const activeAgency = defaultAgencyConfig
+ const activeAgency = acmeAgencyConfig
3

Restart the dev server

Run pnpm dev. The header, footer, contact page, SEO meta, and every other consumer will reflect the new agency immediately.

Complete field reference

The full defaultAgencyConfig shipped with the template is shown below, followed by a detailed description of every field.
app/config/agencies/default.agency.ts
export const defaultAgencyConfig: AgencyConfig = {
  id: 'default',
  name: 'Real Estate Agency',
  slogan: 'Find your ideal property',
  logo: '/images/logo.svg',
  favicon: '/favicon.ico',
  theme: 'default',
  defaultLocale: 'en',
  availableLocales: ['en', 'es'],
  currency: 'USD',
  measurementUnit: 'metric',
  contact: {
    phone: '1-800-555-1234',
    whatsapp: '1-800-555-1234',
    email: 'example@email.com',
    address: '123 Main Street, Anytown, USA',
    businessHours: 'Mon-Fri 9am-5pm',
  },
  social: {
    facebook: 'http://www.facebook.com/youragency',
    instagram: 'http://www.instagram.com/youragency',
    linkedin: 'http://www.linkedin.com/youragency',
    tiktok: 'http://www.tiktok.com/youragency',
    youtube: 'http://www.youtube.com/youragency',
  },
  modules: {
    properties: true,
    developments: true,
    agents: true,
    blog: false,
    testimonials: true,
    contact: true,
  },
}

Identity fields

id
string
required
Unique slug identifying this agency. Used internally and as the data-agency attribute. Must be a non-empty string.
name
string
required
Agency display name. Appears in the header, footer, page titles, SEO meta, and JSON-LD structured data. Must contain at least one non-whitespace character.
slogan
string
Short marketing slogan shown in the hero and footer tagline area. Optional — omit it to leave the space empty.
Public path to the agency logo image. Must start with / (file is served from the public/ directory). Example: /images/logo.svg. The validator throws if the path does not begin with a forward slash.
favicon
string
Public path to the favicon file. Must start with / if provided. Defaults to /favicon.ico when omitted.

Theme and locale fields

theme
string
required
ID of the theme registered in app/themes/index.ts. The validator throws a ZodError when this ID is not found in the theme registry. See Theming for how to create and register a new theme.
defaultLocale
string
required
BCP 47 locale code used on first visit. Must be present in both availableLocales and the i18n locale list registered in nuxt.config.ts. Example: 'en'.
availableLocales
string[]
required
Array of locale codes the agency supports. Every code must be registered in the Nuxt i18n config. The AppLanguageSwitcher component builds its list from this array. Example: ['en', 'es'].

Currency and measurement

currency
string
required
ISO 4217 currency code used to format property prices throughout the site. Examples: 'USD', 'MXN', 'EUR', 'GBP'. The validator emits a console.warn if the value is not exactly three uppercase letters but does not throw — allowing transitional codes.
measurementUnit
"metric" | "imperial"
required
Unit system for property area display. 'metric' renders areas as m²; 'imperial' renders them as ft². Individual property records can override this with their own sizeUnit field — the template never auto-converts between units.

Contact object

contact.phone
string
required
Primary phone number shown in the header, footer, and contact page. Include the country code for international dialing.
contact.whatsapp
string
required
WhatsApp number for the floating CTA and contact page. The template strips non-digit characters automatically when building the wa.me deep link. Include the country code (e.g. '15551234567' or '+1 555 123 4567').
contact.email
string
required
Agency contact email. Shown on the contact page and used in JSON-LD structured data. The validator prints a warning if the value does not look like a valid email address.
contact.address
string
required
Physical office address shown on the contact page and in structured data.
contact.businessHours
string
Human-readable office hours string, e.g. 'Mon–Fri 9am–5pm'. Optional; the contact page hides this field when it is omitted.

Social object

All social fields are optional. The footer hides icons for any platform whose value is omitted or empty. Provide full HTTPS URLs for best SEO practice — the validator warns (but does not throw) when a URL is supplied without any recognized prefix (http://, https://, or www.).
social.facebook
string
Full Facebook page URL.
social.instagram
string
Full Instagram profile URL.
social.linkedin
string
Full LinkedIn company or profile URL.
social.tiktok
string
Full TikTok profile URL.
social.youtube
string
Full YouTube channel URL.

Modules object

modules.properties
boolean
required
Enables the property catalog (/properties). When false, the nav entry, footer link, homepage featured section, and sitemap entries for properties are all hidden.
modules.developments
boolean
required
Enables the developments portfolio (/developments). When false, the nav entry, footer link, and homepage developments section are hidden.
modules.agents
boolean
required
Enables the team directory (/agents). When false, the nav entry and footer link are hidden.
modules.blog
boolean
required
Enables the blog. Ships as false because the blog feature is not yet implemented — flip to true once an implementation is added.
modules.testimonials
boolean
required
Enables the testimonials section on the homepage. When false, the section is hidden even if testimonial data is present.
modules.contact
boolean
required
Enables the contact page (/contact) nav and footer link, and the homepage contact CTA section.

Validation at module load

validateAgencyConfig() is called synchronously when site.config.ts is first imported — before the Nuxt app mounts. It runs two validation passes: Structural checks (throw a ZodError):
  • id, name, logo, and theme are non-empty strings
  • logo and favicon start with /
  • measurementUnit is exactly 'metric' or 'imperial'
  • defaultLocale is present in availableLocales
  • defaultLocale and every entry in availableLocales are registered in the Nuxt i18n locale list
  • theme is a key in the themes registry
Format warnings (printed via console.warn, never throw):
  • contact.email does not look like a standard email address
  • currency is not a three-uppercase-letter ISO 4217 code
  • Any social.* URL does not start with https://, http://, or www.
The shipped default.agency.ts produces no format warnings at startup. All five social placeholder URLs already begin with http://, which satisfies the URL_PREFIX_RE check in the validator. Format warnings appear only when a social URL is supplied without any URL prefix — for example, 'facebook.com/youragency' would trigger [agency] social.facebook "facebook.com/youragency" should start with "http://", "https://" or "www.". Upgrade your placeholder URLs to https:// when rebranding to follow best practice.
If the app fails to start with a ZodError, the error message lists every failing field and a clear description of what is wrong. The most common causes are: theme set to an ID not yet registered in app/themes/index.ts, defaultLocale not listed in availableLocales, or a logo path that does not start with /.

Build docs developers (and LLMs) love