Listings browser
Every home, filtered and paged in the browser.
The block on the listings page (ADR 0039): a white filter panel (a location picker of cities and their neighbourhoods, room chips, a rent range, and "more filters" opening in place: size, move-in date, status), then a live result count with the sort, one page ofListingCards in the shared grid, and numbered pagination.
The browser holds an index, not the cards. The page ships the first page of cards; the script fetches the index (every unit's filter fields, about 100 bytes each) from one JSON file that every page of the browser shares, filters and sorts it, and fetches each further card once, from a fragment built by the same ListingCard. Here every card is rendered up front, so only the index is fetched.
The state lives in the URL, replaced in place. With no JavaScript the first page shows and the controls are inert; the pagination is drawn by the script, so it is absent rather than broken.
Five homes, two a page
4 homes
- 1 / 12New8.400 kr/md.LejlighedAvailable
- 1 / 1Open houseReserved11.200 kr/md.RækkehusReserved
- 1 / 5Open houseNewComing soon
Strandgade 7, 1.5000 Odense C
6.950 kr/md.LejlighedComing soon - 1 / 2Let
Bredgade 44, 3.5200 Odense V
9.500 kr/md.LejlighedLet - 1 / 1Coming soon
Havnegade 21, 4.5000 Odense C
7.800 kr/md.LejlighedAvailable from 1 Dec 2026
No homes match these filters. Try clearing one.
Some homes could not be loaded.
Props
| Prop | Type | Required |
|---|---|---|
| index For the counts the server draws. Not put in the page: the script reads the same index from `indexUrl`. | IndexEntry[] | yes |
| indexUrl Where the index is served as JSON, exactly as `index`. | string | yes |
| listings The cards rendered at build time, in index order. | Card[] | yes |
| cardUrl A URL with "{id}", answering with one card's fragment. | string | yes |
| pageSize | number | — |
| locale Formats the ranges' numbers. | string | yes |
| places Counts are of the default view, which leaves let homes out; the script recounts them as the status toggles change. | Place[] | yes |
| roomFilters Keys "1", "2", "3", "4+"; "4+" matches four rooms or more. | Facet[] | yes |
| rentRange A range is left out when every home has the same value. | Range & { currency: string } | — |
| sizeRange | Range | — |
| sortOptions The first is the default. Keys: "move-in", "rent", "area". | Option[] | yes |
| placeUrls The page of each place that has one (ADR 0043), by the picker's key: a city's name, "city/neighbourhood", or "" for every place. Closing the picker on one of them goes to its page. | Record<string, string> | — |
| ownPlace The place this page is about, by the same key; picked when the URL names none, and left out of the URL. | string | — |
| listLabel | string | yes |
| locationLabel | string | yes |
| anywhereLabel | string | yes |
| placeSearchLabel | string | yes |
| areasInLabel "{city}" template. | string | yes |
| otherAreaLabel | string | yes |
| selectAllLabel | string | yes |
| noPlaceMatchLabel | string | yes |
| clearLabel | string | yes |
| clearLocationLabel | string | yes |
| showCountOne "{count}" templates. | string | yes |
| showCountOther | string | yes |
| roomsLabel | string | yes |
| filterRoomsLabel | string | yes |
| rentLabel | string | yes |
| rentMinLabel | string | yes |
| rentMaxLabel | string | yes |
| sizeLabel | string | yes |
| sizeMinLabel | string | yes |
| sizeMaxLabel | string | yes |
| moreFiltersLabel | string | yes |
| moveInByLabel | string | yes |
| filterStatusLabel The status toggles: their group's name, then each toggle's label. A toggle shows only when the index holds a home it would change. | string | yes |
| showLetLabel | string | yes |
| hideReservedLabel | string | yes |
| resetLabel | string | yes |
| sortLabel | string | yes |
| countLabelOne "{count}" templates. | string | yes |
| countLabelOther | string | yes |
| emptyLabel | string | yes |
| emptyLetOne "{count}" templates: the empty grid when let homes, hidden by default, would match. Said with a button that shows them. | string | yes |
| emptyLetOther | string | yes |
| loadErrorLabel | string | yes |
| paginationLabel | string | yes |
| prevLabel | string | yes |
| nextLabel | string | yes |
| pageLabel "{page}" template, the accessible name of a page link. | string | yes |
| cardHeadingLevel | 1 | 2 | 3 | 4 | 5 | 6 | — |
| Field | Type | Required |
|---|---|---|
| id | string | yes |
| place A key of an area in `places`, "city/neighbourhood". | string | yes |
| rooms | number | null | yes |
| rent | number | null | yes |
| area | number | null | yes |
| from ISO date; null sorts as "now". | string | null | yes |
| status Let homes are hidden until the reader asks for them. | "available" | "reserved" | "let" | yes |
| Field | Type | Required |
|---|---|---|
| key | string | yes |
| label | string | yes |
| count | number | yes |
| Field | Type | Required |
|---|---|---|
| min | number | yes |
| max | number | yes |
| step | number | yes |
| Field | Type | Required |
|---|---|---|
| value | string | yes |
| label | string | yes |