Ping SDKs

DaVinci client sample apps

Applies to:

  • DaVinci client for Android

  • DaVinci client for iOS

  • DaVinci client for JavaScript

We provide the source code for sample applications that demonstrate how to integrate DaVinci flows into your mobile and web applications using the DaVinci client.

You can clone or download the sample source code from our GitHub repository at https://github.com/ForgeRock/sdk-sample-apps.

Each sample is a functional application designed to provide a practical guide for common integration scenarios. You can use them as a reference to understand key concepts or as a starting point for your own custom implementation.

The sample applications are provided "as is" for demonstration purposes only.

They are not official products of Ping Identity and are not officially supported.

We provide DaVinci client sample apps for the following platforms:

Android sample apps

kotlin-davinci

What does the kotlin-davinci sample support?
Feature Supported by sample

Orchestration

  • PingOne - DaVinci flows

Implementation

  • Embedded

Language

  • Kotlin

DaVinci Fields

  • Text

  • Password

  • Checkbox

  • Combobox

  • Dropdown

  • Label

  • Phone number

DaVinci Buttons

  • Flow button

  • Submit

  • Social sign-on

  • Radio

DaVinci Toolbox

  • OTP device registration

  • OTP device authentication

The kotlin-davinci application is a lightweight Android client.

Screenshot of the `kotlin-davinci` sample app on Android.

It is designed to demonstrate a core capability of the DaVinci client for Android: rendering a dynamic user interface based on signals received from a DaVinci flow.

Instead of having a hardcoded login screen, the app starts a DaVinci flow and waits for the server to send instructions on what to display. It then constructs the UI on-the-fly, whether it’s a username/password form, a message, or other interactive elements defined in your DaVinci flow.

The application’s code showcases several important implementation patterns for integrating with DaVinci:

1. Dynamic UI Rendering with Jetpack Compose

The app uses modern Android development practices, leveraging Jetpack Compose to build its user interface. The core logic resides in the DaVinciScreen.kt file.

  • It observes a state object from the DaVinciViewModel.

  • It uses a when statement to react to the current state of the DaVinci flow (Login, Success, or Failure).

  • For the Login state, it iterates through the list of collectors returned from the DaVinci flow and renders the appropriate Composable for each one.

    This is the dynamic part—if you change the DaVinci flow the UI will change without needing to recompile the app.

2. State Management with ViewModel and StateFlow

The application follows the recommended Android architecture by separating UI logic from business logic.

  • DaVinciViewModel.kt is responsible for all interactions with the Ping Identity SDK.

  • It uses a MutableStateFlow to hold the current state of the DaVinci flow (DaVinciAction). The UI (Composable functions) subscribes to this flow and automatically updates whenever the state changes.

    This decouples the SDK interaction from the UI, making the code cleaner and easier to test.

3. SDK Initialization and Configuration

The app demonstrates how to initialize and configure the SDK to connect to your specific PingOne and DaVinci environment. In DaVinciViewModel, it shows how to:

  • Provide the necessary DaVinci client configuration

  • Start the DaVinci flow by calling start().

4. Handling User Input

The sample shows how to collect data from the dynamically rendered input fields, such as username and password fields, package it into a Map, and submit it back to DaVinci using the action.next() method.

This is the mechanism for advancing the flow after a user provides their credentials or makes a choice.

iOS sample apps

swiftui-davinci

What does the swiftui-davinci sample support?
Feature Supported by sample

Orchestration

  • PingOne - DaVinci flows

Implementation

  • Embedded

Language

  • Swift

DaVinci Fields

  • Text

  • Password

  • Checkbox

  • Combobox

  • Dropdown

  • Label

DaVinci Buttons

  • Flow button

  • Submit

  • Social sign-on

  • Radio

The swiftui-davinci application is a modern iOS client built with Swift and SwiftUI.

Screenshot of the `swiftui-davinci` sample app on iOS.

It’s designed to demonstrate a core capability of the DaVinci client for iOS: rendering a dynamic user interface based on collectors received from a DaVinci flow.

Instead of having a hardcoded login screen, the app initiates a DaVinci flow and waits for the server to send collectors, which describe the required data. It then constructs the UI on-the-fly, whether it’s a username and password form, a message, or other interactive elements defined in your DaVinci flow.

The application’s code showcases several important implementation patterns for integrating with DaVinci using modern iOS development practices:

1. Dynamic UI Rendering with SwiftUI

The app uses SwiftUI to build its user interface declaratively. The core rendering logic resides in ContentView.swift.

  • It observes a state object from the DavinciViewModel.

  • It uses a switch statement to react to the current state of the DaVinci flow, either .loading, .loaded, or .success).

  • For the .loaded state, it iterates through an array of collectors returned by the DaVinci flow and renders the appropriate SwiftUI View for each one.

    This is the dynamic part—if you change the DaVinci flow on the server, the UI will change without needing to recompile the app.

2. State Management with Combine and ViewModel

The application follows the recommended MVVM (Model-View-ViewModel) architecture by separating UI logic from business logic.

  • DavinciViewModel.swift is responsible for interactions with the DaVinci client for iOS.

  • It uses @Published properties from the Combine framework to hold the current state of the DaVinci flow, such as flowState and inputs. The SwiftUI View subscribes to these properties and automatically updates whenever their values change.

    This decouples the SDK interaction from the UI, making the code cleaner and easier to manage.

3. SDK Initialization and Configuration

The app demonstrates how to initialize and configure the SDK to connect to your specific PingOne and DaVinci environment.

  • Provide the necessary DaVinci client configuration

  • Start the DaVinci flow by calling the start() method.

4. Handling User Input and Flow Progression

The sample shows how to collect data from the dynamically rendered input fields, bind it to a dictionary in the ViewModel, and submit it back to DaVinci.

This is the mechanism for advancing the flow after a user provides their credentials or makes a choice.

JavaScript sample apps

reactjs-todo-davinci

What does the reactjs-todo-davinci sample support?
Feature Supported by sample

Orchestration

  • PingOne - DaVinci flows

Implementation

  • Embedded

Language

  • ReactJS

DaVinci Fields

  • Text

  • Password

  • Checkbox

  • Combobox

  • Dropdown

  • Label

  • Phone number

DaVinci Buttons

  • Flow button

  • Submit button

  • Social sign-on

  • Radio

DaVinci Toolbox

  • OTP device registration

  • OTP device authentication

The reactjs-todo-davinci application is a "To-Do List" single-page application (SPA) built with ReactJS.

javascript angular todo davinci sample

Its primary purpose is to demonstrate how to secure a React application by embedding a PingOne DaVinci flow directly into the user experience.

Instead of a static login form, the application initiates a DaVinci flow and dynamically renders the necessary UI components based on the collectors it receives from the server. Once a user is authenticated, they can access the protected To-Do list page, showcasing a complete, secure workflow from login to application usage.

This sample optionally uses the javascript/todo-api sample app to act as the backend API, but will also run without the API backend.

The application showcases several modern, best-practice patterns for integrating the DaVinci client for JavaScript within a React project:

1. Global State Management with React Context

The application uses React’s built-in Context API for managing shared state, which is a lightweight and effective alternative to larger libraries like Redux for this use case.

  • Location: javascript/reactjs-todo-davinci/client/global-state.js

  • Function: It defines a custom hook, useGlobalStateMgmt, which encapsulates all the logic for managing shared state like isAuthenticated, username, and theme. The AppContext then makes this state and its setter functions available to any component wrapped in its provider.

    The setAuthenticationWrapper function couples the application’s state with the DaVinci client’s functionality. When a component sets the authentication state to false, this wrapper interprets it as a logout action and triggers logout(), ensuring the user’s session is properly terminated PingOne.

2. Dynamic, View-Based Routing

The application uses react-router-dom to manage navigation, with a structure that separates public and private views.

  • File: javascript/reactjs-todo-davinci/client/router.js

  • Function: The Router component defines all application routes. It makes use of a custom ProtectedRoute component to guard access to the /todos page.

    This guard checks the isAuthenticated flag from the global context and redirects unauthenticated users to the /login page.

3. Component-Driven DaVinci Flow

The login experience is not hardcoded but is driven by the DaVinci flow itself.

  • File: javascript/reactjs-todo-davinci/client/views/login.js

  • Function: The Login view acts as a container. It renders a dedicated <Form /> component (refer to javascript/reactjs-todo-davinci/client/components/davinci-client/form.js).

    This Form component is responsible for initiating the DaVinci flow, listening for collectors, and dynamically rendering the appropriate input fields, such as a username and password. This architecture makes the login UI incredibly flexible, as the entire user journey can be modified in the DaVinci flow builder without changing the React code.