# @sonordev/re-site-kit

Real estate listings for Sonor-powered Next.js sites: search and filters, a page for every listing, the MLS attribution IDX rules ask for, condo buildings, trending homes, and MCP tools a buyer's AI assistant can use. Sonor pulls the MLS feed and your site reads it with the same `SONOR_API_KEY` it already uses, so the site never holds an MLS credential.

Full docs live at [sonor.dev/re-site-kit](https://sonor.dev/re-site-kit).

## Built on site-kit

re-site-kit is an industry layer on top of [`@sonordev/site-kit`](https://sonor.dev/site-kit), not a second stack. site-kit already owns the data plane, analytics, visitor identity and forms, and this kit adds real estate rendering and meaning on top of them:

| Concern              | Who owns it                         | How re-site-kit uses it                                                                                                                     |
| -------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| Server data fetching | site-kit (`serverApiFetch`)         | Every fetcher in `/server` goes through it: one key, one retry and caching policy.                                                          |
| View analytics       | site-kit (`trackEvent`)             | `ListingViewTracker` sends a `listing_view` event on the standard pipeline, and Sonor ranks hot properties from it.                         |
| Lead forms           | site-kit (`ManagedForm`)            | `ListingInquiryForm` wraps it with the listing's details and a conversion event. Spam protection, routing and CRM attribution stay in core. |
| Agent tools          | site-kit (`@sonordev/site-kit/mcp`) | The `/mcp` subpath defines real estate tools; site-kit serves them.                                                                         |

If you find yourself adding transport, credentials or a provider to a real estate site, check site-kit first. It almost certainly has it.

## What's in it

- **Search:** `searchListings` with filters, sort and paging, a zero-JavaScript `ListingFilters` form and crawlable `ListingPagination`. [Search and filters](https://sonor.dev/re-site-kit/search)
- **Listing pages:** `getListing`, `getListingParams`, `listingMetadata`, `ListingDetail`, `ListingGallery` and schema.org JSON-LD. [Listing pages](https://sonor.dev/re-site-kit/listing-pages)
- **Cards and grids** that credit the listing brokerage by default. [Cards and grids](https://sonor.dev/re-site-kit/cards)
- **Hot properties** ranked from your own listing views. [Hot properties](https://sonor.dev/re-site-kit/hot-listings)
- **Buildings:** listings matched to your condo building pages, plus a market snapshot for any set of listings. [Buildings](https://sonor.dev/re-site-kit/buildings), [Market snapshot](https://sonor.dev/re-site-kit/market-snapshot)
- **Leads and compliance:** an inquiry form that carries the listing into the CRM, and IDX attribution. [Inquiry forms](https://sonor.dev/re-site-kit/inquiry-forms), [IDX compliance](https://sonor.dev/re-site-kit/idx)
- **MCP tools** so a buyer's AI assistant can search your listings and ask for a showing. [MCP tools](https://sonor.dev/re-site-kit/mcp)

## Requirements

- `@sonordev/site-kit` 4.3.0 or later, installed and mounted with `SiteKitLayout` (or your site's deferred analytics sibling). The MCP tools need site-kit 6.4.0 or later.
- Next.js App Router and React, at the versions your site-kit release supports.
- A Sonor project with the Real Estate module and a listing feed.
- `SONOR_API_KEY` in the environment. It's the only env var, and it stays server-side.

## Install

```bash
pnpm add @sonordev/re-site-kit
```

## Quickstart

A listings page with search, filters and paging, all server-rendered:

```tsx
// app/listings/page.tsx
import { searchListings } from '@sonordev/re-site-kit/server'
import { ListingFilters, ListingGrid, ListingPagination } from '@sonordev/re-site-kit'

type SearchParams = Promise<Record<string, string | string[] | undefined>>

export default async function ListingsPage({ searchParams }: { searchParams: SearchParams }) {
  // One value per parameter (a repeated ?city=…&city=… keeps the first).
  const params = Object.fromEntries(
    Object.entries(await searchParams).map(([key, v]) => [key, Array.isArray(v) ? v[0] : v]),
  )
  const { listings, pagination } = await searchListings({
    city: params.city,
    minPrice: params.min_price ? Number(params.min_price) : undefined,
    maxPrice: params.max_price ? Number(params.max_price) : undefined,
    page: params.page ? Number(params.page) : 1,
  })

  return (
    <main>
      <h1>Homes for sale</h1>
      <ListingFilters basePath="/listings" values={{ city: params.city }} />
      <ListingGrid listings={listings} hrefFor={(l) => (l.slug ? `/listings/${l.slug}` : null)} />
      <ListingPagination
        pagination={pagination}
        listingCount={listings.length}
        basePath="/listings"
        searchParams={params}
      />
    </main>
  )
}
```

`ListingFilters` is a plain GET form whose field names are the API's query parameters, so the page's `searchParams` flow straight back into `searchListings`, even with JavaScript off. The [Quickstart](https://sonor.dev/re-site-kit/quickstart) adds the listing detail page, the inquiry form and view tracking.

## Subpaths

| Import                         | What's there                                                                                                        |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `@sonordev/re-site-kit`        | Types, components that render on the server, format helpers, JSON-LD, the building registry and the market snapshot |
| `@sonordev/re-site-kit/server` | The server-only data layer: `searchListings`, `getListing`, `getHotListings` and friends                            |
| `@sonordev/re-site-kit/client` | `ListingGallery`, `ListingInquiryForm`, `ListingViewTracker`                                                        |
| `@sonordev/re-site-kit/mcp`    | `realEstateMcpTools`, `realEstateMcpServerInfo`                                                                     |

Every export is listed in the [Subpath map](https://sonor.dev/re-site-kit/exports).

## Docs

- [Quickstart](https://sonor.dev/re-site-kit/quickstart)
- [Search and filters](https://sonor.dev/re-site-kit/search)
- [Listing pages](https://sonor.dev/re-site-kit/listing-pages)
- [Cards and grids](https://sonor.dev/re-site-kit/cards)
- [Hot properties](https://sonor.dev/re-site-kit/hot-listings)
- [Buildings and the registry](https://sonor.dev/re-site-kit/buildings)
- [Market snapshot](https://sonor.dev/re-site-kit/market-snapshot)
- [Inquiry forms](https://sonor.dev/re-site-kit/inquiry-forms)
- [IDX compliance](https://sonor.dev/re-site-kit/idx)
- [MCP tools](https://sonor.dev/re-site-kit/mcp)
- [Formatting and JSON-LD](https://sonor.dev/re-site-kit/formatting)
- [Types](https://sonor.dev/re-site-kit/types)
- [Subpath map](https://sonor.dev/re-site-kit/exports)
- [Styling and performance](https://sonor.dev/re-site-kit/styling)
- [Changelog](https://sonor.dev/re-site-kit/changelog)
