# Skeleton loader

One of the key features of Bravo is its **flexibility** both for the **design** and the **backend**. Thanks to leveraging the power of tools like Figma or Adobe XD together with the usage of [Bravo tags](https://bravostudio.notion.site/bravostudio/Bravo-Tags-Master-List-145bec845f0b4afaa9e3bb8321b218a8), we can have full control over how our apps look and feel.

### What is a skeleton loader?

> *In simplest terms,* [*Skeleton Loader*](https://blog.prototypr.io/skeleton-loader-an-overview-purpose-usage-and-design-173b5340d0e1) *is a static / animated placeholder for the information that is still loading. It mimic the structure and look of the entire view.*

Skeleton loaders create a perception of reduced waiting time, providing a good user experience for the app navigation. Good interaction design and good UX will always require some kind of feedback: **obvious, visible, understandable reactions from the UI**. While generic loaders like spinners are effective in many cases, skeleton ones give an immediate reaction and let users understand what is going to happen next.

{% embed url="<https://youtu.be/ue7CgpPAdUA>" %}

### How it works

To create a skeleton loader in Bravo, we are going to use the Bravo page states tags: `[state:default:NAME]` for the page that is loaded and `[state:loading:NAME]` for the skeleton one. Whenever the first one triggers an API request to load external data, the loading page will be shown immediately. Some points we need to keep in mind:

* The loading page will only appear when the related page loads external data
* Loading pages can’t have any data bound
* Page transitions won’t work on loading pages
* We can have one loading page per "default" page (will increase the page count)
* Loading pages won’t be shown when using pull to refresh

It is interesting to mention also that we can set up a \[state:loading] page (without :NAME) to be used by default on any screen of you app, and then use custom loading screens for specific pages. Full design power! 🙌

### Setup the design

![](/files/57xYFWi2Ax6lR5hbOMq8)

Once you have the main page designed, you can duplicate it and replace some elements by grey shapes. In our case we have also added a [LottieFile animation](https://docs.bravostudio.app/bravo-tags/interactive-component/component-lottie) at the top. Alternatively you can place a LottieFile with the whole skeleton design. There are [plenty of them](https://lottiefiles.com/search?q=skeleton\&category=animations) ready to use! Just find the one that better fits in with your design or create your own.

Then add the tag `[state:default:NAME]` to the main page and `[state:loading:NAME]` to the skeleton screen. Note that you need to replace NAME with a unique identifier of your choice. It is not required to be uppercase but it helps us to keep things organised.

And that’s it! Now every time the page loads data from the API, the skeleton loader will be shown 🎉

{% hint style="info" %}
You can see this example in action by [duplicating our sample app](https://projects.bravostudio.app/sample-apps/functionalities?appId=01G1T4Q3WNJ92RT2FTZY556CBS) or building the full setup from scratch duplicating the [design file](https://www.figma.com/community/file/1101792374472444768), copying the [Airtable base](https://airtable.com/shrcEMxmzh9gWzuzs) and [connecting both](https://docs.bravostudio.app/connnec-api/data-library-connecting-to-apis/set-up-api-requests/data-library-connect-to-any-api-get-request-for-lists) in Bravo Studio.
{% endhint %}

#### **Resources for this tutorial**

* [Sample app in Bravo Studio](https://projects.bravostudio.app/sample-apps/functionalities?appId=01G1T4Q3WNJ92RT2FTZY556CBS)
* [Design file](https://www.figma.com/community/file/1101792374472444768)
* [Example database](https://airtable.com/appJ97vgwpZbaWgCq/tblHJnz6RQ9ccVXxS/viwILpcYZetluBndY?blocks=hide)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.bravostudio.app/get-started/help-and-tutorials/browse-by-app-feature/skeleton-loader.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
