[Yandex Cloud documentation](../../index.md) > [Yandex Managed Service for YDB](../index.md) > [Tutorials](index.md) > Building a skill for Alice and a website with authorization

# Building a skill for Alice and a website with authorization based on serverless products

# Building a skill for Alice and a website with authorization


In this tutorial, you will build a [skill for Alice](https://yandex.ru/dev/dialogs/alice/doc/ru/about) and deploy a web app to create, read, and edit to-do lists using Alice, as well as share such lists with other website users.

The project's data is stored in a [Yandex Object Storage](../../storage/index.md) bucket and [Yandex Managed Service for YDB](../index.md) database. [Yandex Cloud Functions](../../functions/index.md) process requests; [Yandex API Gateway](../../api-gateway/index.md) enables service interaction.



To deploy a project:

1. [Get your cloud ready](#before-begin).
1. [Set up your environment](#prepare).
1. [Create resources](#create-resources).
1. [Set the project variables](#set-variables).
1. [Deploy the project](#deploy).
1. [Register your skill for Alice](#register-skill).
1. [Test the skill](#test-skill).

If you no longer need the resources you created, [delete them](#clear-out).


## Get your cloud ready {#before-begin}

Sign up for Yandex Cloud and create a [billing account](../../billing/concepts/billing-account.md):
1. Navigate to the [management console](https://console.yandex.cloud) and log in to Yandex Cloud or create a new account.
1. On the **[Yandex Cloud Billing](https://center.yandex.cloud/billing/accounts)** page, make sure you have a billing account linked and it has the `ACTIVE` or `TRIAL_ACTIVE` [status](../../billing/concepts/billing-account-statuses.md). If you do not have a billing account, [create one](../../billing/quickstart/index.md) and [link](../../billing/operations/pin-cloud.md) a cloud to it.

If you have an active billing account, you can create or select a [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) for your infrastructure on the [cloud page](https://console.yandex.cloud/cloud).

[Learn more about clouds and folders here](../../resource-manager/concepts/resources-hierarchy.md).



### Required paid resources {#paid-resources}

The infrastructure support cost includes:

* Fee for the number of function calls, computing resources allocated for the function, and outgoing traffic (see [Yandex Cloud Functions pricing](../../functions/pricing.md)).
* Fee for YDB operations and data storage (see [Yandex Managed Service for YDB pricing](../pricing/serverless.md)).
* Fee for storing data in a bucket (see [Yandex Object Storage pricing](../../storage/pricing.md)).
* Fee for the number of requests to the API gateway and outgoing traffic (see [Yandex API Gateway pricing](../../api-gateway/pricing.md)).
* Fee for logging operations and data storage in a log group (see [Yandex Cloud Logging pricing](../../logging/pricing.md)).



## Set up your environment {#prepare}

{% list tabs group=operating_system %}

- Windows {#windows}

  1. [Install Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install) to use Linux.
  1. Run WSL (Ubuntu by default).
  1. Set up the environment as described in this guide for Linux.

- Linux {#linux}

  {% note info %}

  If you are using a distribution other than Ubuntu, install the specified software using your package manager.

  {% endnote %}

  1. Clone the [yc-serverless-alice-shareable-todolist](https://github.com/yandex-cloud-examples/yc-serverless-alice-shareable-todolist) repository:

     ```bash
     git clone https://github.com/yandex-cloud-examples/yc-serverless-alice-shareable-todolist.git
     ```

  1. Install and configure the following:

     * [Yandex Cloud CLI](../../cli/quickstart.md)
     * [YDB CLI](https://ydb.tech/docs/en/reference/ydb-cli/install)
     * [Bash](http://www.gnu.org/software/bash/)
     * [AWS CLI](../../storage/tools/aws-cli.md)
     * [jq](https://stedolan.github.io/jq/download/)
     * [Node.js](https://nodejs.org/en/download/package-manager/)
     * [npm](https://en.wikipedia.org/wiki/Npm)
     * [Terraform](../../tutorials/infrastructure-management/terraform-quickstart.md)
     * [Go](https://go.dev/doc/install)

  1. Optionally, to finalize the project, additionally install:

     * [go-swagger](https://goswagger.io/go-swagger/install/)
     * [api-spec-converter](https://www.npmjs.com/package/api-spec-converter)

{% endlist %}


## Create resources {#create-resources}

### Create a bucket {#create-bucket}

Create a [bucket](../../storage/concepts/bucket.md) to store static data:

{% list tabs group=instructions %}

- Management console {#console}

  1. Go to the Yandex Cloud [management console](https://console.yandex.cloud) and select the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) where you will perform the operations.
  1. On the folder page, click ![plus](../../_assets/console-icons/plus.svg) **Create resource** and select **Bucket**.
  1. In the ** Name** field, enter a name for the [bucket](../../storage/concepts/bucket.md) consistent with the [naming conventions](../../storage/concepts/bucket.md#naming).
  1. In the **Read objects**, **Read object list**, and **Read settings** fields, select `With authorization`.
  1. Specify the maximum size of the bucket in GB.
  1. Click **Create bucket**.

{% endlist %}


### Create an API gateway {#create-api-gw}

Create an [API gateway](../../api-gateway/concepts/index.md) for interaction between services:

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder you are using to complete this tutorial.
  1. Navigate to **API Gateway**.
  1. Click **Create API gateway**.
  1. In the **Name** field, enter `gate-1`.
  1. Click **Create**.
  1. Wait for the API gateway status to change to `Active`.
  1. Select the created API gateway.
  1. Find the **ID** and **Default domain** fields and save their values. You will need them to configure the skill.

{% endlist %}


### Create a database {#db-create}

Create a YDB database in [Serverless mode](../concepts/serverless-and-dedicated.md#serverless):

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you created the bucket.
  1. Navigate to **Managed Service for&nbsp;YDB**.
  1. Click **Create a database**.
  1. Specify a **Name** for the database. The naming requirements are as follows:

      * Length: between 3 and 63 characters.
      * It can only contain lowercase Latin letters, numbers, and hyphens.
      * It must start with a letter and cannot end with a hyphen.

  1. Under **Database type**, select `Serverless`.
  1. Click **Create a database**.
  1. Wait for the database status to change to `Running`.
  1. Select the created database.
  1. Under **Connection**, find the **Endpoint** field and save its value. You will need it when creating functions.

{% endlist %}


### Create an app {#create-app}

[Create](https://yandex.ru/dev/id/doc/ru/register-client) an application in Yandex.OAuth:

{% list tabs %}

- Yandex.OAuth interface

  1. Go to the [Yandex OAuth website](https://oauth.yandex.com) and log in.
  1. Click **Create app**.
  1. Specify an appropriate app name and upload an icon.
  1. Under **Target platforms**, select `Web services` and click **Save and continue**.
  1. Under **Application platforms**, specify the following URIs in the **Redirect URI** field:

      * `https://social.yandex.net/broker/redirect`
      * `<API_gateway_service_domain>/receive-token`

      Leave the **Suggest Hostname** field blank.

  1. Click **Save and continue**.
  1. Under **Data access**, select `Access to user picture` and click **Save and continue**.
  1. Under **Email for communication**, specify your email address and click **Save and continue**.
  1. Check the data and click **Everything is correct, create app**.

  You can read more about the Yandex.OAuth features in [this guide](https://yandex.com/dev/oauth/doc/dg/tasks/register-client.html).

{% endlist %}

## Set the project variables {#set-variables}

Configure the project using the values you got when creating your resources.

### Create a file with secrets {#set-variables-secure-config}

Create a file named `secure-config.json` with secrets:

{% list tabs group=programming_language %}

- Bash {#bash}

  1. To create a file from the `secure-config-template.json` template, navigate to the `yc-serverless-alice-shareable-todolist` directory with project files and run this command:

      ```bash
      cp secure-config-template.json secure-config.json
      ```

  1. Open the `secure-config.json` file in `nano`:

      ```bash
      nano secure-config.json
      ```

  1. Substitute these variable values into the file:

      * `oauth_secret`: Password of the app (**Client Secret**) registered in [Yandex OAuth](https://oauth.yandex.com/).
      * `hash`: Base64-encoded random 64-byte string, e.g., `qrJagO5NVwOj0FeTmgYSwUN+XXkiQJMWifvrklF53wT55q80Xk8vmEB3kxhtpDnA1WDC893Z9Bh6QcqK********`. You can generate a random value in your terminal using `openssl rand -base64 64 | tr -d '\n'`.
      * `block`: Base64-encoded random 32-byte string, e.g., `uwk0duFgn2nYyfu2VzJe+MnWKWQrfKaiZijI********`. You can generate a random value in your terminal using `openssl rand -base64 32 | tr -d '\n'`.

      You can generate random values at [generate.plus](https://generate.plus/en/base64).

{% endlist %}


### Create a configuration file {#set-variables-variables}

Create a file named `variables.json` with the project deployment configuration:

{% list tabs group=programming_language %}

- Bash {#bash}

  1. To create a file from the `variables-template.json` template, navigate to the project files directory and run this command:

      ```bash
      cp variables-template.json variables.json
      ```

  1. Open the `variables.json` file in `nano`:

      ```bash
      nano variables.json
      ```

  1. Substitute these variable values into the file:

      * `folder-id`: Cloud [folder ID](../../resource-manager/operations/folder/get-id.md).
      * `domain`: `gate-1` API gateway service domain without `https://`, e.g., `d5dbo25bol8n********.apigw.yandexcloud.net`.
      * `oauth-client-id`: **ClientID** field value of the app registered in [Yandex.OAuth](https://oauth.yandex.com).
      * `database`: Database location, the second part of the previously saved **Endpoint** field value (following `/?database=`), e.g., `/ru-central1/r1gra875baom********/g5n22e7ejfr1********`.
      * `database-endpoint`: First part of the previously saved **Endpoint** field value (following `grpcs://` and preceding `/?database=`), e.g., `ydb.serverless.yandexcloud.net:2135`.
      * `yc-profile`: Yandex Cloud CLI [profile name](../../cli/operations/profile/profile-list.md).
      * `secure-config-path`: Path to the `secure-config.json` [secrets file](#set-variables-secure-config).
      * `storage-bucket`: Name of the bucket you created for storing static data.
      * `gateway-id`: `gate-1` API gateway ID.

{% endlist %}

## Deploy the project {#deploy}

Transfer the project files to Yandex Cloud and update the configuration.


### Apply a data schema {#deploy-schema}

To create tables in the database, navigate to the project files directory and run this command:

{% list tabs group=programming_language %}

- Bash {#bash}

  ```bash
  ./upload_ydb_schema.sh
  ```

{% endlist %}


### Upload the backend code to Cloud Functions {#deploy-backend}

Use Terraform to automate your operations. Before you start, [initialize it](../../tutorials/infrastructure-management/terraform-quickstart.md#configure-provider).

{% list tabs group=instructions %}

- Terraform {#tf}

  With [Terraform](https://www.terraform.io/), you can quickly create a cloud infrastructure in Yandex Cloud and manage it using configuration files. These files store the infrastructure description written in HashiCorp Configuration Language (HCL). If you change the configuration files, Terraform automatically detects which part of your configuration is already deployed, and what should be added or removed.
  
  Terraform is distributed under the [Business Source License](https://github.com/hashicorp/terraform/blob/main/LICENSE). The [Yandex Cloud provider for Terraform](https://github.com/yandex-cloud/terraform-provider-yandex) is distributed under the [MPL-2.0](https://www.mozilla.org/en-US/MPL/2.0/) license.
  
  For more information about the provider resources, see the guides on the [Terraform](https://www.terraform.io/docs/providers/yandex/index.html) website or [its mirror](../../terraform/index.md).

  If you do not have Terraform yet, [install it and configure the Yandex Cloud provider](../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform).
  
  
  To manage infrastructure using Terraform under a service account or user accounts (a Yandex account, a federated account, or a local user), [authenticate](../../terraform/authentication.md) using the appropriate method.

  1. Run the following command in the directory with the `app.tf` configuration file:

      ```bash
      terraform init
      ```

      {% note info %}

      If you encounter a `permission denied` error during Terraform provider initialization, run the `sudo chown $(whoami) ~/yc-serverless-alice-shareable-todolist` command to edit current user's access permissions for the project directory.

      {% endnote %}

  1. Following successful initialization, create resources and provide the IAM token for Yandex Cloud authentication:

      ```bash
      terraform apply -var-file ./variables.json -var yc-token="$(yc iam create-token)"
      ```

      As a result, Terraform will automatically create or update the required resources.

{% endlist %}


### Upload the frontend code to Object Storage {#deploy-frontend}

To deploy the frontend web app, compile the static files and upload them to Object Storage.

{% list tabs group=programming_language %}

- Bash {#bash}

  1. Before compiling static files, make sure you have **Node.js** and **npm** [installed](#prepare).
  1. Navigate to the `yc-serverless-alice-shareable-todolist/frontend` directory and run the following command:

      ```bash
      npm run build
      ```

      If during the compilation you get this error:

      * `ERR_OSSL_EVP_UNSUPPORTED`, create the `NODE_OPTIONS` variable:

         ```bash
         export NODE_OPTIONS=--openssl-legacy-provider
         ```
      * `npm ERR! Could not resolve dependency`, run this command:

          ```bash
          npm install --legacy-peer-deps && npm install --force
          ```

      Result:

      ```text
      > todolist@0.1.0 build
      > react-scripts build

      Creating an optimized production build...
      Compiled successfully.

      File sizes after gzip:

        75.93 KB  build/static/js/2.84be0fca.chunk.js
        23.26 KB  build/static/css/2.ef9168ec.chunk.css
        2.63 KB   build/static/js/main.d9e069c9.chunk.js
        776 B     build/static/js/runtime-main.676997b0.js
        402 B     build/static/css/main.e5cbab88.chunk.css

      The project was built assuming it is hosted at /.
      You can control this with the homepage field in your package.json.

      The build folder is ready to be deployed.
      You may serve it with a static server:

        npm install -g serve
        serve -s build
      ```

  1. To upload the files to Object Storage, run this command:

      ```bash
      cd ../
      ./upload_static.sh
      ```

      Result:

      ```text
      ./upload_static.sh
      upload: frontend/build/robots.txt to s3://frontent-statics/robots.txt
      upload: frontend/build/manifest.json to s3://frontent-statics/manifest.json
      upload: frontend/build/static/css/main.e5cbab88.chunk.css.map to s3://frontent-statics/static/css/main.e5cbab88.chunk.css.map
      upload: frontend/build/index.html to s3://frontent-statics/index.html
      upload: frontend/build/asset-manifest.json to s3://frontent-statics/asset-manifest.json
      upload: frontend/build/static/js/2.84be0fca.chunk.js.LICENSE.txt to s3://frontent-statics/static/js/2.84be0fca.chunk.js.LICENSE.txt
      upload: frontend/build/static/css/main.e5cbab88.chunk.css to s3://frontent-statics/static/css/main.e5cbab88.chunk.css
      upload: frontend/build/static/js/main.d9e069c9.chunk.js to s3://frontent-statics/static/js/main.d9e069c9.chunk.js
      upload: frontend/build/static/js/2.84be0fca.chunk.js to s3://frontent-statics/static/js/2.84be0fca.chunk.js
      upload: frontend/build/static/js/runtime-main.676997b0.js to s3://frontent-statics/static/js/runtime-main.676997b0.js
      upload: frontend/build/static/js/runtime-main.676997b0.js.map to s3://frontent-statics/static/js/runtime-main.676997b0.js.map
      upload: frontend/build/static/js/main.d9e069c9.chunk.js.map to s3://frontent-statics/static/js/main.d9e069c9.chunk.js.map
      upload: frontend/build/static/css/2.ef9168ec.chunk.css to s3://frontent-statics/static/css/2.ef9168ec.chunk.css
      upload: frontend/build/static/css/2.ef9168ec.chunk.css.map to s3://frontent-statics/static/css/2.ef9168ec.chunk.css.map
      upload: frontend/build/static/js/2.84be0fca.chunk.js.map to s3://frontent-statics/static/js/2.84be0fca.chunk.js.map
      ```

{% endlist %}


### Update the API gateway configuration {#deploy-gateway}

To upload the current specification to API Gateway, run this command:

{% list tabs group=programming_language %}

- Bash {#bash}

  ```bash
  ./update_gateway.sh
  ```

  Result:

  ```text
  done (2s)
  id: d5dsj4st2g81********
  folder_id: b1g86q4m5vej********
  created_at: "2024-10-22T16:01:54.777Z"
  name: gate-1
  status: ACTIVE
  domain: d5dm1lba80md********.i9******.apigw.yandexcloud.net
  connectivity:
    network_id: enp3srbi9u49********
  log_options:
    folder_id: b1g86q4m5vej********
  execution_timeout: 300s
  ```

{% endlist %}


## Register your skill for Alice {#register-skill}

### Create a dialog {#create-dialog}

{% list tabs %}

- Yandex Dialogs console

  1. Go to [Yandex Dialogs](https://dialogs.yandex.ru/) and log in to the console.
  1. Click **Create dialog** and select the `Skill` type.
  1. In the **Skill name** field, specify `To-do lists`.
  1. Under **Backend**, enable **Yandex Cloud function** and from the list, select the `todolist-alice` function you created earlier in Cloud Functions.
  1. Enable **Use data storage for the skill**.
  1. Fill in the required fields under **Publication in folder**. Configure the other settings as needed. For example, you can specify various word forms to trigger the skill, select a voice, or set access type.
  1. Click **Save** at the bottom of the page.

  Learn more in [this Yandex Dialogs guide](https://yandex.ru/dev/dialogs/alice/doc/publish.html).

{% endlist %}


### Configure authorization on the Alice page {#configure-authorization}

{% list tabs %}

- Yandex Dialogs console

  1. Go to the **Account linking** tab.
  1. Enter the following:

      * **Application ID**: `ClientID` field value of the app registered in [Yandex.OAuth](https://oauth.yandex.com).
      * **Application secret**: `Client secret` field value of the app registered in [Yandex.OAuth](https://oauth.yandex.com).
      * **Authorization URL**: `https://oauth.yandex.com/authorize`.
      * **Get token URL**: `https://oauth.yandex.com/token`.
      * **Refresh token URL**: `https://oauth.yandex.com/token`.

  1. Click **Save**.

  To learn more about OAuth 2.0, see [RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749).

{% endlist %}


### Add intents {#add-intents}

{% list tabs %}

- Yandex Dialogs console

  1. Go to the **Settings** tab.
  1. Go to the **Intents** tab and click **Create**.
  1. Add intents for every action possible in the dialog. The intents you make reside in the project's `yc-serverless-alice-shareable-todolist/intents` folder.
  1. Enter the following:

      * **Name**: Any name to display in the interface.
      * **ID**: Intent ID matching the file name in the `intents` folder.
      * **Grammar**: Grammar text matching the file contents in the `intents` folder.

  1. Click **Save**.
  1. To complete creating the dialog, click **Submit for moderation** on the right side of the page.

  To learn more about intents, see [this guide on Alice's skills](https://yandex.ru/dev/dialogs/alice/doc/nlu-docpage/).

{% endlist %}


## Test the skill {#test-skill}

To debug the skill, use the **Testing** tab in the [Yandex Dialogs](https://dialogs.yandex.ru/developer) console or one of the [devices](https://yandex.ru/dev/dialogs/alice/doc/surfaces.html) you selected when designing the skill.

{% list tabs %}

- In the Yandex Dialogs console:

  Navigate to the **Testing** tab. You will see a chat with Alice on the left and an interaction log in JSON format on the right.

  Dialog example:

  ```text
  Let me help you with your lists!

    Hi Alice, create a Groceries list.

  Done, I created a Groceries list.

    Add milk to Groceries.

  Done, I added milk to Groceries.

    Add bread.

  Which list would you like me to add bread to?

    Groceries.

  Done, I added bread to Groceries.

    Add eggs.

  Which list would you like me to add eggs to?

    Groceries.

  Done, I added eggs to Groceries.

    Alice, tell me what's on the Groceries list.

  Groceries:
  1. Milk
  2. Bread
  3. Eggs
  ```

- Using a device

  To start a dialog, use any device or service supported by [Alice](https://yandex.ru/alice).

- On the website

  In your browser, follow the URL in the **Default domain** field of your `gate-1` API gateway and log in. The **My lists** page will open. In any of the lists, you can add or remove items and grant other users access to the list.

{% endlist %}


## How to delete the resources you created {#clear-out}

To stop paying for the resources you created:

* [Delete](../../storage/operations/buckets/delete.md) the bucket.
* [Delete](../operations/manage-databases.md#delete-db) the database.
* [Delete](../../functions/operations/function/function-delete.md) the functions.
* [Delete](../../api-gateway/operations/api-gw-delete.md) the API gateway.
* [Delete](../../logging/operations/delete-group.md) the log group.