Loading Layout (Skeleton Screens)
A loading layout is a skeleton version of your page shown while data is loading. Instead of a blank canvas or a lone spinner, visitors see a shimmer that mirrors the shape of the finished page — giving an immediate sense of structure and reducing perceived wait time.
Note: The loading layout is shown only when the page is used as a template component inside another page, and the host page signals a loading state. It does not appear during ordinary page navigation or while individual data sources are fetching. For data-source loading within a normal page, bind block visibility to the data source's isLoading flag instead.
How the Skeleton Is Generated
The loading layout lives as a separate subtree beside the page's normal body, managed from the Loader section in the page hierarchy. You do not build it block by block — the platform generates it from the current page body.
| Action | When to use | What it does |
| Set | First time you want to create the loading layout | Reads the current page body and generates the skeleton subtree. Containers, stacks, and cards keep their structural role. Text and links become dashed-line placeholders. Other content becomes solid shimmer blocks. |
| Regenerate | After making structural changes to the page | Discards the existing skeleton and rebuilds it from the updated page body. Use after adding, removing, or significantly rearranging blocks. |
Placeholder Generation Rules
The generator follows consistent rules when converting page content into skeleton placeholders:
| Original block type | Skeleton treatment |
| Container, Stack, Card, Row, Column | Preserved as structural wrappers. Their children are converted. |
| Text, Heading, Link, Label | Replaced with a dashed-line placeholder sized to match the text area as currently rendered. |
| Image, Icon, Avatar, Button, Badge | Replaced with a solid shimmer block matching the component's rendered dimensions. |
| Table, List, Data Grid | Converted to a repeating row of shimmer blocks approximating column widths. |
| Modal, Dialog, Drawer, Bottom Sheet | Excluded from the skeleton. These are not part of the initial page view. |
Warning: Placeholder dimensions are measured from the real layout at generation time. If you later change block sizes, add new blocks, or adjust spacing, the skeleton goes out of sync. Use Regenerate after structural page changes to keep the skeleton accurate.
Editing the Generated Skeleton
The generated loading layout is an ordinary block subtree — you can open it in the builder, select individual placeholders, and adjust them like any other block. Styling, spacing, and placeholder shape can all be refined by hand after generation.
While a block inside the loader subtree is selected, the canvas automatically switches to the loading layout view so you can see your edits in context. The main page body is hidden while you are editing the loader. Deselect or select a block outside the loader to return to the normal canvas.
Example — Binding block visibility to data source loading state
For normal in-page loading states (not template component skeleton), bind the visibility of a spinner or placeholder component directly to the data source's isLoading flag:
// Show spinner only while data source is loading its first result Visible when: {{ orders_query.isLoading }} // Show the data table only once results are available Visible when: {{ !orders_query.isLoading }} // Show an error message when loading fails Visible when: {{ !!orders_query.error }}
This is the correct approach for standard page data fetching. The skeleton loading layout is reserved for the template component use case.
Page Triggers
A page can run a sequence of actions automatically — without the visitor clicking anything. These are called page triggers and are configured in Page Settings → Events.
Page triggers are particularly useful for:
Fetching data as soon as a page opens
Setting initial variable values
Running analytics or logging events
Coordinating multiple data sources that share a common starting point
On Page Load
The most commonly used trigger. Fires once when the page finishes mounting — meaning someone has opened or navigated to this page for the first time in their session, or navigated back to it from another page.
Note: When a user navigates away from a page and then back to it, the page is torn down and mounted fresh. This means On Page Load fires again each time the user returns to the page via navigation — it is not a one-time event for the lifetime of the session.
Example — Using On Page Load to fetch initial data
A common On Page Load action sequence:
On Page Load: 1. Run data source: customer_list_query 2. Run data source: notifications_query 3. Set variable: selectedTab = "overview"
This ensures data is available immediately after the page renders, and that the UI starts in a predictable state regardless of where the user navigated from.
On Page Focus
Fires when the browser tab or window regains focus while the page is already mounted. Unlike On Page Load, this trigger does not fire when the page first opens — only on subsequent focus events.
Typical uses:
Refreshing a data source after the user returns from another browser tab
Checking for new notifications when the user comes back to the app
Resuming a timer or interval that was paused while the tab was hidden
Tip: Use On Page Load for the initial data fetch, and On Page Focus for a lighter "refresh" that checks for updates without fully reloading. This pattern gives users fresh data when they return to a tab without triggering a full re-fetch on every navigation.
On Receive MQTT Event
Available when the page is wired to an MQTT integration. Fires each time a message arrives on the configured MQTT topic. Use this to update page state in real time in response to server-pushed events — for example, updating a machine status indicator as telemetry arrives.
Walkthrough Triggers
Two triggers support pages that participate in walkthroughs:
| Trigger | When it fires | Common use |
| On Walkthrough Pre Start | Immediately before a walkthrough begins on this page | Prepare page state before the walkthrough starts — set variables, navigate to the correct tab |
| On Walkthrough Pre End | Immediately before a walkthrough ends on this page | Clean up or log completion when the walkthrough finishes |
Trigger vs Data Source Auto-Run
Both page triggers and data source auto-run settings can cause a data source to execute when a page opens. Understanding the difference prevents unexpected double-fetches and ensures your intended sequencing.
| Mechanism | How it works | Best for |
| Data source auto-run | The data source is configured to run automatically on its own timing — on page load or when its inputs change. This is a setting on the data source itself, independent of any page trigger. | Simple cases where one data source should fetch independently on load. The default for most data sources. |
| On Page Load trigger | An explicit action sequence that runs when the page mounts. You add "Run data source" actions to this sequence manually. | Coordinating multiple data sources that should run in a specific order. Running other actions (set variables, logging) alongside the fetch. Centralizing all page initialization in one visible place. |
Warning: If a data source is set to auto-run on page load and you also add it to the On Page Load action sequence, it will run twice — once from its own setting and once from the trigger. Configure one or the other, not both, for each data source.
No Page Leave Trigger
UnifyApps does not currently provide an "on page leave" or "before navigate away" trigger. If you need to perform cleanup or save draft state when a user leaves a page, use one of these alternatives:
Auto-save at regular intervals using a polling or interval mechanism
Save state to a page variable and persist it to a data source on explicit user action (Save button)
Use the On Page Load trigger on the destination page to handle any initialization that depends on what the user was doing before
All Page Triggers at a Glance
| Trigger | When it fires | Fires on first load? | Notes |
| On Page Load | Page finishes mounting | Yes | Also fires when user navigates back to the page — page tears down and remounts fresh each time. |
| On Page Focus | Browser tab/window regains focus while page is mounted | No | Does not fire on first load. Only fires on subsequent focus events after the page is already open. |
| On Receive MQTT Event | MQTT message arrives on configured topic | No | Requires MQTT integration to be configured on the page. |
| On Walkthrough Pre Start | Just before a walkthrough begins on this page | No | Only available when page is part of a walkthrough. |
| On Walkthrough Pre End | Just before a walkthrough ends on this page | No | Only available when page is part of a walkthrough. |
Configuring Page Triggers
Open Page Settings: In the builder, click the page root in the hierarchy or open the page settings from the top toolbar. Navigate to the Events tab.
Select the trigger: Choose the trigger you want to configure — for example, On Page Load. An empty action list for that trigger appears.
Add actions: Click Add Action to add items to the action sequence. Actions run in order from top to bottom. You can add as many actions as needed — run data sources, set variables, navigate, show toasts, or call custom logic.
Test in preview: Use the builder's preview mode to verify that the trigger fires at the correct moment and produces the expected results. Check that data sources load in the right order and that variables are set correctly before any blocks attempt to read them.
Best Practices
Tip: Put all page startup logic — data fetches, variable initialization, and setup actions — in a single On Page Load action sequence. This makes the page's startup behavior easy to read and debug in one place.
Tip: Do not use the loading layout for normal page data fetching. Instead, bind a spinner or placeholder block's visibility to {{ your_datasource.isLoading }}. Reserve the loading layout for when the page is used as a template component.
Tip: If you use a loading layout and later rearrange or add blocks to the page, run Regenerate from the Loader section to keep the skeleton in sync with the current page body. A stale skeleton that no longer matches the real layout degrades the loading experience.