Just like blocks, listings are managed in the API Builder section of your dashboard. The main difference between listings and blocks is that listings are designed to work with lists of items - where each item is a block.

Overview of listings in the API Builder

Why use listings?

It’s easier to understand by comparing it to components in a frontend framework like React.

A listing component takes a list of items and renders them in a grid or list.

product-listing.jsx
function ProductListing({ products }) {
  return (
    <div>
      {products.map((product) => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  );
}

A product card component takes a single product and renders it in a card.

product-card.jsx
function ProductCard({ product }) {
  return <div>{product.name}</div>;
}

Most of the time, you will fetch the list of products from a listing component and pass the products one by one to the product card component. In that case, you can use a listing to fetch the products.

By defining a listing, you can fetch the products in a single request like this:

listing.jsx
import { client } from "@frontstack/client";
const { items } = await client.listing("ProductListing");

return (
  <div>
    {items.map((product) => (
      <ProductCard key={product.id} product={product} />
    ))}
  </div>
);

Input Parameters

Oftentimes, you will want to fetch a list of items based on a certain criteria. For example, you might want to fetch all products in a certain category.

Using parameters, you can define the criteria for the list. Parameters can be strings - for example a category ID or arrays - for example a list of product IDs.

In the Filter Query card inside the Query tab of the listing, you can map the parameters to query criteria that will be used to filter the results.

Parameters are typically controlled by the frontend application based on context (like the current category being viewed), while query options are intended for user-controlled actions such as searching, filtering, and pagination. This separation allows yout to maintain core content relevance while enabling user refinement of results.

Listing Settings

Listing settings are used to control how the listing behaves and how it can be queried.

Listing settings in the query tab of a listing

Filter query

The filter query is a pre-defined query that will always be applied to the listing. For example, you might want to fetch all products in a certain category. You can add mulitple query conditions to refine the results.

Filter options

Press the Settings button in the query tab to see filter, search, sorting and pagination settings.

Filters are used to filter the results of the listing. They provide data to display filters in the application UI - often used to filter by tags, categories or other properties.

By default, the listing response will include full facet information (all possible values) for your filters. For cases with lots of different options (where you’d usually not even show a filter selection - for example for price ranges), you should consider disabling the facets. This will reduce your response size and performance.

Searchable fields

You can mark fields as searchable to enable a text search on them. This will allow your users to search for items by typing in a search query. Often used for product names, aliases or descriptions.

By default, Frontstack will run a fuzzy search on your searchable fields to find the best matches and counteract user typos. You can disable fuzzy search to get exact matches only.

Sorting

You can define multiple sorting fields to allow your users to sort the results by different criteria as well as specify the default sorting.

Pagination

Lets you define how many items per page are fetched.

Fetching a listing

If this is your first time reading, check out how to generate the client first.

To fetch a listing, you can use the clients listing method.

const { items } = await client.listing("ProductListing");

Parameters

If you need to specificy parameters, you can do so by passing them as the second argument to the listing method.

const { items } = await client.listing("ProductListing", {
  categoryId: "123",
});

Filtering

For applying filters (as defined in the Filter options), you can pass a config object with a query field as the third argument to the listing method. You can filter by all fields that are configured as filter options.

The following filter types are supported:

  • equals
  • range
  • contains
  • and/or - allows chaining multiple filters
const { items } = await client.listing("ProductListing", {
  categoryId: "123",
  },
  query: {
    filter: [
      { field: "properties.activity", type: "equals", value: ["Running"] },
    ],
  },
);

Pagination

To paginate the results, you can pass a page and a limit field to the query object. Note, that the limit parameter respects the default and maximum limit set in the pagination settings.

const { items } = await client.listing("ProductListing", {
  categoryId: "123",
  },
  query: { page: 6, limit: 24 },
);

To perform a search, you can pass a search field to the query object.

const { items } = await client.listing("ProductListing", {
  categoryId: "123",
  },
  query: { search: "Running shoe" },
);