The Pagination Playbook for Bubble’s Native Engine
(a.k.a. how to stop blasting 10 000 rows into your user’s phone)
Hey everyone! — Adam here. When I first ported my web app to Bubble’s shiny React-Native stack I hit the same wall again and again:
“Short List is okay… until the database crosses five figures — then the app turns into sludge. And the workload units shoot through the roof.”
Below is the recipe that finally gave me silky-smooth scrolling whether I’m showing 8 items or 80 000.
Two flavours, the same Prev / Next buttons. Copy, paste, tweak, done. Ready?
Flavour #1 — when the list is actually short
If you’ll never show more than ±30 rows, life is easy:
| Piece | Why it exists |
|---|---|
current_page (number, default = 1) |
Tracks where we are |
page_size (5 – 10) |
Rows per page |
| Short List | Renders that slice |
| Flip the slice |
Data source (Bubble expression)
Search for Things
:sorted by Name (DESC=yes)
:items from (((current_page - 1) * page_size) + 1)
:items until page_size
Workflows
| Trigger | Action |
|---|---|
| Next | current_page = current_page + 1 |
| Prev | current_page = current_page - 1 (disable when 1) |
That’s literally it. The Short List still loads every row, but who cares — there are only a few dozen. ![]()
Flavour #2 — when the list is a dinosaur (100+ rows)
1 · Expose the Data API (one-time)
- Settings → API →
Enable Data API → tick your Thing. - Grab an admin token (or use Private key in header).
Your endpoint now looks like:
GET https://your-app.bubbleapps.io/api/1.1/obj/product
2 Build a paged call in API Connector
| Field | Value |
|---|---|
| Name | Products – paged |
| Method | GET |
| URL | https://your-app.bubbleapps.io/api/1.1/obj/product?limit=[page_size]&cursor=[offset]&constraints=[constraints] |
| Headers | Authorization: Bearer <TOKEN> |
| Use as | Data |
| Key path | results |
Parameters:
page_size(number, default = 5)offset(number, default = 0)constraints(text, default = [{ “key”: “name”, “constraint_type”: “text contains”, “value”: “Product 1” }])
3 Same UI, new data source
Bind your Short / Vertical List to Products – paged and map:
page_size = 10
offset = (current_page - 1) * page_size
constraints = [{ "key": "name", "constraint_type": "text contains", "value": "Input Name's value" }]
Buttons & states stay exactly the same.
4 But how many pages do I have?
count = Product API - paged's response remaining + page_size
So, on Page load:
total_pages = (count / page_size):ceiling
Then you can sshow a label like “Page X of total_pages”.
Debug / UX checklist
- Always
:sorted bysomething stable before paginating. - Disable Prev on page 1, disable Next on the last page.
- Show a tiny loader while the API call is
. - Lock down your Privacy Rules — the Data API respects them.
Starter pack (copy ➜ paste)
- Group named
controller
- states:
current_page = 1,page_size = 5,total_pages
- Short List wired to Flavour #1 or Flavour #2
- Two buttons →
current_page ± 1 - On page load → fetch count → set
total_pages
One reusable, zero-lag component that scales from 5 → 50 000 rows just by swapping the data source.
Hope I could help you make safe and scalable native apps!