> ## Documentation Index
> Fetch the complete documentation index at: https://docs.napps.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Product listing formatter extension

The Product Listing Formatter Extension lets you customize product display data before products are shown in the app.

Use this extension when you want to change how products appear in listings. For example, you can change the vendor text, add or remove product tags, set a stamp image, or hide a product from the listing.

This extension runs on almost all products the app sees across screens.

## Exported Function

Your project must export a function named `formatProducts`.

```ts theme={null}
import type { ProductListingBaseDataEditor } from "@napps/component-extension";

export const formatProducts = async (
  products: ProductListingBaseDataEditor[]
) => {
  // Edit products here.
};
```

The function can be synchronous or asynchronous.

If you return a promise, the mobile app waits up to 3 seconds for it to finish. If the promise does not resolve within 3 seconds, the app treats the extension as failed and continues without the formatter result.

Keep this function fast. It can run often, and it can receive many products.

Important:

In case you need to make network calls create multiple promises and await them like:

```ts theme={null}
import type { ProductListingBaseDataEditor } from "@napps/component-extension";

export const formatProducts = async (
  products: ProductListingBaseDataEditor[]
) => {
    const promises = products.map(async (product) => {
        // Run your async work
    });

    return Promise.all(promises);
};
```

## What You Can Change

Each item received by `formatProducts` is a `ProductListingBaseDataEditor`.

You can:

* Read the original product data.
* Change the vendor text.
* Set or clear the stamp image.
* Read the current tags.
* Replace all tags.
* Add a tag.
* Remove a tag.
* Remove a tag by type.
* Clear all tags.
* Hide or show the product.
* Check if the product is currently visible.

## TypeScript Types

```ts theme={null}
export declare class ProductTag {
  type: string;
  labelText: string;
  labelTextColor: string;
  labelBackgroundColor: string;

  constructor(
    type: string,
    labelText: string,
    labelTextColor: string,
    labelBackgroundColor: string
  );
}

export type ProductListingBaseDataEditor = {
  product: Product;
  setVendor: (vendor?: string) => void;
  setStampImage: (imageUrl?: string) => void;
  getTags: () => ProductTag[];
  replaceTags: (tags: ProductTag[]) => void;
  addTag: (tag: ProductTag) => void;
  removeTag: (tag: ProductTag) => void;
  removeTagByType: (type: string) => void;
  clearTags: () => void;
  setVisible: (isVisible: boolean) => void;
  isVisible: () => boolean;
};
```

## Example

```ts theme={null}
import {
  ProductTag,
  type ProductListingBaseDataEditor
} from "@napps/component-extension";

export const formatProducts = async (
  products: ProductListingBaseDataEditor[]
) => {
  for (const item of products) {
    const product = item.product;

    if (product.vendor === "Hidden Vendor") {
      item.setVisible(false);
      continue;
    }

    if (product.discountPercentage > 0) {
      item.addTag(
        new ProductTag(
          "discount",
          `${product.discountPercentage}% OFF`,
          "#ffffff",
          "#d32f2f"
        )
      );
    }

    item.setVendor(product.vendor.toUpperCase());
  }
};
```

## Best Practices

* Keep the function fast.
* Avoid long network requests.
* Avoid heavy CPU work.
* Always handle missing or optional product data.
* Return within 3 seconds when using async code.
* Avoid making any change after the function has resolved, or the promise has resolved;
