# Real Estate Page

> A React real estate template: buy or rent search, listing cards, a price pin map, neighborhoods, a mortgage estimate and a valuation form.

- Type: React template (Templates)
- Access: Pro (the source needs a Wingo UI Pro plan, see https://wingo-ui.com/pricing)
- Version: 1.0.0
- Install: `npx wingo-ui@latest add real-estate-page`
- Docs: https://wingo-ui.com/templates/real-estate-page

## Interaction

The Buy / Rent switch in the hero swaps the homes, the price choices and the map; typing a neighborhood, street or ZIP, picking a price band or a minimum of beds filters the featured homes and the map live, with the count announced. Search glides down to the homes. On phones the search is a stacked card: Filters opens a bottom sheet with a price slider over a price histogram, preset chips and a beds switch, and Show homes closes it on the results; the homes become a swipeable snap rail. Every listing card is one link that lifts on hover; its heart saves the home with a little burst. On the map, a pin or a row in the list beside it (above it on phones) opens a preview card with View home and Estimate payment, which fills the calculator with that price; Escape or the close button closes it and focus returns to the pin. A neighborhood tile searches that neighborhood. The mortgage sliders (arrow keys, Page Up / Down), the rate field and the term switch update the monthly payment and its breakdown bar live. The valuation form checks the address, name and email, focuses the first problem, spins on submit and then confirms.

## Installation

```bash
npx wingo-ui@latest add real-estate-page
```

Pro item: run `npx wingo-ui@latest login` once with a Pro account. The CLI adds the files, their dependencies and a version record for updates.

With shadcn: `npx shadcn@latest add @wingo-ui/real-estate-page` (needs the @wingo-ui registry with your API key in components.json)

Files:

- `components/templates/real-estate-page.tsx`
- `components/templates/real-estate-page-data.ts`

npm dependencies: `npm i lucide-react motion`

Wingo UI dependencies (installed automatically):

- [Marketing Section](https://wingo-ui.com/components/marketing-section) ([Markdown](https://wingo-ui.com/components/marketing-section.md))
- [Marketing Header](https://wingo-ui.com/components/marketing-header) ([Markdown](https://wingo-ui.com/components/marketing-header.md))
- [Marketing Footer](https://wingo-ui.com/components/marketing-footer) ([Markdown](https://wingo-ui.com/components/marketing-footer.md))
- [Testimonials Section](https://wingo-ui.com/components/testimonials-section) ([Markdown](https://wingo-ui.com/components/testimonials-section.md))
- [Avatar](https://wingo-ui.com/components/avatar) ([Markdown](https://wingo-ui.com/components/avatar.md))
- [Button](https://wingo-ui.com/components/button) ([Markdown](https://wingo-ui.com/components/button.md))
- [Favorite button](https://wingo-ui.com/components/favorite-button) ([Markdown](https://wingo-ui.com/components/favorite-button.md))
- [Input](https://wingo-ui.com/components/input) ([Markdown](https://wingo-ui.com/components/input.md))
- [Price range](https://wingo-ui.com/components/price-range) ([Markdown](https://wingo-ui.com/components/price-range.md))
- [Segmented Control](https://wingo-ui.com/components/segmented-control) ([Markdown](https://wingo-ui.com/components/segmented-control.md))
- [Select](https://wingo-ui.com/components/select) ([Markdown](https://wingo-ui.com/components/select.md))
- [Sheet](https://wingo-ui.com/components/sheet) ([Markdown](https://wingo-ui.com/components/sheet.md))
- [Slider](https://wingo-ui.com/components/slider) ([Markdown](https://wingo-ui.com/components/slider.md))
- [useControllableState](https://wingo-ui.com/components/use-controllable-state) ([Markdown](https://wingo-ui.com/components/use-controllable-state.md))
- [Navigation](https://wingo-ui.com/components/navigation) ([Markdown](https://wingo-ui.com/components/navigation.md))
- [Motion presets](https://wingo-ui.com/components/motion) ([Markdown](https://wingo-ui.com/components/motion.md))
- [Tones](https://wingo-ui.com/components/tones) ([Markdown](https://wingo-ui.com/components/tones.md))
- [UIProvider](https://wingo-ui.com/components/ui-config) ([Markdown](https://wingo-ui.com/components/ui-config.md))

## Usage

```tsx
// app/page.tsx
"use client"

import Link from "next/link"
import { RealEstatePage, type RealEstateValuationValues } from "@/components/templates/real-estate-page"

async function requestValuation(values: RealEstateValuationValues) {
  await fetch("/api/valuations", { method: "POST", body: JSON.stringify(values) })
}

export default function HomeRoute() {
  return <RealEstatePage linkComponent={Link} defaultMode="buy" onValuation={requestValuation} />
}
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `listings?` | `RealEstateListing[]` | `"REAL_ESTATE_LISTINGS"` | { id, mode, price, previousPrice?, address, neighborhood, city, beds, baths, sqft, kind, color, image?, lat, lng, badge?, href?, favorite? }. mode buy or rent (rent prices are per month); kind picks the drawn photo (brownstone, condo, loft, house, townhouse) tinted with color, image replaces it; lat / lng place the map pin. |
| `neighborhoods?` | `RealEstateNeighborhood[]` | `"REAL_ESTATE_NEIGHBORHOODS"` | { name, medianPrice, medianRent?, homes, trend?, description?, color } tiles; the rent median shows in rent mode, trend is a yearly percent. An empty array hides the section. |
| `agents?` | `RealEstateAgent[]` | `"REAL_ESTATE_AGENTS"` | { name, role, phone, email, avatar?, sales?, rating?, areas?, languages? } cards with Call and Email links. |
| `testimonials?` | `Testimonial[]` | `"REAL_ESTATE_TESTIMONIALS"` | Client quotes for the testimonials grid (the TestimonialsSection shape). |
| `stats?` | `RealEstateStat[]` | `"REAL_ESTATE_STATS"` | { value, label } numbers under the search; an empty array hides them. |
| `phone?` | `string` | `"(718) 555-0100"` | The office number in the header, the phone menu and the valuation band (a tel: link); empty hides it. |
| `labels?` | `Partial<RealEstatePageLabels>` |  | Every string on the page: the brand, the hero, the search, the section headings, the calculator, the form and its errors. Some are functions (matches, listingsTitle, bedCount, showHomes, successDescription). |
| `currency?` | `string` | `"USD"` | ISO currency of every price, pin, median and payment. |
| `locale?` | `string` | `""` | Intl locale for prices and numbers; empty uses the UIProvider's, else en-US. |
| `mode?` | `"buy" \| "rent"` |  | Buy or rent (controlled): the search, the featured homes, the map and the neighborhood medians follow it. |
| `defaultMode?` | `"buy" \| "rent"` | `"buy"` | The mode on first render (uncontrolled). Switching resets the price filter, since sale and rent bands differ. |
| `onModeChange?` | `(mode: "buy" \| "rent") => void` |  | Fires when the Buy / Rent switch changes. |
| `onSearch?` | `(search: RealEstateSearch) => void` |  | Runs on Search, on Show homes in the filters sheet and on a neighborhood tile with { mode, location, price: [min, max], minBeds }. The listings filter live either way; use it to fetch or to sync the URL. |
| `onValuation?` | `(values: RealEstateValuationValues) => void \| Promise<unknown>` |  | Runs on Request my valuation with { address, propertyType, beds, timeline, name, email, phone }. A returned promise keeps the button loading; a rejection keeps the form and shows labels.failed. Without it the page pretends for 900 ms, then confirms. |
| `onFavoriteChange?` | `(listing: RealEstateListing, favorite: boolean) => void \| Promise<unknown>` |  | Runs when a heart is pressed. A returned promise keeps the heart on while pending; a rejection rolls it back. |
| `pricePresets?` | `Record<"buy" \| "rent", PriceRangeValue[]>` | `"REAL_ESTATE_PRICE_PRESETS"` | The price bands of the search and the filters sheet, per mode, as [min, max] pairs (null is an open end). |
| `mortgage?` | `Partial<RealEstateMortgage>` | `"DEFAULT_REAL_ESTATE_MORTGAGE"` | { price, downPayment (percent), rate (yearly percent), term (15, 20 or 30 years), taxRate (yearly percent of the price), insurance and hoa (per month) }: the calculator's starting numbers and the averages behind the breakdown. |
| `mapBounds?` | `RealEstateMapBounds` | `"REAL_ESTATE_MAP_BOUNDS"` | { north, south, west, east } of the drawn map; pins are placed by lat / lng inside it and pulled in at the edges. |
| `featuredCount?` | `number` | `6` | Listing cards shown from 768px before Show all; phones get every match in the rail. |
| `tone?` | `"neutral" \| "brand" \| "success" \| "warning" \| "danger" \| "info"` | `"neutral"` | Accents: the selected map pin, the price slider and histogram, the mortgage sliders and payment bar, the agent stars and the testimonial metrics. |
| `ctaTone?` | `"neutral" \| "brand" \| "success" \| "warning" \| "danger" \| "info"` | `"neutral"` | Search, Free valuation, Show homes and Request my valuation. |
| `favoriteTone?` | `"neutral" \| "brand" \| "success" \| "warning" \| "danger" \| "info"` | `"neutral"` | The heart on a saved home; neutral is white on the photo. |
| `radius?` | `"none" \| "sm" \| "md" \| "lg"` | `"lg"` | Corners of the listing, map, neighborhood, calculator, agent and form cards: 0 / 12 / 16 / 24px; the photos inside follow. |
| `background?` | `"plain" \| "soft" \| "glow" \| "aurora" \| "grid" \| "dots"` | `"glow"` | The main background: plain is the bare page color; the others tint the page and add a glow, an aurora, a grid or dots over the first screen. |
| `backgroundColor?` | `string` | `"oklch(0.62 0.14 275)"` | The tint and glow color of the main background. |
| `bandBackground?` | `"muted" \| "tinted" \| "gradient" \| "dots"` | `"muted"` | The secondary background of every second section (the map, the mortgage and the testimonials with all sections on). Cards and fields inside are lifted one step above it. |
| `bandColor?` | `string` | `"oklch(0.62 0.14 275)"` | The tint of tinted and gradient bands; left equal to backgroundColor it follows it. |
| `showMap?` | `boolean` | `true` | The map band with the price pins and the list beside it (and its header link). |
| `showNeighborhoods?` | `boolean` | `true` | The neighborhood tiles with medians and trends. |
| `showMortgage?` | `boolean` | `true` | The mortgage estimate; off also removes Estimate payment from the map preview. |
| `showAgents?` | `boolean` | `true` | The agent cards with Call and Email links. |
| `showTestimonials?` | `boolean` | `true` | The testimonials section. |
| `showValuation?` | `boolean` | `true` | The Request a valuation band. Off, Free valuation in the header calls the office instead. |
| `header?` | `boolean` | `true` | The sticky header with the brand, the section links, the phone number and Free valuation. |
| `footer?` | `boolean` | `true` | The footer with Buy, Rent, Sell and Company links and the broker's legal line. |
| `headerProps?` | `Partial<MarketingHeaderProps>` |  | Anything for MarketingHeader (layout, variant, items...); wins over the page's own values. |
| `footerProps?` | `Partial<MarketingFooterProps>` |  | Anything for MarketingFooter (variant, columns, socials, newsletter...). |
| `testimonialsProps?` | `Partial<TestimonialsSectionProps>` |  | Anything for the TestimonialsSection (layout, columns, card...). |
| `animateIn?` | `boolean` | `true` | The hero and the search rise in once when the page mounts on the client; never during hydration, under reduced motion or in thumbnails. |
| `linkComponent?` | `(props: LinkComponentProps) => ReactNode` |  | The router link for the listing, header and footer links (next/link in an app). |
| `className?` | `string` |  | Classes for the root. |
| `classNames?` | `Partial<Record<RealEstatePageSlot, string>>` |  | Classes for header, hero, search, filters, listings, listing, photo, map, mapList, neighborhoods, neighborhood, mortgage, agents, agent, testimonials, valuation, form and footer. |

## Parts

### REAL_ESTATE_PAGE_SAMPLE (constant)

All the sample content in one object: listings, neighborhoods, agents and testimonials.

### REAL_ESTATE_LISTINGS (constant)

Eight Brooklyn homes for sale and six rentals from Greenpoint to Park Slope, with map coordinates.

### REAL_ESTATE_NEIGHBORHOODS (constant)

Park Slope, Williamsburg, DUMBO, Fort Greene, Bed-Stuy and Greenpoint.

### REAL_ESTATE_AGENTS (constant)

Four Harbor & Pine agents with phone, email, sales, rating and areas.

### REAL_ESTATE_TESTIMONIALS (constant)

Three quotes from a buyer, a seller and a renter.

### REAL_ESTATE_STATS (constant)

The three numbers under the search.

### REAL_ESTATE_PRICE_PRESETS (constant)

Four price bands for buying and four for renting.

### REAL_ESTATE_MAP_BOUNDS (constant)

The corners of the drawn Brooklyn map.

### DEFAULT_REAL_ESTATE_MORTGAGE (constant)

$1,250,000, 20% down, 6.5% over 30 years, 0.9% tax, $150 insurance.

### DEFAULT_REAL_ESTATE_PAGE_LABELS (constant)

The English strings.

### RealEstatePageProps (type)

Props of RealEstatePage, including the attributes of the root element.

### RealEstatePageLabels (type)

Every string of the page.

### RealEstatePageRadius (type)

"none" | "sm" | "md" | "lg".

### RealEstatePageSlot (type)

The keys of classNames.

### RealEstateMode (type)

"buy" | "rent".

### RealEstateListing (type)

One home: price, address, facts, the drawn photo and the map position.

### RealEstateHomeKind (type)

"brownstone" | "condo" | "loft" | "house" | "townhouse": the drawn photos.

### RealEstateNeighborhood (type)

One neighborhood tile with its medians and trend.

### RealEstateAgent (type)

One agent card.

### RealEstateStat (type)

{ value, label }.

### RealEstateSearch (type)

What onSearch receives: { mode, location, price, minBeds }.

### RealEstateMortgage (type)

The calculator's numbers: price, downPayment, rate, term, taxRate, insurance, hoa.

### RealEstateMapBounds (type)

{ north, south, west, east }.

### RealEstateValuationValues (type)

What onValuation receives.

### RealEstatePropertyType (type)

"house" | "townhouse" | "condo" | "coop" | "multi".

### RealEstateTimeline (type)

"now" | "soon" | "later": when the owner plans to sell.

## Examples

- **Rentals**: defaultMode="rent": monthly prices, rent price bands, rent medians on the neighborhood tiles and the rentals on the map.
- **Brand accents**: tone, ctaTone and a red favoriteTone on an aurora page with tinted bands: orange pins, sliders and buttons, red hearts.
- **A listings site, search first**: Listings, map and mortgage only, square-ish cards, eight featured homes and a soft background: a lean portal for a single office.
- **When the request fails**: onValuation rejects: after the spinner the form keeps everything and shows the error above the button.
- **Inside a site layout**: No header or footer, on a plain page with dotted bands: the sections alone.

## See also

- [Listing card](https://wingo-ui.com/components/listing-card) ([Markdown](https://wingo-ui.com/components/listing-card.md))
- [Listing grid](https://wingo-ui.com/components/listing-grid) ([Markdown](https://wingo-ui.com/components/listing-grid.md))
- [Location Map](https://wingo-ui.com/components/location-map) ([Markdown](https://wingo-ui.com/components/location-map.md))
- [Price range](https://wingo-ui.com/components/price-range) ([Markdown](https://wingo-ui.com/components/price-range.md))
- [Landing Page](https://wingo-ui.com/templates/landing-page) ([Markdown](https://wingo-ui.com/templates/landing-page.md))

---

Canonical: https://wingo-ui.com/templates/real-estate-page
More components: https://wingo-ui.com/components · Index for agents: https://wingo-ui.com/llms.txt
