Skip to content

4. Configure the Application in the Frontend Development Kit

The Frontend Development Kit (FDK) is where you build your client-facing frontend application. You can use drag-and-drop components from the OR Frontend Library and connect them to the data schemas you created in the DDK.

What You'll Learn
  • Set up an FDK workspace and create a new application
  • Build the core UI with a map, layer, and panel
  • Connect frontend data connections to your deployed DDK server
  • Regenerate data connection types
  • Configure panels using the Panel Builder
  • Add custom code for simulation logic
  • Build, deploy, and test your frontend application

4.1 Set Up the Frontend Workspace

In the left sidebar, click FDK. A Create frontend workspace modal appears.

  1. Click Create and wait for the initialisation to finish.
Create frontend workspace
  1. Once complete, you should see an empty workspace.
frontend workspace installed

WARNING

Some components already support update and delete actions, and these capabilities will be added to the remaining components soon.

  1. In the left panel, click New Application.
New Application
  1. In the Create application wizard:
    • Set Application name to fleet-management
    • Add a description
Create application form
  1. Click Create. Application creation usually takes about 1 minute.

4.2 Build and Configure the Application UI

After creation completes, your application appears in the left panel with default components in the visualiser.

Application in visualiser

INFO

When a new application is created, the following components are added by default:

  • Simulation Controls
  • Network Control
  • Home
  • Visualiser Control
  1. With your application selected, click the Components tab.
Library tab

FDK Visualiser Overview

  • Each component library has its own color, and the same color is used for its nodes in the visualiser
  • Nodes can have different actions depending on their type
  • For example, if a node represents a panel, Panel Builder action are also available

Component Types and Purpose

Each component type serves a specific purpose:

  • Data Connection: Add queries, mutations, and subscriptions.
  • Context Provider: Create shared application state.
  • Hook: Build reusable React hooks.
  • Map / Globe: Add map or globe visualisation.
  • Map Layer: Add data layers to the map.
  • Map Hover: Configure hover interactions.
  • Visualiser Control: Toggle visualiser visibility.
  • Panel: Create UI panels with different layouts.
  • Page: Add pages beyond the default Home page.
  1. Create a base map:

    • Drag or click the Map card
    • Enter a name and description, then click Next
    Create map step1
    • Review the default map parameters and update them if needed

      Create map step2
    • Click Create

After creation, the visualiser is populated with map-related nodes and connections.

Map created in visualiser

These blocks show that creating a map also creates required supporting components.

  1. Add a map layer by dragging Map Layer into the visualiser.

    • Configure the layer details:
      • Name: sim traffic
      • Add a description
      • Select the target map
      • Keep the default simulated geospatial points layer type
    • Click Next.
    Map Layer create step 1
    • Skip Layer props (Optional) and click Next.

      Map Layer create step 2
    • Skip Link to control (Optional).

      Map Layer create step 3
    • Click Create.

Once complete, the visualiser updates with the new map layer (sim traffic).

Sim traffic layer added

INFO

These connections provide a high-level representation of how components and enablers work together in your application.

  1. Build a panel to host the simulation form and execution logic.

    • Click the Panel card (or drag it into the visualiser).
Panel drag
  • Configure the panel:
    • Name: Sim form
    • Panel type: Nav
    • Add a description for your panel
    • Select an icon
    • Choose whether to hide the close button
  • Click Create.
Panel form
  • After completion, a panel node appears in the visualiser.
Panel in visualiser

With the panel in place, you can now create data connections and connect them to the panel.

4.3 Add Data Connections and Connect to the Deployed DDK Server

Do not skip this step

Adding data connections is an important step in linking your frontend application to your DDK. This allows you to see and execute your simulation in the browser.

  1. Set up a connection to a deployed DDK server by clicking Connect to server.
Connect to server button
  1. In the modal, select your deployed DDK server (likely transport) and click Connect.
Select DDK server
  1. Once the DDK server is successfully connected, create a mutation data connection for the simulation inputs. To do this, drag the Data Connection from the left panel into the visualiser. Then, fill in the form that appears as follows:
    • Data connection type: Mutation
    • Resolver: createSimSettings
    • Select the first four output fields
    • Name: createSimSettings
    • Panel: Sim form
    • Click Create
Create mutation

After the mutation is created, the visualiser should look like this:

mutation created

TIP

You can also select the data connection node you created and click the Edit icon to modify the settings you entered.

Edit Data Connection
  1. Create a lazy query to fetch simulation results:
    • Data connection type: Lazy query
    • Resolver: getSimOutcomeList
    • Select all output fields
    • Name: getSimOutcomeList
    • Panel: Sim form
    • Click Create
Create lazy query

After the lazy query is created, the visualiser should look like this:

lazy query created

4.4 Regenerate Data Connection Types

  1. Click the Regenerate button at the top center of the FDK interface.
  2. Select Data Connection Types and wait for generation to complete.
data connection types

Wait for generation to complete before moving to the next section.

data connection types generated

4.5 Configure the Panel with Panel Builder

The Panel Builder is a visual drag-and-drop tool for designing panel layouts. You can add components, connect data sources, and configure form logic, all without writing code manually.

4.5.1 Open the Panel Builder

  1. In the visualiser, locate the Sim Form panel node you created earlier.

  2. Click the Panel Builder on the node.

Panel Builder button

TIP

The Panel Builder icon only appears on panel nodes. If you don't see it, make sure you've selected the correct node.

  1. The Panel Builder interface opens in a new view:
Panel Builder view

4.5.2 Understand the Panel Builder Layout

Before proceeding, familiarize yourself with the Panel Builder interface:

Panel Builder Overview

Left Sidebar Tabs:

TabDescription
ComponentsPre-built UI components (forms, buttons, text) you can drag into your panel
DataData connections, context providers, local states, and custom functions

Canvas Sections:

SectionDescription
Panel HeaderTop area with left CTA, right CTA, and children slots
Panel BodyMain content area where you place your form and other components

4.5.3 Add Local State Variables

Before configuring the panel, you need to add some React state variables and imports to the simulation form file. These enable the form to track submission state and control the simulation.

Open the Code Editor

  1. Open the OR Code Editor in a new browser tab.

  2. If prompted, click Trust Authors to accept the setup prompts:

Trust authors
  1. In the file explorer, navigate to:

File Breadcrumb

orOrProjectstransportsimulationor-transportsimulation-uiappsfleet-managementsrcpanelsSimFormsim-form.tsx

Add State Declarations

  1. In sim-form.tsx, locate this block:
tsx
// #region function state code
// #endregion function state code
  1. Add the following hook and state declarations inside the block (between the two comments):
tsx
const { simulationControlsDispatch } = useSimulationControls();
const [simInputId, setSimInputId] = React.useState('');
const [fetchLoading, setFetchLoading] = React.useState(false);

What these do:

VariablePurpose
simulationControlsDispatchDispatches actions to control the simulation playback state
simInputIdStores the current simulation input ID for tracking
fetchLoadingBoolean flag indicating whether simulation results are being fetched

Add Import Statements

  1. In the same file, locate this block:
tsx
// #region import code
// #endregion import code
  1. Add the following imports inside the block:
tsx
import { TransitionType } from '@or/client';
import { useSimulationControls, type StoredSimOutputData } from '../../contexts/SimulationControls';
import useZoomToFeature from '../../visualisers/main-view/hooks/useZoomToFeature';
import { point } from '@turf/helpers';
Custom imports and states
  1. Save the file (Cmd+S on Mac or Ctrl+S on Windows).

4.5.4 Create Custom Functions

Now return to the Panel Builder browser tab. You will create two custom functions:

FunctionPurpose
handleIsLoadingReturns true when any loading state is active (shows spinner)
handleSubmitHandles form submission and triggers the simulation

Function 1: handleIsLoading

This function checks if any operation is in progress and returns a boolean for the loading state.

  1. In Panel Builder, select the Data tab in the left sidebar.

  2. Scroll down to the Custom Functions section.

  3. Click Add Function.

Add custom function button
  1. Configure the function:

    • Function name: handleIsLoading
  2. In the function body field, enter:

tsx
return (
  createSimSettingsLoading || getSimOutcomeListLoading || fetchLoading
);
  1. Click Create Function to save.
Loading custom function

Function 2: handleSubmit

This function processes form data and triggers the simulation when the user clicks submit.

  1. Click Add Function again.

  2. Configure the function:

    • Function name: handleSubmit
  3. Click Add Parameter and set:

    • Name: formData
    • Type: object
  4. In the function body field, enter:

tsx
const sections = Object.keys(formData?.formData);
const firstSection = sections[0];
setSimInputId(formData?.formData?.[firstSection]?.Id);

simulationControlsDispatch({ type: 'RESET_CONTROLS' });
fireCreateSimSettings({
  variables: {
	id: formData?.formData?.[firstSection]?.Id,
	longitude: formData?.formData?.[firstSection]?.Longitude,
	latitude: formData?.formData?.[firstSection]?.Latitude,
	radius: 5,
  },
});
  1. Click Create Function to save.
Handle submit custom function

TIP

Both custom functions are now available in the Data tab under Custom Functions. You will connect these to the form in the next step.

4.5.5 Design the Simulation Form

Now you will add a dynamic form component and configure it with input fields for the simulation.

Add the Form Component

  1. In Panel Builder, select the Components tab in the left sidebar.

  2. Find DynamicForm in the component list.

  3. Drag DynamicForm into the Panel Body area on the canvas.

Drag dynamic form into panel builder
  1. Click the Edit icon (pencil) on the DynamicForm component to open its configuration.

Configure the Form Section

  1. In the formSections property, select Static Value.

  2. Click Add Item to create a new form section.

  3. Fill in the section details:

PropertyValue
IDsimulation
NameSimulation

Add Input Fields

  1. In the fields section, add three fields with the following configurations:
FieldidnamelabelrequiredfieldTypedefaultValue
IdidIdIdtrueString(leave empty)
LongitudelongitudeLongitudeLongitudetrueFloat144.9631
LatitudelatitudeLatitudeLatitudetrueFloat-37.8136

Default Coordinates

The default longitude and latitude values (144.9631, -37.8136) represent Melbourne, Australia. Users can change these when running the simulation.

Simulation form

Configure Form Submission

  1. Scroll down to the submission settings.

  2. Configure onSubmitLabel:

    • Select Static Value
    • Enter: Create and Execute
  3. Configure onSubmit (what happens when the form is submitted):

    • Select Custom Function
    • Choose handleSubmit from the dropdown
    • For the formData parameter, select data(T)
  4. Configure isLoading (shows a loading spinner while processing):

    • Select Custom Function
    • Choose handleIsLoading from the dropdown
Select functions in dynamic form
  1. Click Apply Changes to save the form configuration.

  2. Click the Save button at the top right of the Panel Builder to save all panel changes.

Save button

Important

Make sure to click both Apply Changes and Save. If you skip either step, your changes may be lost.

Panel Builder configuration is complete. Next, you will add custom code to enable the simulation logic.

Future Simplification

Over time, more of this manual wiring will be handled directly through the Panel Builder, reducing the need for custom code.

4.6 Add Custom Code

4.6.1 Open the Code Editor

  1. Open the OR Code Editor in a new browser tab.

  2. If prompted, click Trust Authors to accept the setup prompts:

Trust authors

4.6.2 Update the Simulation Form File

  1. In the file explorer, navigate to:

File Breadcrumb

orOrProjectstransportsimulationor-transportsimulation-uiappsfleet-managementsrcpanelsSimFormsim-form.tsx

Sim-form code
  1. Locate this block:
tsx
// #region createSimSettings resolver onComplete code
// #endregion createSimSettings resolver onComplete code
  1. Add the following code inside the block:
tsx
fireGetSimOutcomeList();
setFetchLoading(true);
  1. Locate this block:
tsx
// #region getSimOutcomeList resolver response options code
// #endregion getSimOutcomeList resolver response options code
  1. Add the following code inside the block:
tsx
stopPolling,
startPolling,
  1. Locate this block:
tsx
// #region getSimOutcomeList resolver onComplete code
// #endregion getSimOutcomeList resolver onComplete code
  1. Add the following code inside the block:
tsx
const simResult = result?.getSimOutcomeList[0];
if (!!simResult) {
	// Stop polling once we have data
	stopPolling();
	setFetchLoading(false);
	setSimInputId('');

	const parsedData = parseStringifiedJSON(
		simResult.result,
	) as StoredSimOutputData;
	console.log(
		'parsedData',
		result,
		parsedData,
		simResult?.result,
	);
	const firstKey = Object.keys(
		parsedData as unknown as Record<
			string,
			Record<string, StoredSimOutputData>
		>,
	)[0];

	const simData = (
		parsedData as unknown as Record<
			string,
			Record<string, StoredSimOutputData>
		>
	)?.[firstKey]?.data;
	const timeStamps = Object.keys(simData);

	const centerPoint = simData[timeStamps[0]]?.[0]?.coordinates;

	zoomToFeature({
		feature: point(centerPoint as number[]),
		transitionType: TransitionType.FLY_TO,
		transitionDuration: 1000,
		maxZoom: 11,
	});

	simulationControlsDispatch({
		type: 'SET_ALL_CONTROLS',
		payload: {
			simId: simResult.id,
			playing: false,
			visible: true,
			open: true,
			startTime: parseInt(timeStamps[0]),
			currentTime: parseInt(timeStamps[0], 10),
			endTime: parseInt(
				timeStamps[timeStamps.length - 1],
				10,
			),
			playbackSpeed: 1,
			data: simData,
			events: [],
		},
	});
} else {
	if (simInputId !== '') {
		startPolling(10000);
	}
	simulationControlsDispatch({ type: 'RESET_CONTROLS' });
}
  1. Locate this block:
tsx
// #region function body code
// #endregion function body code
  1. Add the following code inside the block:
tsx
const zoomToFeature = useZoomToFeature();
const parseStringifiedJSON = (data: string): unknown => {
	try {
		return JSON.parse(data);
	} catch (e) {
		return null;
	}
};
  1. Save the file (Cmd+S on Mac or Ctrl+S on Windows).

4.6.3 Update the Map Layer File

  1. In the file explorer, navigate to:

File Breadcrumb

orOrProjectstransportsimulationor-transportsimulation-uiappsfleet-managementsrcvisualisersmain-viewlayerssim-trafficuseSimTraffic.ts

File tree
  1. Locate this block:
tsx
// #region import code
// #endregion import code
  1. Add the following import inside the block:
tsx
import { useMapViewState } from '../../../../contexts/MainView/MapViewState';
  1. Locate this block:
tsx
// #region function state code
// #endregion function state code
  1. Add the following code inside the block:
tsx
const { mapViewState } = useMapViewState();
  1. Locate this block:
tsx
// #region function body code
// #endregion function body code
  1. Add the following code inside the block:
tsx
const roundedZoom = React.useMemo(
	() => Math.round(mapViewState.zoom),
	[mapViewState.zoom],
);
  1. Locate this block:
tsx
// #region props code
// #endregion props code
  1. Add the following layer properties inside the block:
tsx
visible: simVisible,
// @ts-ignore - Accessor function type
getPosition: ({ coordinates }) => coordinates,
getFillColor: [235, 92, 42],
radiusUnits: 'pixels',
getRadius: roundedZoom / 4,
pickable: true,
updateTriggers: {
	getRadius: roundedZoom,
	visible: [simVisible],
},
  1. Save the file (Cmd/Ctrl + S).

4.7 Build, Deploy, and View in Browser

Now that your application code is complete, build and deploy it to see the simulation in action.

Build the Application

  1. In the FDK visualizer, click Build at the top center.
Build button
  1. Wait for the build to complete successfully.
Build complete

Configure Deployment

  1. Go to Nexus. In the left panel, find OR transportsimulation FE, click the three-dot menu (⋮), and select Configure Deployment.

  2. In the deployment wizard:

    • Set Version Tag to latest
    • Click Next
    • Click Save (no additional changes required)
Frontend deployment configuration

Deploy to Environment

  1. In Nexus, click Deploy (top center).

  2. Select transportsimulationui, then click Next and Deploy.

Deploy UI selection
  1. Wait until the deployment status changes to Succeeded.
Deployment completed

Open the Application

  1. In Nexus, select OR transportsimulation FE from the left panel.

  2. In the right panel, click the application link to open the app in a new browser tab.

Application link
  1. In the App Switcher on the left, select FM (Fleet Management) to open your frontend application.
Frontend application

Test the Simulation

  1. Open the Sim form panel on the left side of the application.

  2. Fill in the simulation form:

    • ID: Enter a unique number (e.g., 1001)
    • LON: Enter longitude (e.g., 144.9631 for Melbourne)
    • LAT: Enter latitude (e.g., -37.8136 for Melbourne)
  3. Click Create and Execute to run the simulation.

Simulation form

Improve Map Visibility

For better simulation visualization, click Map Style in the right-hand control panel and select Theme Match.

Theme Match option
  1. To run additional simulations, use a new unique ID for each run.

Unique IDs Required

Reusing the same ID may prevent the simulation from running. Always increment or change the ID value for each new simulation.

Simulation results on map

🎉 Congratulations!

You have successfully completed the FDK Quick Start tutorial!

Coming Soon

Additional workflow patterns and advanced topics will be added soon.

User documentation for Optimal Reality