Frequently Asked Questions
How do I pass backend configuration to the frontend?
Section titled “How do I pass backend configuration to the frontend?”Often, iTwin Studio Apps require the backend to provide initialization or configuration data to the frontend. StudioHost has a method to set configuration data on the backend, while StudioApp has a method to retrieve this data on the frontend.
Setting Data On Backend
In the backend, StudioHost provides a method called finalizeFrontendInitData(), which accepts a JSON object as input. This method stores the initialization data for the frontend to fetch when needed. It’s advisable to call this method in the backend as early as possible, within activateBackend(). Below is an example of how to use it:
export function activateBackend() { StudioHost.finalizeFrontendInitData({ USE_DEBUGGER: process.env.USE_DEBUGGER, DEV_MODE: process.env.DEV_MODE, });}Getting Data On Frontend
On the frontend, StudioApp offers a method called getFrontendInitData(), which retrieves the data set by finalizeFrontendInitData() on the backend. Since this method relies on data already being set in the backend, it’s important to ensure that finalizeFrontendInitData() has been called before using getFrontendInitData(). Below is an example of how to use this method in frontend code:
export function activateFrontend() { const initDataResult = await StudioApp.getFrontendInitData();}If getFrontendInitData() fails to retrieve data within a specified time (default is 5000ms), it may time out with an error. Users can increase the timeout by providing an optional options parameter to the method, as shown below:
StudioApp.getFrontendInitData({ timeoutInMS: 7000 });How do I make sure my development environment is up-to-date?
Section titled “How do I make sure my development environment is up-to-date?”@bentley/studio-cli has a studio-cli apps runtime-check command. On a Windows machine, navigate to your package directory and run the following to keep your debug environment up-to-date (run without the --fix flag to see the changes first):
npx --registry="https://pkgs.dev.azure.com/bentleycs/_packaging/Packages/npm/registry/" @bentley/studio-cli@latest apps runtime-check --fixHow do I add styles and css?
Section titled “How do I add styles and css?”iTwin Studio’s build tools support .scss, .module.scss, .css, and .module.css files.
Import the file and it will be automatically bundled for you.
import "styles.css";import "styles.scss";import styles from "styles.module.css";import styles from "styles.module.scss";How do I add user preferences?
Section titled “How do I add user preferences?”In iTwin Studio, each app can have its own user preferences that users can modify using the User Preferences Editor. All user modified user preferences are stored in a userPreferences.json (or userPreferences.qa.json) file. On Windows, the path is %APPDATA%\Bentley\iTwin Studio\userPreferences.json. To integrate your app’s user preferences into the User Preferences Editor, follow these steps:
Step 1: Define the User Preferences Schema
Section titled “Step 1: Define the User Preferences Schema”The first step is to create a JSON Schema file that defines the structure of your app’s preferences. This file should be added to the backend of your application and copied into your dist at build-time (see how to copy assets here). In the schema file, specify the preferences’ names, data types, and default values.
{ $schema: "http://json-schema.org/draft-07/schema", $id: "MyAppsSettings", type: "object", groupName: "myAppName", properties: { "myAppName/openSelectionOnStartup": { title: "Always start iModel Selection page", description: "MyApp:openSelectionOnStartup.description", // localized key type: "boolean", default: true, }, "myAppName/maxRecents": { title: "Max Recents", type: "number", default: 5, description: "MyApp:maxRecents.description", // localized key }, },}You can learn more about JSON Schema at JSON Schema Website.
Step 2: Import and Use Schemas
Section titled “Step 2: Import and Use Schemas”In your backend code, you’ll need to import the StudioHost singleton from the @bentley/studio-apps-backend-api library. Initialize the schema by calling StudioHost.addUserPreferencesSchemaFile('path/to/schema/json'), where you provide the path to the JSON file you defined in Step 1. This step allows the User Preferences Editor in iTwin Studio to recognize your app’s preferences, and users can modify the values through the interface.
import { StudioHost } from "@bentley/studio-apps-backend-api";const schemaPath = StudioHost.resolveAssetPath("backend/assets/settings.schema.json");await StudioHost.addUserPreferencesSchemaFile(schemaPath);Step 3: Access Settings
Section titled “Step 3: Access Settings”As a developer, you can access the app’s settings on both the backend and the frontend:
Backend Access:
Developers can access the preferences on the backend using the StudioHost.getUserPreference method. This method enables you to retrieve the values of your app’s preferences and use them as needed in your backend logic.
Frontend Access:
On the frontend, developers can access the app’s preferences using the StudioApp.getUserPreference() method. This way, you can utilize these preferences in the app’s user interface and functionality on the frontend side.
For more comprehensive details and examples on how preferences are different from settings utilized in iTwin.js applications, you can refer to the iTwin.js Documentation.
How do I add icons or svgs?
Section titled “How do I add icons or svgs?”There are two ways how svgs can be used in apps:
ES6 imports
Section titled “ES6 imports”Like in any other application, you can use ES6 import syntax:
import icon from "./{relative path to svg}"Currently supported formats include SVG, PNG and JPG images.
Troubleshooting
Section titled “Troubleshooting”- Build fails due to missing loader
No loader is configured for ...Ensure that a loader is configured for your image. This can be done by adding a declaration.d.ts file in your frontend directory. Below is an example for SVG files:
declare module '*.svg' { const content: string; export default content;}Separate module declaration is need for every image type (png/jpg/svg) that is used in your project.
- SVG is missing it’s
<styles>tag after compiling.
There are known issues with loading more complex SVGs that rely on the styles tag. We recommend using the second approach for loading them, or getting in touch with our team to discuss this further.
Using studio-app URL
Section titled “Using studio-app URL”In addition to using ES6 imports, assets can be loaded directly. This is mainly used to allow iTwin Studio to find images belonging to a specific app (to display them in the sidebar, etc.), but can be used within an app as well.
- Copy your assets folder to the
distfolder. In your dev/build scripts, use the--copyarg to specify the folder location.
--copy frontend/assets- Assets can be accessed via
StudioApp.resolveAssetPath
StudioApp.resolveAssetPath("fronted/assets/icon.svg");Note that the path should be relative to the root folder.
To use it as an image, we recommend using an img tag to resolve the image source.
<img src=${StudioApp.resolveAssetPath("fronted/assets/icon.svg")}/>Posting telemetry (Azure Application Insights) in apps
Section titled “Posting telemetry (Azure Application Insights) in apps”iTwin Studio exposes telemetry methods from its APIs. In order to post telemetry to Azure Application Insights , apps need to first initialize the telemetry service by calling StudioHost.initializeTelemetry(instrumentalKey) in the activateBackend method. After initializing, we can post the telemetry by calling StudioHost.postTelemetry({ ...telemetryData }) in the backend and StudioApp.postTelemetry({ ...telemetryData }) in the frontend.
How to Upload Sourcemaps to Sentry
Section titled “How to Upload Sourcemaps to Sentry”Follow these steps to use studio-cli and upload your sourcemaps to Sentry using the sentry-cli option.
Prerequisites
Section titled “Prerequisites”- Ensure you are logged in to Sentry CLI or have set the necessary credentials. For more details, refer to the Sentry CLI documentation.
-
Build your app with the
--externalSourcemapflag enabled:Terminal window studio-cli apps build --externalSourcemap -
Inject Sentry Debug IDs into the build code and sourcemaps:
Terminal window sentry-cli sourcemaps inject dist -
Package your app:
Terminal window studio-cli apps packageBy default,
.mapfiles are excluded from the zip. Use the--devflag if you want to include them. -
Upload sourcemaps to Sentry:
Terminal window sentry-cli sourcemaps upload
You should now be able to see readable stack traces in your Sentry errors.
Internal-only FAQs
Section titled “Internal-only FAQs”Determining which environment you are in
Section titled “Determining which environment you are in”Use StudioApp.getApiOverrides() from @bentley/studio-apps-frontend-api to determine which development environment you are in. The API will return a serverEnvironmentPrefix of “dev”, “qa”, or "".
import { StudioApp } from "@bentley/studio-apps-frontend-api";const environment = StudioApp.getApiOverrides();Switching environments between PROD and QA
Section titled “Switching environments between PROD and QA”How can I build a modular iTwin Studio app to prepare for dynamically loaded apps?
Section titled “How can I build a modular iTwin Studio app to prepare for dynamically loaded apps?”Currently, iTwin Studio apps are designed to be monolithic. In the future, apps will be able to be composed of smaller units that can be delivered separately and optionally download and installed by users via an app store. In order to prepare for this, and for good practice in general, it is advised to build larger apps as a collection of smaller modules. For now, the modules should be npm packages that may be published (internally to Azure Artifacts).
Dynamic apps will be restricted in their contribution points and in their allowed API usage. To begin to prepare for this, modules should use the @bentley/studio-apps-frontend-api and @bentley/studio-apps-backend-api packages for Studio APIs. Apps that contain these modules can use these packages as well, in addition to the @bentley/studio-startup-apps-frontend-api and @bentley/studio-startup-apps-backend-api packages, which contain additional APIs that will not be available to modules and dynamic apps. Dynamic app APIs will likely be even more restrictive, but this is the best path towards isolating code that you wish to deliver independent of your main app code in the future.
In order to facilitate this type of iTwin Studio app development, it is a good idea to use a monorepo, where modules can be locally linked to the app in which they are imported. This allows for easier development of modules without having to publish them ahead of time. There are many monorepo tools available that aid in this type of development, including pnpm workspaces.