Using the Scheduler Editor Component
The Scheduler Editor Component lets your users access the Scheduler Editor within your application, so they can create and manage Scheduling Pages. This page explains how to customize the Scheduler Editor Component.
How the Scheduler Editor Component works
Nylas offers the Scheduler Editor Component as a pre-built, extensible web- (HTML/Vanilla JS) and React-based UI Component. After you add it to your project, organizers can use the Scheduler Editor to create and customize Scheduling Pages within your application.
The Scheduler Editor Component includes...
- Custom event handlers that let you define specific logic or behavior for user actions.
- Composable components that let you customize how each sub-component is arranged and rendered in the UI.
- Custom UI stylings that support CSS shadow parts for a higher level of customization.
For more information, see the UI Components references.
Configuration modes
The Scheduler Editor Component supports two configuration modes: app
and composable
. By default, the Component is set to app
mode. This allows it to render all sub-components by default, meaning you can embed the pre-built components in your project with minimal configuration.
You can use the composable
mode to customize how the Scheduler Editor Component arranges and renders each sub-component in the UI. In this mode, you can use sub-components as stand-alone components.
For more information, see the Scheduler Editor Component references.
Set up the Scheduler Editor Component
Before you can start using the Scheduler Editor Component in your project, you need to configure authentication for it. This lets the Component make requests to the Nylas APIs. There are two ways to set up auth:
- Using the
nylasSessionsConfig
property (Hosted Auth). - Using the
nylasApiRequest
property (existing Hosted Auth flow, or Custom Auth).
Set up authentication with nylasSessionsConfig
To set up Hosted Auth for the Scheduler Editor Component, set nylasSessionsConfig
with the following properties:
clientId
: Your application's client ID from the Nylas Dashboard.redirectUri
: The URL that the OAuth provider sends users to after they authenticate.domain
: The Nylas auth domain (U.S.:https://api.us.nylas.com/v3
, E.U.:https://api.eu.nylas.com/v3
).hosted
: Whentrue
, Nylas redirects users to the Hosted login component.accessType
: Whenoffline
, specifies that Nylas should return a refresh token with the access token.
<html>
<body>
<nylas-scheduler-editor />
<script type="module">
import { defineCustomElement } from "https://cdn.jsdelivr.net/npm/@nylas/web-elements@latest/dist/cdn/nylas-scheduler-editor/nylas-scheduler-editor.es.js";
defineCustomElement();
const schedulerEditor = document.querySelector("nylas-scheduler-editor");
schedulerEditor.nylasSessionsConfig = {
clientId: '<NYLAS_CLIENT_ID>',
redirectUri: `${window.location.origin}/scheduler-editor`,
domain: 'https://api.us.nylas.com/v3',
hosted: true,
accessType: 'offline'
}
</script>
</body>
</html>
import React from 'react';
import { NylasSchedulerEditor } from "@nylas/react";
function App() {
return (
<NylasSchedulerEditor
nylasSessionsConfig={{
clientId: "<NYLAS_CLIENT_ID>",
redirectUri: `${window.location.origin}/scheduler-editor`,
domain: "https://api.us.nylas.com/v3",
hosted: true,
accessType: 'offline'
}}
/>
);
}
export default App;
Set up authentication with nylasApiRequest
Before you can use nylasApiRequest
, you need to download the latest version of the Nylas identity package.
npm i @nylas/identity@latest
Now you can use nylasApiRequest
to set up auth for the Scheduler Editor Component. You have two options for this:
- Using
nylasApiRequest
with theNylasIdentityRequestWrapper
for existing Hosted Auth flows. - Using
nylasApiRequest
with theCustomIdentityRequestWrapper
for Custom Auth flows.
Use existing Hosted Authentication flow
📝 You must have an existing Hosted Auth flow in your Nylas application to use this configuration.
You can use the nylasApiRequest
property with the NylasIdentityRequestWrapper
to configure the Scheduler Editor Component with your existing Hosted Auth details.
<html class="h-full bg-white" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Nylas Scheduler Editor with auth using NylasIdentityRequestWrapper</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet" />
<style type="text/css">
body {
font-family: "Inter", sans-serif;
}
</style>
</head>
<body class="h-full">
<div class="grid h-full place-items-center">
<!-- Add the Nylas Scheduler Editor Component -->
<nylas-scheduler-editor />
</div>
<!-- Configure the Nylas Scheduler Editor Component -->
<script type="module">
import { defineCustomElement } from "https://cdn.jsdelivr.net/npm/@nylas/web-elements@latest/dist/cdn/nylas-scheduler-editor/nylas-scheduler-editor.es.js";
import { NylasSessions } from 'https://cdn.jsdelivr.net/npm/@nylas/identity@latest/dist/nylas-identity.es.js';
import { NylasIdentityRequestWrapper } from 'https://cdn.jsdelivr.net/npm/@nylas/web-elements@latest/dist/esm/index.js';
defineCustomElement();
// Specify settings for Nylas identity management
const config = {
clientId: '<NYLAS_CLIENT_ID>',
redirectUri: `${window.location.origin}/login`,
domain: 'https://api.us.nylas.com/v3',
hosted: false,
accessType: "offline",
};
const identity = new NylasSessions(config);
async function checkLoggedIn() {
const loggedIn = await identity.isLoggedIn();
return loggedIn;
}
// Create new nylasApiRequest instance
const nylasApiRequest = new NylasIdentityRequestWrapper(identity);
// Specify Scheduler Editor Component details
const schedulerEditor = document.querySelector("nylas-scheduler-editor");
schedulerEditor.nylasApiRequest = nylasApiRequest;
schedulerEditor.schedulerPreviewLink = `${window.location.origin}/?config_id={config.id}`;
schedulerEditor.eventOverrides = {
// The default behavior of the close button is to log the user out, so redirect to the login page.
schedulerConfigCloseClicked: async (e) => {
setTimeout(async () => {
window.location.href = `${window.location.origin}/login`;
}, 3000);
},
}
schedulerEditor.defaultSchedulerConfigState = {
selectedConfiguration: {
requires_session_auth: false, // Creates a public Configuration.
},
};
// Redirect to the login page if the user is not logged in.
checkLoggedIn().then((loggedIn) => {
if (!loggedIn) {
window.location.href = `${window.location.origin}/login`;
}
});
</script>
</body>
</html>
import { BrowserRouter, Route, Routes } from "react-router-dom";
import { NylasSchedulerEditor, NylasScheduling } from "@nylas/react";
import LoginComp from '@nylas/login-component';
import "./App.css";
import { NylasSessions } from '@nylas/identity';
import { NylasIdentityRequestWrapper } from '@nylas/react';
function App() {
// Get the configuration ID from the URL query string
const urlParams = new URLSearchParams(window.location.search);
const clientId = '<NYLAS_CLIENT_ID>';
const configId = urlParams.get("config_id") || "";
const componentSettings = {
// Adjust the scopes as needed
authSettings: {
scopes: {
google: [
'openid',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/contacts',
'https://www.googleapis.com/auth/calendar',
'https://www.googleapis.com/auth/directory.readonly',
],
microsoft: [
'Calendars.ReadWrite',
'Mail.ReadWrite',
'Contacts.ReadWrite',
'User.Read',
'offline_access'
],
},
},
};
const identitySettings = {
clientId: clientId,
redirectUri: `${window.location.origin}/nylas-auth/scheduler-editor`,
domain: 'https://api.us.nylas.com/v3',
hosted: true,
accessType: 'offline',
};
const identity = new NylasSessions(identitySettings);
const nylasApiRequest = new NylasIdentityRequestWrapper(identity);
return (
<BrowserRouter>
<Routes>
<Route path="/meet" element={
<div>
<a href="/scheduler-editor" className="button">View Scheduler Editor</a>
<NylasScheduling
configurationId={configId}
schedulerApiUrl="https://api.us.nylas.com"
/>
</div>
} />
<Route path="/login" element={
<div>
<LoginComp
clientId={clientId}
redirectUri={`${window.location.origin}/nylas-auth/scheduler-editor`}
config={componentSettings}
identity={identity} popup={false} hosted={false}
/>
</div>
} />
<Route path="/nylas-auth/scheduler-editor" element={
<div>
<NylasSchedulerEditor
schedulerPreviewLink={`${window.location.origin}/meet?config_id={config.id}`}
nylasApiRequest={nylasApiRequest}
defaultSchedulerConfigState={{
selectedConfiguration: {
requires_session_auth: false, // Creates a public Configuration.
}
}}
/>
</div>
} />
</Routes>
</BrowserRouter>
);
}
export default App;
Use Custom Authentication
If you want to use Custom Auth or a different HTTP client library, you can define the CustomIdentityRequestWrapper
. This implements nylasApiRequest
.
⚠️ The Scheduler Editor Component and the CustomIdentityRequestWrapper
require an access token from the same origin. Follow the steps in Create grants with OAuth and an access token and set the redirect_uri
to https://127.0.0.1:3000/scheduler-editor
to generate the access token.
When you have an access token, you can use it in CustomIdentityRequestWrapper
and the Scheduler Editor Component. Make sure that CustomIdentityRequestWrapper
has a currentUser
function that returns the email address associated with the access token.
export class CustomIdentityRequestWrapper {
private accessToken: string;
constructor(accessToken: string) {
// Initialize the class
this.accessToken = accessToken;
}
async request<T = any>(args: any): Promise<T> {
try {
const response = await fetch(`https://api.us.nylas.com/v3/grants/me/${args.path}`, {
method: args.method,
body: JSON.stringify(args.body),
headers: {
...args.headers,
'Authorization': `Bearer ${this.accessToken}`,
'Content-Type': 'application/json',
},
});
// Check if the response is not okay (e.g., 404, 500)
if (!response.ok) {
console.error(`Error: ${response.status} ${response.statusText}`);
return { error: `Error: ${response.status} ${response.statusText}` } as any;
}
// Parse the response
const data = await response.json();
return [data, null] as any;
} catch (error) {
console.error('Fetch error:', error);
return { error: "Error" } as any;
}
}
/**
* This method returns the current user's information.
*/
async currentUser() {
// IMPLEMENT: Get the logged in user's ID token and return the user information.
return {
id: 'idToken.sub',
email: 'j.doe@example.com',
name: 'John Doe',
provider: 'google',
};
}
/**
* This method sets the default authentication arguments to use when authenticating the user.
*/
async setDefaultAuthArgs(authArgs: any) {
// Set the default authentication arguments.
return authArgs;
};
/**
* This method returns the URL to redirect the user to for authentication.
*/
async authenticationUrl(): Promise<string | undefined> {
// IMPLEMENT: Return the URL to redirect the user to for authentication.
return 'https://example.com/auth';
}
}
<html class="h-full bg-white" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Nylas Scheduler Editor Component</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet" />
<script src="https://cdn.tailwindcss.com"></script>
<style type="text/css">
body {
font-family: "Inter", sans-serif;
}
</style>
</head>
<body class="h-full">
<div class="grid h-full place-items-center">
<!-- Add the Nylas Scheduler Editor Component -->
<nylas-scheduler-editor />
</div>
<!-- Configure the Nylas Scheduler Editor Component -->
<script type="module">
import { defineCustomElement } from "https://cdn.jsdelivr.net/npm/@nylas/web-elements@latest/dist/cdn/nylas-scheduler-editor/nylas-scheduler-editor.es.js";
import { CustomIdentityRequestWrapper } from './custom.js';
defineCustomElement();
const schedulerEditor = document.querySelector("nylas-scheduler-editor");
schedulerEditor.schedulerPreviewLink = `${window.location.origin}/?config_id={config.id}`;
const accessToken = '<NYLAS_ACCESS_TOKEN>';
const domain ='https://api.us.nylas.com/v3'
// Create an instance of the CustomIdentityRequestWrapper class defined above.
const nylasApiRequest = new CustomIdentityRequestWrapper(accessToken, domain);
schedulerEditor.nylasApiRequest = nylasApiRequest
schedulerEditor.defaultSchedulerConfigState = {
selectedConfiguration: {
requires_session_auth: false, // Creates a public Configuration.
},
};
</script>
</body>
</html>
import { BrowserRouter, Route, Routes } from "react-router-dom";
import { NylasSchedulerEditor, NylasScheduling } from "@nylas/react";
import { CustomIdentityRequestWrapper } from './custom';
import "./App.css";
function App() {
const accessToken = '<NYLAS_ACCESS_TOKEN>';
const domain ='https://api.us.nylas.com/v3';
// Get the configuration ID from the URL query string.
const urlParams = new URLSearchParams(window.location.search);
const configId = urlParams.get("config_id") || "";
const nylasApiRequest = new CustomIdentityRequestWrapper(accessToken, domain);
return (
<BrowserRouter>
<Routes>
<Route path="/meet" element={
<div>
<a href="/scheduler-editor" className="button">View Scheduler Editor</a>
<NylasScheduling
configurationId={configId}
schedulerApiUrl="https://api.us.nylas.com"
/>
</div>
} />
<Route path="/custom-auth/scheduler-editor" element={
<div>
<NylasSchedulerEditor
schedulerPreviewLink={`${window.location.origin}/meet?config_id={config.id}`}
nylasApiRequest={nylasApiRequest}
defaultSchedulerConfigState={{
selectedConfiguration: {
requires_session_auth: false, // Creates a public Configuration.
}
}}
/>
</div>
} />
</Routes>
</BrowserRouter>
);
}
export default App;
Add Scheduling Page Preview button
You can use the schedulerPreviewLink
property to set a URL for the Preview button in the Scheduling Page manager view. When an organizer clicks the preview button, they can view their Scheduling Page.
<html>
<body>
<nylas-scheduler-editor />
<script type="module">
// ...Scheduler Editor Configuration
schedulerEditor.schedulerPreviewLink = `${window.location.origin}/?config_id={config.id}`
</script>
</body>
</html>
<NylasSchedulerEditor
schedulerPreviewLink={`${window.location.origin}/?config_id={config.id}`}
...
/>
Disable Feedback button
By default, the Scheduler Editor includes a feedback option that lets users provide feedback and report errors to Nylas. If you want to hide the Feedback button in your UI, set enableUserFeedback
to false
.
<html>
<body>
<nylas-scheduler-editor enable-user-feedback="false"/>
<script type="module">
// ...Scheduler Editor configuration
schedulerEditor.schedulerPreviewLink = `${window.location.origin}/?config_id={config.id}`
</script>
</body>
</html>
<NylasSchedulerEditor enableUserFeedback={false}
...
/>
Disable Scheduling Page Manager view
You can set the configurationId
property to point to a specific Scheduler Configuration. This disables the Scheduling Page Manager view, and loads the Edit view for the specified Scheduling Page.
<html>
<body>
<nylas-scheduler-editor />
<script type="module">
// ...Scheduler Editor configuration
schedulerEditor.configurationId = "<SCHEDULER_CONFIGURATION_ID>"
</script>
</body>
</html>
<NylasSchedulerEditor
configurationId="<SCHEDULER_CONFIGURATION_ID>"
...
/>
Arrange and customize sub-components
You can use the composable
mode to customize how Scheduler renders each sub-component in the Scheduler Editor. When you use composable
mode, you add sub-components under the nylas-scheduler-editor
tag, rather than wrapping them with nylas-editor-tabs
.
This example removes the default navigation tabs, and displays the calendar picker and availability picker in a single view.
<html>
<body>
<nylas-scheduler-editor mode="composable">
<!-- Add sub-components -->
<nylas-calendar-picker />
<nylas-availability-picker />
<nylas-scheduler-editor />
<!-- Configure the Scheduler Editor Component -->
<script type="module">
import { defineCustomElement } from "https://cdn.jsdelivr.net/npm/@nylas/web-elements@latest/dist/cdn/nylas-scheduler-editor/nylas-scheduler-editor.es.js";
defineCustomElement();
const schedulerEditor = document.querySelector('nylas-scheduler-editor');
schedulerEditor.nylasSessionsConfig = {
clientId: '<NYLAS_CLIENT_ID>',
redirectUri: `${window.location.origin}/scheduler-editor`,
domain: 'https://api.us.nylas.com/v3',
hosted: true,
accessType: 'offline',
}
</script>
</body>
</html>
<NylasSchedulerEditor
nylasSessionsConfig={{
clientId: "<NYLAS_CLIENT_ID>",
redirectUri: `${window.location.origin}/scheduler-editor`,
domain: "https://api.us.nylas.com/v3",
hosted: true,
accessType: 'offline',
}}
>
// Add sub-components
<NylasCalendarPicker />
<NylasAvailabilityPicker />
</NylasSchedulerEditor>
Customize event handlers
Scheduler's event handlers respond to user actions and control the operations that follow. Each event handler is associated with a specific type of event (for example, formSubmitted
or previewButtonClicked
).
You can use the eventOverrides
property to customize the default event handlers to use specific logic or behaviors. For example, you can add or remove steps in your booking flow, track user interactions for analytics, update the available time slots when the user selects a date, and much more.
This example defines custom logic to perform after the schedulerConfigChanged
event is triggered.
<html>
<body>
<nylas-scheduler-editor />
<!-- Configure the Scheduler Editor Component -->
<script type="module">
import { defineCustomElement } from "https://cdn.jsdelivr.net/npm/@nylas/web-elements@latest/dist/cdn/nylas-scheduler-editor/nylas-scheduler-editor.es.js";
defineCustomElement();
const schedulerEditor = document.querySelector('nylas-scheduler-editor');
schedulerEditor.eventOverrides = {
schedulerConfigChanged: async (event) => {
// Any task that you want to perform
console.log(event)
}
}
</script>
</body>
</html>
<NylasSchedulerEditor
eventOverrides = {{
schedulerConfigChanged: async (event) => {
// Any task that you want to perform.
console.log(event)
}
}}
>
</NylasSchedulerEditor>