# Using the Scheduling component

Source: https://developer.nylas.com/docs/v3/scheduler/using-scheduling-component/

You can use the Nylas Scheduling component to embed a complete scheduling interface directly in your project.

<img
  src="/_images/scheduler/scheduling.png"
  alt="The Scheduling component displaying the calendar and time picker."
  style="height:600px"
/>

This page covers how to set it up using a [Configuration ID](#embed-scheduling-component-with-configuration-id) or a [slug](#embed-scheduling-component-with-slug) and [how to customize it](#customize-scheduling-component).

## How the Scheduling component works

Nylas offers the Scheduling component as a pre-built, extensible web- (HTML/Vanilla JS) and React-based UI component. After you add it to your project, guests can use the Scheduling Page to book meetings.

The Scheduling Component includes...

- **Custom event handlers** that let you define specific logic or behavior for user actions.
- **Composable components** that let you customize how each element is arranged and rendered in the UI.
- **Custom UI stylings** that support [CSS shadow parts](https://www.w3.org/TR/css-shadow-parts-1/) for a higher level of customization.

The component supports two configuration modes: `app` and `composable`. By default, it's set to `app` mode. In this mode, the Scheduling component renders all elements it contains, meaning you can embed the pre-built component in your project with minimal configuration. `composable` mode allows you to customize how the Scheduling component arranges and renders each element in the UI. In this mode, you can embed elements as standalone components.

For more information, see the [Scheduler UI components references](/docs/reference/ui/).

## Before you begin

Before you can use the Scheduling component, you need to...

- [Create a scheduling Configuration](/docs/v3/scheduler/#create-a-configuration).
- Install the latest `@nylas/react` package.

  ```bash [install-npm]
  npm install @nylas/react
  ```

  ```bash [install-yarn]
  yarn add @nylas/react
  ```

  ```bash [install-pnpm]
  pnpm add @nylas/react
  ```

## Embed Scheduling component with Configuration ID

The simplest way to embed the Scheduling component is by passing a Configuration ID.

```html {11} [config-HTML/Vanilla JS]
<!DOCTYPE html>
<html>
  <head>
    <title>Scheduler Integration</title>
    <script src="https://cdn.jsdelivr.net/npm/@nylas/react@latest/dist/cdn/nylas-scheduling/nylas-scheduling.es.js"></script>
  </head>
  <body>
    <div id="scheduler-container">
      <h1>Book a Meeting</h1>
      <nylas-scheduling
        configuration-id="<CONFIGURATION_ID>"
        default-language="en"
      >
      </nylas-scheduling>
    </div>
  </body>
</html>
```

```tsx {8} [config-React]


function BookingPage() {
  return (
    <div className="booking-container">
      <h1>Book a Meeting</h1>
      <NylasScheduling
        configurationId="<CONFIGURATION_ID>"
        defaultLanguage="en"
      />
    </div>
  );
}
```

When you use a Configuration ID, the Scheduling component gains direct access to the Configuration, loads faster, and is more secure than passing a slug. We strongly recommend using this approach.

## Embed Scheduling component with slug

Use a slug in the Scheduling component when you want to reference a public Configuration by its URL identifier.

```html {11-12} [slug-HTML/Vanilla JS]
<!DOCTYPE html>
<html>
  <head>
    <title>Scheduler Integration</title>
    <script src="https://cdn.jsdelivr.net/npm/@nylas/react@latest/dist/cdn/nylas-scheduling/nylas-scheduling.es.js"></script>
  </head>
  <body>
    <div id="scheduler-container">
      <h1>Book a Meeting</h1>
      <nylas-scheduling
        client-id="<NYLAS_CLIENT_ID>"
        slug="<SLUG>"
        default-language="en"
      >
      </nylas-scheduling>
    </div>
  </body>
</html>
```

```tsx {8-9} [slug-React]


function BookingPage() {
  return (
    <div className="booking-container">
      <h1>Book a Meeting</h1>
      <NylasScheduling
        clientId="<NYLAS_CLIENT_ID>"
        slug="<SLUG>"
        defaultLanguage="en"
      />
    </div>
  );
}
```

When you use a slug, Scheduler presents a human-readable URL that's easy to share. This solution also works with [Nylas-hosted Scheduling Pages](/docs/v3/scheduler/hosted-scheduling-pages/).

## Best practices for Scheduling component

The following sections cover some best practices to keep in mind when adding the Scheduling component to your project.

### Set up error boundaries

We recommend wrapping the Scheduling component in an error boundary when you integrate it. The boundary should be able to catch and handle any unexpected errors.

```tsx
class SchedulerErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  render() {
    if (this.state.hasError) {
      return <div>Something went wrong with the scheduler.</div>;
    }

    return this.props.children;
  }
}

...
```

### Add loading state indicators

We recommend adding custom loading indicators to display while the Scheduling component is initializing or completing processes in the background.

```tsx
function SchedulerWithLoading() {
  const [isReady, setIsReady] = useState(false);

  return (
    <div>
      {!isReady && <div>Loading...</div>}

      <NylasScheduling
        configurationId="<CONFIGURATION_ID>"
        onLoad={() => setIsReady(true)}
      />
    </div>
  );
}
```

### Prepare to clean up events

Your project should be prepared to clean up event listeners when the Scheduling component unmounts.

```tsx
useEffect(() => {
  const handleBooking = (event) => {
    // Handle booking
    ...
  };

  // Add event listener
  document.addEventListener('nylas-booking-confirmed', handleBooking);

  // Cleanup
  return () => {
    document.removeEventListener('nylas-booking-confirmed', handleBooking);
  };
}, []);
```

## Customize Scheduling component

The Scheduling component includes many customization options — the following sections cover a few. For more options, see the [`NylasScheduling` component references](/docs/reference/ui/scheduling/).

### Set default language and time zone

You can set both the default language and time zone for your users by passing the `defaultLanguage` and `defaultTimezone` properties, respectively.

```tsx


function BookingPage() {
  return (
    <div className="booking-container">
      <h1>Book a Meeting</h1>
      <NylasScheduling
        configurationId="<CONFIGURATION_ID>"
        defaultLanguage="es"
        defaultTimezone="America/Mexico_City"
      />
    </div>
  );
}
```

### Create one-time invitation

You can use the Scheduling component to create and display one-time invitations for events. These invitations have a set date and time, and guests can book the event by entering their contact information.

This example configures the default Scheduling Page state (`defaultSchedulerState`) to show the booking form with a pre-selected time. It also disables the Back button, so the user can't go back to the time slot selection page.

```html [createInvite-HTML/Vanilla JS]

<html>
  <body>
    <nylas-scheduling />

    <script type="module">
      import { defineCustomElement } from "https://cdn.jsdelivr.net/npm/@nylas/web-elements@latest/dist/cdn/nylas-scheduling/nylas-scheduling.es.js";

      defineCustomElement();

      const nylasScheduling = document.querySelector("nylas-scheduling");
      nylasScheduling.showBookingForm = true;

      nylasScheduling.selectedTimeslot = {
        start_time: new Date(1739257200 * 1000),
        end_time: new Date(1739259000 * 1000),
      };
    </script>
  </body>
</html>


```

```tsx
<NylasScheduling
  mode="app"
  // Set the Scheduler Configuration ID if using public Configuration (`requires_session_auth=false`).
  configurationId={"<SCHEDULER_CONFIGURATION_ID>"}
  // OR set the Scheduler session ID if using private Configuration (`requires_session_auth=true`).
  // sessionId={"<SCHEDULER_SESSION_ID>"}

  defaultSchedulerState={{
    showBookingForm: true,
    selectedTimeslot: {
      start_time: new Date(1739257200 * 1000),
      end_time: new Date(1739259000 * 1000),
    },
  }}
/>;


```

### Pre-fill the booking form

You can define `bookingInfo` to pre-fill the booking form (for example, to pre-fill the guest's name and email address).

> **Success:** 
> **For hosted Scheduling Pages**, you can [pass query parameters in the URL](/docs/v3/scheduler/hosted-scheduling-pages/#pre-filled-booking-forms) to pre-fill the booking form.

```html [prefill-HTML/Vanilla JS]

<html>
  <body>
    <nylas-scheduling />

    <script type="module">
      import { defineCustomElement } from "https://cdn.jsdelivr.net/npm/@nylas/web-elements@latest/dist/cdn/nylas-scheduling/nylas-scheduling.es.js";

      defineCustomElement();

      const nylasScheduling = document.querySelector("nylas-scheduling");

      nylasScheduling.bookingInfo = {
        primaryParticipant: {
          name: "Leyah Miller",
          email: "leyah@example.com",
        },
        guests: [
          {
            name: "Nyla",
            email: "nyla@example.com",
          },
        ],
        additionalFields: {
          additional_email: {
            value: "nylas@example.com",
            type: "email",
          },
          phone_number: {
            value: "1234567890",
            type: "phone_number",
          },
        },
      };
    </script>
  </body>
</html>


```

```tsx
const bookingInfoData = {
  primaryParticipant: {
    name: 'Leyah Miller',
    email: 'leyah@example.com',
  },
  guests: [{
    name: 'Nyla',
    email: 'nyla@example.com'
  }],
  additionalFields: {
    additional_email: {
      value: 'nylas@example.com',
      type: 'email',
    },
    phone_number: {
      value: '1234567890',
      type: 'phone_number'
    }
};


```

### 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, `bookTimeslot` or `cancelBooking`).

You can use the `eventOverrides` property to customize the default event handlers to use specific logic or behaviors. For example, you can track user interactions for analytics, update the available time slots when the user selects a date, and much more.

The following example overrides the default `timeslotConfirmed` handler.

```html [eventHandlers-HTML/Vanilla JS]
<nylas-scheduling id="scheduler" eventOverrides='{"timeslotConfirmed": timeslotConfirmedHandler}'>
</nylas-scheduling>

<script>
  document.addEventListener('DOMContentLoaded', function() {
    const schedulerElement = document.getElementById('scheduler');

    function timeslotConfirmedHandler(event, nylasConnector) {
      console.log("Timeslot Confirmed event fired!");

      // Custom logic for booking the timeslot using the connector.
      // Assuming 'bookTimeslot' is a method available in the connector.
      const timeslot = event.detail;

      const bookingData = {
        primaryParticipant: {name: "John Smith", email: "john.smith@example.com"}
        timezone: "America/New_York",
        guests: [{name: "Jane Doe", email: "jane.doe@example.com"}],
        additionalFields: {"key": {value: "", type: ""}},
        timeslot
      };

      nylasConnector.scheduler.bookTimeslot(bookingData).then(bookingResponse => {
        console.log("Booking completed:", bookingResponse);
      }).catch(error => {
        console.error("Booking failed:", error);
      });

      // Send data to analytics service.
      sendToAnalyticsService(event.detail);
    }
  });
<script/>
```

```tsx
<NylasScheduling
  eventOverrides={
    timeslotConfirmed: async (event, connector) => {
      const timeslot = event.detail;

      const bookingData = {
        primaryParticipant: {name: "John Smith", email: "john.smith@example.com"}
        timezone: "America/New_York",
        guests: [{name: "Jane Doe", email: "jane.doe@example.com"}],
        additionalFields: {"key": {value: "", type: ""}},
        timeslot
      };

      connector.scheduler.bookTimeslot(bookingData).then(bookingResponse => {
        console.log("Booking completed:", bookingResponse);
      }).catch(error => {
        console.error("Booking failed:", error);
      });

    ...
    }
  }
/>
```

The `NylasSchedulerConnectorInterface` object allows custom event handlers to interact with the following Nylas Scheduler API functions:

- `bookTimeslot`
- `cancelBooking`
- `getAvailability`
- `rescheduleBooking`

Custom event handlers return a `Promise` for asynchronous operations. This is useful when you want to fetch data, update UI Components, or perform any tasks that rely on the outcome of other operations.

### Set up custom error handling

The Scheduling component includes built-in error handling methods, but you can implement custom error handling to suit your project.

```tsx


function BookingPage() {
  return (
    <div className="booking-container">
      <h1>Book a Meeting</h1>
      <NylasScheduling
        configurationId="<CONFIGURATION_ID>"
        eventOverrides={{
          // Handle validation errors
          validateTimeslotError: async (event, connector) => {
            const error = event.detail;

            // Show custom error message
            console.error("Timeslot validation error:", error);
          },

          // Handle booking form errors
          bookingFormError: async (event, connector) => {
            const error = event.detail;
            console.error("Booking form error:", error);
          },
        }}
      />
    </div>
  );
}
```

### Customize styling

You can use the `themeConfig` property to customize the appearance of the Scheduler component. This lets you update the colors, fonts, and borders.

```tsx


function BookingPage() {
  return (
    <div className="booking-container">
      <h1>Book a Meeting</h1>
      <NylasScheduling
        configurationId="<CONFIGURATION_ID>"
        themeConfig={{
          "--nylas-primary": "#007bff",
          "--nylas-base-0": "#ffffff",
          "--nylas-base-100": "#f8f9fa",
          "--nylas-font-family": "Inter, sans-serif",
        }}
      />
    </div>
  );
}
```

### Arrange and customize elements

You can use the [`composable` mode](#how-the-scheduling-component-works) to customize how the Scheduling component renders each element in the Scheduling Page.

This example creates a date selection page with a panel on either side of the component. The left panel contains the date picker and locale switch elements, and the right panel displays the time slot picker.

```html [arrange-HTML/Vanilla JS]
<nylas-scheduling mode="composable">
  <div class="select-date-page">
    <div class="left-panel">
      <nylas-date-picker></nylas-date-picker>

      <nylas-locale-switch></nylas-locale-switch>
    </div>
    <div class="right-panel">
      <nylas-timeslot-picker></nylas-timeslot-picker>
    </div>
  </div>
</nylas-scheduling>
```

```tsx

  <div class="select-date-page">
    <div class="left-panel">
      <nylas-date-picker></nylas-date-picker>

      <nylas-locale-switch></nylas-locale-switch>
    </div>
    <div class="right-panel">
      <nylas-timeslot-picker></nylas-timeslot-picker>
    </div>
  </div>

```