docs
    re-site-kit: Formatting and JSON-LD
    v0.6.0.md

    Formatting and JSON-LD

    The helpers the components use to turn a listing into display text and schema.org markup. They're exported so your own layouts can say things the same way. All of them are pure functions from the package root, safe in server and client components alike.

    import {
      formatPrice,
      formatSpecs,
      formatLocation,
      formatStreet,
      buildListingJsonLd,
      safeJsonLdString,
    } from '@sonordev/re-site-kit'

    Display text

    Each takes a RealEstateListing and returns a string, empty when there's nothing to show.

    HelperExample outputHow it's built
    formatPrice(listing)$349,900The feed's own price_display when it has one (used as is, e.g. "From the low $300s"). Otherwise price as currency in listing.currency (USD when missing), with no cents. Empty when there's no price.
    formatSpecs(listing)3 bd · 2.5 ba · 1,850 sqftBedrooms, bathrooms and square feet, joined with " · ". Each part is skipped when it's missing or zero, so a studio shows no bedroom count.
    formatLocation(listing)Springfield, IL 62701City and state joined with ", ", then the ZIP, skipping whatever's missing.
    formatStreet(listing)12 Oak St #4BThe street address, plus # and the unit number when there's one.
    <p className="listing-line">
      {formatPrice(listing)} · {formatSpecs(listing)}
      <br />
      {formatStreet(listing)}, {formatLocation(listing)}
    </p>

    Price uses US formatting (en-US). Square footage uses the runtime's default number formatting, which on a typical server gives "1,850".

    buildListingJsonLd

    buildListingJsonLd(listing: RealEstateListing, options?: ListingJsonLdOptions): Record<string, unknown>

    Builds the schema.org RealEstateListing object that ListingSchema renders. Use it directly when you want to add to the markup or combine it with your own graph.

    OptionTypeWhat it does
    urlstringThe listing page's canonical absolute URL.
    siteNamestringYour brokerage's name, used as the provider when the listing has no listing_office_name.

    What it sets, each only when the listing has the value:

    PropertyFrom
    @typeAlways RealEstateListing.
    nameThe street address (formatStreet).
    urloptions.url.
    datePostedlisting_date.
    descriptionThe first 500 characters of description.
    imageUp to eight photos.
    offersAn Offer with price and priceCurrency (USD when missing), availability: https://schema.org/InStock for active listings only, and url. Left out when there's no price.
    providerA RealEstateAgent named after listing_office_name, or options.siteName.
    aboutThe home itself: see below.

    about describes the property, with its name (the street address), a PostalAddress (street, city, state, ZIP, and country, which defaults to US), and geo coordinates when the listing has both latitude and longitude. Its @type comes from the property type, and the type decides which of the home's facts it carries, since schema.org only defines numberOfBedrooms, numberOfFullBathrooms, yearBuilt and floorSize (in square feet) on some types:

    property_typeabout['@type']Facts it carries
    single_familySingleFamilyResidenceAll four
    condoApartmentAll four
    townhouseHouseAll four
    multi_familyApartmentComplexnumberOfBedrooms only
    landPlaceNone
    commercialPlaceNone
    other, or noneAccommodationAll four

    A few of these are judgment calls, because schema.org doesn't have a type for everything an MLS does:

    • Land is a Place. schema.org has no type for a lot, and a lot isn't an Accommodation, the type homes and apartments belong to.
    • A townhouse is a House. There's no townhouse type. SingleFamilyResidence is a kind of House too, but MLS feeds list townhouses separately from single-family homes, so the markup doesn't claim the narrower type.
    • A listing with no type is an Accommodation, the type that House and Apartment both come from, so its bedrooms and square footage still make it into the markup.

    safeJsonLdString

    safeJsonLdString(value: Record<string, unknown>): string

    Serializes JSON-LD for a <script> tag, escaping every < so text inside a listing can never close the script element. Use it whenever you render JSON-LD yourself:

    import { buildListingJsonLd, safeJsonLdString, type RealEstateListing } from '@sonordev/re-site-kit'
    
    export function MyListingSchema({ listing, url }: { listing: RealEstateListing; url: string }) {
      const jsonLd = buildListingJsonLd(listing, { url, siteName: 'Example Realty' })
      jsonLd.mainEntityOfPage = url
      return (
        <script
          type="application/ld+json"
          dangerouslySetInnerHTML={{ __html: safeJsonLdString(jsonLd) }}
        />
      )
    }

    Metadata and stats

    Two more helpers live with the features they belong to: listingMetadata (Next.js metadata for a listing page) in Listing pages, and summarizeListings and monthlyHoa in Market snapshot.