Directories: Totals That Match the List

The condo and new development directories show a number next to every area and developer, and that number is what you get when you pick it, also with price, bedrooms or delivery year filters on. Every area also keeps how many condos, communities and new developments it holds, so any section of your website can say "84 condos in Aventura" without another search. Both are in the Site API and in the website widgets.

What you can build

PieceWhat is newUse it to
GET /v1/condos/directory/buildingsfacets=1 returns facetsShow beside each area or developer what picking it lists, with the other filters applied
GET /v1/areasdirectory on every areaShow "84 condos in Aventura" in an areas section
GET /v1/libraries/:idThe same directory on area itemsThe same, from an areas library of the site
usePandaDirectory()facets (areas, developers)Draw your own area and developer lists with the right totals
BuildingDetail variant="panda"listingViews propChoose which views the units list offers

All of it is additive: nothing that already worked changes shape. Requests use the public key of your website (see Getting Started).

Totals per area and developer

Send facets=1 on the first page (offset=0) of the directory search and the response carries facets next to the page. facets.areascounts the matches of every area, keyed by the area's upper-case name (the query of the areas). With forceNewdev=1, facets.developers is a list of { name, count } per developer; without it the list is empty.

Each count is computed with the same search as the list and every filter except its own dimension: areas ignore the area filter and developers the developer filter. So facets.areas.BRICKELL is the totalyou get after selecting Brickell, with price, bedrooms, delivery year and the rest still applied. This example lists new developments from $1M; Brickell's count is the projects of Brickell from $1M.

Request
curl --get "https://api.pandaidx.com/v1/condos/directory/buildings" \
--data "key=$PANDA_PUBLIC_KEY" \
--data "forceNewdev=1" \
--data "minprice=1000000" \
--data "facets=1" \
--data "limit=24"
Response 200
{
"data": [ ... ],
"total": 61,
"hasMore": true,
"facets": {
"areas": { "BRICKELL": 14, "MIAMI BEACH": 9, "SUNNY ISLES BEACH": 7 },
"developers": [
{ "name": "Related Group", "count": 11 },
{ "name": "Fortune International", "count": 4 }
]
}
}

Facets are computed for each request, so ask for them once per filter change and not on every "load more" page. With no filter set, use the unfiltered numbers instead (buildingCount of each area in Directory Bootstrap, or directory below). Every parameter is in Condo Directory Search.

Totals per area in any section

Every area of GET /v1/areas has a directory field: { condos, communities, newDevelopments }. condos and communities count the buildings with a published asking price, like the Condos and Communities tabs of /condos; newDevelopments counts the projects of /new-developments. The area items of an areas library (GET /v1/libraries/:id) carry the same field.

Request
curl --get "https://api.pandaidx.com/v1/areas" \
--data "key=$PANDA_PUBLIC_KEY" \
--data "placement=homepage"
Response 200
{
"placement": "homepage",
"libraries": [
{
"title": "Miami Areas",
"areas": [
{
"query": "BRICKELL",
"name": "Brickell",
"directory": { "condos": 65, "communities": 0, "newDevelopments": 22 },
"paths": { "forSale": "/for-sale/brickell", ... }
}
]
}
]
}

directory is recalculated every hour and is null until the first run has counted the area: show the area without the number in that case.

Widgets: usePandaDirectory

Inside PandaDirectoryRoot, usePandaDirectory() returns facets with the same two parts: facets.areas["AVENTURA"] next to each area and facets.developers in the list of developers. It is null before the first search and on the landing (no filter), so fall back to buildingCount and developers there. This is a directory built by hand, with the filters and the results of the widget and your own area pills:

Area pills
"use client"
import { PandaDirectoryRoot, usePandaDirectory, type PandaDirectoryData } from "@pandaidx/widgets/client"
// Area pills with the total each one lists under the other filters (price, beds, delivery year...).
const AreaPills = ({ areas }: { areas: PandaDirectoryData["allAreas"] }) => {
const { facets, query, handleSubmit } = usePandaDirectory()
return (
<ul className="flex flex-wrap gap-2">
{areas.map((area) => {
// facets is null on the landing (no filter) and before the first search: fall back to buildingCount.
const count = facets ? (facets.areas[area.query] ?? 0) : Number(area.buildingCount ?? 0)
if (facets && count === 0) return null
const selected = query.selectedAreas.includes(area.query)
return (
<li key={area._id}>
<button type="button" aria-pressed={selected} onClick={() => handleSubmit({ selectedAreas: selected ? [] : [area.query] })}>
<span className="capitalize">{area.query.toLowerCase()}</span> <span>{count}</span>
</button>
</li>
)
})}
</ul>
)
}
export const CondosView = ({ data }: { data: PandaDirectoryData }) => (
<PandaDirectoryRoot data={data} detailHref="/condos/{slug}">
<AreaPills areas={data.allAreas} />
</PandaDirectoryRoot>
)
Developers (new developments)
const DeveloperList = () => {
const { developers, facets, handleSubmit } = usePandaDirectory()
// facets is null on the landing and before the first search: `developers` (every developer, A to Z) fills in.
const list = facets ? facets.developers : developers
return (
<ul>
{list.map((developer) => (
<li key={developer.name}>
<button type="button" onClick={() => handleSubmit({ developer: developer.name })}>
{developer.name} <span>{developer.count}</span>
</button>
</li>
))}
</ul>
)
}

Widgets: building page

BuildingDetail with variant="panda" takes listingViews, the views its units list offers: grid (big photos), cards (two per row) and list (table). The default offers the three and opens on cards; passing a single view hides the toggle. In the amenities, long lists now go under the title, aligned to the left, and short values like "Yes" stay beside it. That one needs no prop.

listingViews
import { BuildingDetail } from "@pandaidx/widgets/client"
// Units list in cards (2 per row) and a list; the big photo grid is not offered.
<BuildingDetail variant="panda" data={data} listingViews={["cards", "list"]} />

Availability

Site API: live since Oct 21, 2026@pandaidx/widgets 1.14.0
  • The API changes are in production. directory starts as null and fills in with the first run of the hourly worker (minute 25 of each hour).
  • facets of usePandaDirectory and listingViews need @pandaidx/widgets 1.14.0 or later. A website made with the AI Builder gets it from Update widgets; the AI Builder already knows the new pieces.

Next Steps