Build multipage appsBeta
Build peformant multipage apps.
Standard Retool apps operate as single-page applications where all code and components is continually evaluated. You typically build separate apps for different use cases, such as an inventory management app or refund tool. With multipage apps, you can create a single app that separate distinct use cases into pages. Retool only evaluates the code and components of the page currently in view, making them much more performant for complex needs.
Known issues and limitations
The multipage apps beta contains the following known issues and limitations.
- Retool Cloud
- Self-hosted Retool
- Multiplayer is not currently supported.
- Custom product pages are not currently supported.
- Custom CSS and custom keyboard shortcuts do not currently support
{{ }}
embedded expressions for page elements. - Debug Tools does not display an accurate performance score.
- Some code editors may display an Incorrect scope error even though the scope is valid.
- In self-hosted Retool versions 3.88 or earlier, importing an app into a protected multipage app may not work correctly if you have local changes on the branch. To ensure that local changes are saved, commit and publish all local changes before you attempt to import an existing app.
- Multiplayer is not currently supported.
- Custom product pages are not currently supported.
- Custom CSS and custom keyboard shortcuts do not currently support
{{ }}
embedded expressions for page elements. - Debug Tools does not currently display an accurate performance score.
- Some code editors may display an Incorrect scope error even though the scope is valid.
- If an imported app uses Expand to fit content, this setting is not preserved. You can re-enable this option from the Inspector.
- Only one page-scoped Split Pane frame is currently supported.
- Styles and themes only apply to the default page.
- Within public multipage apps, switching between pages causes an error.
- Certain elements are not correctly rendered in embedded multipage apps.
Get started
You can either build a new multipage app or select an existing app to duplicate as a multipage version.
- Create a new multipage app
- Start from an existing app
Navigate to the tab in your organization and click Create > Multipage app.
If you have an existing app and want to use it as a starting point for a multipage app:
- Navigate to the tab in your organization.
- Find the app you wish to use.
- Click the ••• contextual menu and select Duplicate to multipage.
When duplicating an existing app as a multipage app:
- The default page contains all code and components from the original app. As such, all code is page-scoped.
- Any Header and Sidebar frames are configured for the multipage app.
- Any app settings are ignored. This includes:
- Preloaded JavaScript and libraries.
- Custom CSS.
- Custom keyboard shortcuts.
Existing apps that use container views to group components
If you have an app that uses a Container component with multiple views to mimic separate pages (e.g., a Tabbed Container), duplicate the app as a multipage app and create pages for each view. You can then select and copy all components in each container view and paste them into new pages. You must then move or edit relevant code and components based on the required scope.
Check any value references to ensure that code and components correctly reference each other after completing these steps.
Multipage app model
With multipage apps, each page contains its own code and components. Users switch between pages using event handlers or navigation controls. Retool only evaluates their values when the page is currently in view. This allows for apps to serve multiple functions without impacting performance.
Multipage apps are particularly useful for consolidating apps by use case. For example, a support team may use a collection of different single-page apps within an organization. You can consolidate the functionality they provide into a multipage app without affecting performance, providing support team members with a single tool to use.
In addition, multipage apps help reduce the overall number of apps within an organization. This can help with how you organize apps or grant permissions, since pages are contained within the multipage app.
Global and page scopes
Multipage apps use global and per-page scopes for code and components. Globally-scoped code and components can be referenced anywhere in the multipage app. Page-scoped code and components can only be referenced within the same page.
Globally scoped code and components
You can create Global code (e.g., resource queries or variables) for which all pages can reference. Each page can interact with globally-scoped code to trigger queries, set variable values, etc.
You can drag code to either the Global or Page to change its scope. You can also move code across pages using the Move to page contextual menu action.
The Header and Sidebar frames are also globally scoped and persist across all pages. Any components within these frames inherit this behavior and are globally scoped. All other frames (e.g., Modal and Drawer) are page-scoped and only available within the app in which they reside.
Globally-scoped code and components can only reference other globally-scoped values.
Page-scoped code and components
All code and components within a page are page-scoped, and cannot be referenced by other pages. If a page contains code or event handlers that would run on page load, these run whenever you switch to the page.
Manage pages
Multipage apps require at least one page to use as a default page. A blank defaultPage page is initially included for you to use that's set as the default.
Use the page selection menu in the IDE toolbar to quickly switch between pages.
The Pages tab contains a list of pages within the multipage app. You can explore and manage all pages within the multipage app, change the default page, and view more details.
Default page
The default page is the first page that opens when launching the app. You can change the default page at any time by opening the contextual menu and selecting Set as default page.
Add a new page
Click + > Page to add an empty page to your multipage app. Switching to another page updates the IDE to show only that page's code and components.
Import an existing app as a page
You can also import an existing app as a new page to eliminate the need for rebuilding an app from scratch. Click + > Import app as page and select the app to import.
When you import an existing app as a page:
- Header and Sidebar frame conflicts must be handled. You can choose to retain the multipage app's existing frames or override them with the incoming app.
- All code is page-scoped.
- Any app settings are ignored.
If you override the Header or Sidebar frames using the imported app, value reference errors may occur. You must verify and update any code or components that rely on values within these frames, such as accounting for globally scoped and page-scoped value changes.
Best practices for importing apps
Follow these recommendations when importing existing apps as pages.
Multiple apps that share Header and Sidebar frame content
Multipage apps have a global Header and Sidebar frame. If you have a collection of apps that share the same Header or Sidebar frame content using a module (e.g., shared navigation), import each app and create the necessary Header or Sidebar frame content.
Page URLs
Each page has a title and URL that you configure from the Inspector. The page URL is appended to the multipage app URL and allows for deep-linking to specific pages. For example, a page with the URL of customers
would be available at https://example.retool.com/app/support-dashboard/customers
.
Pass data between pages
Multipage pages cannot directly interact with each other. You can use globally scoped variables, localStorage, or URL parameters to pass data between pages.
- Global variables
- localStorage
- URL parameters
Variables temporarily store data for the duration of the user's app session. They can also include an optional initial value.
To create a global variable, navigate to the Code tab and click + > Variable. As the variable is globally scoped, you can update its value from any page using event handlers, or with the setIn()
and setValue()
JavaScript methods.
You can then reference the global variable from any screen.
For example, you can use the Table component's Double Click Row event handler to store the selected row data in a global variable. You can then reference the global variable in another page, such as a component value.
If a user closes the tab, navigates away from the app, or opens the multipage app in another tab, the variable reverts to its initial value.
localStorage does not encrypt data. Only use localStorage to store nonsensitive information.
localStorage temporarily stores data in the browser's localStorage. Unlike variables, localStorage is a persistent data store. Provided the user continues to use the same browser and has not cleared their browsing history or cache, data remains available.
Use event handlers or the setValue()
JavaScript method to store data in localStorage. You can also clear app-specific data using clear()
.
URL parameters are plain text and often included when sharing URLs. Do not store any sensitive information in URL parameters.
You can configure URL query parameters on a per-page basis. As with URL queries for single-page apps, pages can store values in the URL.
To use URL query parameters, select a page and then configure its URL search params and URL hash params key-value properties. You reference property values, such as textInput1.value
, which dynamically updates the URL parameter. You can also access URL parameters for the page using url
, such as configuring the default value of a component to the initial URL parameter value when launching the app.
Navigate between pages
You can add pages to a Navigation component which automatically use an active state when the page is currently in view. If you want to switch pages using another method, you can configure any event handler with the Go to page action, such as a button click.
View the dependency graph
Hover the cursor over the connecting points to display a tooltip with a list of dependencies and dependents.
The Component tree and Code panels contain the Graph pane. This visualizes the dependency graph for a selected component or query. You can use the graph to view the relationship between the selected component or query and its immediate dependents.