@buyingbuddy/react
v0.2.0
Published
IDX MLS real estate integration for React, Next.js, and Framer — property search, map results, listings, lead capture, and CRM via Buying Buddy.
Readme
@buyingbuddy/react
Add IDX/MLS integration to your site with React components that embed Buying Buddy IDX CRM widgets - MLS property search, map-based results, detailed listing pages, featured-listing showcases, lead-capture forms, and market reports.
Buying Buddy widgets ship as a <bb-widget> custom element loaded from the Buying Buddy plugin script. This package wraps that element in idiomatic React components so you can add IDX search and listings to your site without writing script tags or touching the custom element directly.
Works with React, Next.js, and Framer.
Is this the right package for you? This is a React component library — you use it inside a build-tooled project (Vite, Next.js, Framer) that compiles JSX/TypeScript. If you just want to drop a widget into a plain HTML page with a
<script>tag, you don't need this package — use the standard widget install from your Buying Buddy account dashboard (Widgets → Installation and Setup) instead.
Prerequisites
Before anything will render, you need both of these:
- A Buying Buddy account activation key. Find it in your dashboard under Widgets → Plugin Installation and Setup. There is no anonymous or "try it" mode — the widgets will not load without a valid activation key.
- Your domain authorized on that account. An activation key only works on domains registered to its account. On an unauthorized domain the runtime loads but the widgets stay empty (no data is returned) — if widgets render blank, check that the domain is registered under Widgets → Plugin Installation and Setup.
Don't have an account yet? Start a free trial or buy a license to get your activation key.
Install
Inside an existing React project:
npm install @buyingbuddy/reactReact 18 or 19 is required as a peer dependency, so make sure your project has them:
npm install react react-domStarting from scratch
No React project yet? This gets you from nothing to a running page:
npm create vite@latest my-site -- --template react
cd my-site
npm install
npm install @buyingbuddy/react
npm run dev # opens a dev server, usually http://localhost:5173Then paste one of the examples below into src/App.jsx and save — the page reloads automatically.
Quick start
import { BuyingBuddyProvider, BuyingBuddyWidget } from "@buyingbuddy/react";
export default function App() {
return (
<BuyingBuddyProvider activationKey="account-activation-key">
<BuyingBuddyWidget type="FeaturedGallery" filter="limit:12" />
</BuyingBuddyProvider>
);
}Replace account-activation-key with your activationKey. The provider loads the Buying Buddy script for that account once, waits for it to initialize, then renders your widgets. While it loads it renders the fallback (nothing, by default).
Examples
A standalone search form:
<BuyingBuddyProvider activationKey="account-activation-key">
<BuyingBuddyWidget type="SearchForm" />
</BuyingBuddyProvider>Display properties in grid or list layout, with a limit: token in the filter capping how many:
<BuyingBuddyWidget type="FeaturedGallery" filter="limit:12" />To show listings from the broader MLS instead, add search criteria to the
filter(below). If the filter contains no other criteria then widgets show the account's own (featured) listings.
Display selected properties in a grid layout. All options are expressed as +-joined tokens inside a single filter string — criteria, sort, and count alike. Use FIELD() for a field that accepts several values:
{/* 6 listings over $300k, priced high-to-low */}
<BuyingBuddyWidget
type="FeaturedGallery"
filter="price_min:300000+orderby:price desc+limit:6"
/>
{/* combine criteria with + ; FIELD() for multi-value fields */}
<BuyingBuddyWidget
type="FeaturedGallery"
filter="city:Denver+FIELD(property_beds:3,4,5)+orderby:price desc+limit:9"
/>Search Results (results widgets are driven by the search/cookie state, and SearchResults is bound to the map viewport):
<BuyingBuddyWidget
type="SearchResults"
filter="city:Denver+price_min:300000+orderby:price desc"
/>Interactive map with a fixed height:
<BuyingBuddyWidget type="InteractiveMap" style={{ height: "600px" }} />Next.js
The provider runs entirely in the browser (it loads a script and reads window), so the file that renders it must be a client component. In the App Router, add the "use client" directive at the top of the file — it tells Next.js to run this component in the browser rather than only on the server.
In app/page.tsx:
"use client";
import { BuyingBuddyProvider, BuyingBuddyWidget } from "@buyingbuddy/react";
export default function Page() {
return (
<BuyingBuddyProvider activationKey="account-activation-key" fallback={<p>Loading…</p>}>
<BuyingBuddyWidget type="SearchResults" />
</BuyingBuddyProvider>
);
}Because the widgets are client-only, their listing content is not server-rendered — keep that in mind if SEO of the listings themselves matters to you.
Framer
A standalone, single-file widget for the Framer website builder is included at framer/BuyingBuddyWidget.tsx. It bundles the script loading and adds Framer property controls (activation key, widget type, filter), so you configure everything from Framer's design panel — no React code required.
- Open
framer/BuyingBuddyWidget.tsxand copy its entire contents. (It also ships inside the npm package atnode_modules/@buyingbuddy/react/framer/BuyingBuddyWidget.tsx.) - In Framer, go to Assets → Code → + and paste it in.
- Drag the component onto your canvas and set your activation key in the property panel.
API
<BuyingBuddyProvider>
Loads the Buying Buddy runtime for an account and makes it available to the widgets inside it. Use one provider, near the top of your tree.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| activationKey | string | — | Required. Your Buying Buddy account activation key. |
| fallback | ReactNode | null | Rendered while the script is loading. Not shown on error — see Caveats. |
<BuyingBuddyWidget>
Renders a single widget. Must be a descendant of <BuyingBuddyProvider>.
| Prop | Type | Description |
|------|------|-------------|
| type | BuyingBuddyWidgetType | Required. Widget to render — e.g. "FeaturedGallery", "SearchForm", "SearchResults", "InteractiveMap", "SearchDetails". |
| filter | string | Property filter as +-joined tokens, e.g. "city:Denver+FIELD(property_beds:3,4,5)+orderby:price desc+limit:9". |
| style | React.CSSProperties | Inline styles applied directly to the <bb-widget> element. A height here sizes the widget (e.g. for InteractiveMap / SearchResults). |
Common type values include FeaturedGallery, FeaturedList, SearchForm, SearchResults, SearchDetails, QuickSearch, InteractiveMap, Communities, LcForm (lead capture), LoginPanel, Calculator, MarketReport, MarketStats, Brokers, OfficeRoster, and Disclaimer. The type prop accepts any string, so newer widget types work even before they're added to the typings.
TypeScript
The package is written in TypeScript and ships its own types. These are exported for your own typing needs:
import type {
BuyingBuddyWidgetType,
BuyingBuddyWidgetProps,
BuyingBuddyProviderProps,
BuyingBuddyContextValue,
} from "@buyingbuddy/react";Caveats & limitations
- One account per page. The Buying Buddy script installs a single global, so a page is expected to use one
activationKey. Rendering two providers with different activation keys on the same page is not supported. - Client-side only. Widgets render in the browser after the script loads — nothing is server-rendered. There's no SSR/streaming output, so the listing content isn't in the initial HTML (relevant for SEO).
- Changing a prop rebuilds the widget. Changing
typeorfiltertears down and recreates the underlying<bb-widget>, losing in-widget state (map position, scroll, form input). - The script persists after unmount. Unmounting the provider does not remove the script or reset the global — remounting reuses the already-loaded runtime. This is intentional.
- Error UI is built in. If the runtime script fails to load (network error), the provider renders its own inline error message in place of
children(andfallbackis not shown). You can't currently replace the default error UI. Note this only covers script load failure — an unauthorized domain loads fine but renders empty widgets (see Prerequisites). - ESM-only. This package ships as ES modules only (no CommonJS build). Use it in a project with ESM/bundler support.
- Pre-release. This package is
0.x— the API may change.
Development
npm install
npm run build # compile src/ to dist/ (JS + .d.ts)
npm run dev # rebuild on change (tsc --watch)
npm test # run the unit tests (vitest)License
MIT © Blue Fire Group / Buying Buddy
