# Manage project configuration You can use project configuration to store project-level variables, such as feature flags, API credentials, and access tokens. Project configuration in commercetools Frontend is similar to storing your credentials in a `.env` file, except you store the credentials using the Studio and access them from the extension handler through the `context` parameter. ## Store project configuration in the Studio To store project configuration in the Studio, follow these steps: 1. [Add project configuration fields to the project schema](/frontend-development/api-hub-configuration.md#add-project-configuration-fields-to-the-project-schema). 2. [Enter the project configuration values in the project settings](/frontend-development/api-hub-configuration.md#enter-project-configuration-values-in-project-settings). ### Add project configuration fields to the project schema To add project configuration fields, follow these steps: 1. From the Studio home page or from the left menu, go to **Developer > Other schemas**. 2. Click **Project schema**. The **Project schema** pane opens. 3. Click **Edit schema**. The [schema builder](/frontend-studio/using-the-schema-builder.md) opens. 4. Extend the project schema with the appropriate field types; these field types will be displayed automatically if you are using the visual editor mode. For example, a `boolean` field might be suitable for a feature flag, whereas `encrypted` fields should be used for secret credentials, such as an API key. For more information about schema fields, see [Schemas](/frontend-development/schemas.md). 5. Click **Publish changes**. For demonstration purposes, the following schema adds the `API_KEY` and `APP_ID` fields in the `Project credentials` section of the project schema. By extending the project schema with these fields, a **Project credentials** section with the **Enter API key** and **Enter APP ID** fields is displayed in the **Project** area of the Studio. ```json title="Example project schema for project credentials" { "schema": [ { "name": "Project credentials", "fields": [ { "label": "Enter API key", "field": "API_KEY", "type": "encrypted", "required": true }, { "label": "Enter APP ID", "field": "APP_ID", "type": "string", "required": true } ] } ] } ``` The project schema fields must be unique throughout the schema because they are flattened in the API hub. Duplicate keys will be lost causing bugs. Encryption is a compute heavy task. Use `encrypted` fields only for secret credentials. Overusing `encrypted` fields can slow down your application. ### Enter project configuration values in project settings You must enter the project configuration values for each Studio [environment](/frontend-studio/using-environments-in-the-studio.md), as the values are unique to an environment. To enter the project configuration values, follow these steps: 1. From the Studio home page or from the left menu, go to **Project**. 2. Enter the configuration values in the fields of the relevant section. ![The Project settings page with the Project Credentials section where the Enter API Key and Enter APP ID fields are filled in with values](https://docs.commercetools.com/frontend-development/images/enter-project-config-values-in-the-studio.png) 3. Click **Save**. The values of `encrypted` fields are hidden after they are saved. To update the values, click **X** in the text box and then enter the new value. ## Read project configuration When executing an extension, the API hub reads the project configuration values from the Studio, decrypts the `encrypted` fields, and passes them to the extension handler `context` parameter inside the `context.frontasticContext.projectConfiguration` key. ### Read project configuration in an extension handlers You can access the specified variables through the `context` property that is passed as the second argument to your extension handlers. The following example shows how to read the `API_KEY` configuration value in extensions. ```typescript title="Use project configuration values in extensions in the backend/index.ts" export default { 'dynamic-page-handler': async ( request: Request, context: DynamicPageContext ): Promise => { const apiKey = context.frontasticContext.projectConfiguration['API_KEY']; // Fetch data for dynamic pages. }, 'data-sources': { 'amazing-data-source': async ( config: DataSourceConfiguration, context: DataSourceContext ): Promise => { const apiKey = context.frontasticContext.projectConfiguration['API_KEY']; // Fetch data with the API key. }, }, actions: { commerce: { getStores: async ( request: Request, context: ActionContext ): Promise => { const apiKey = context.frontasticContext.projectConfiguration['API_KEY']; // Fetch stores with the API key. }, }, }, }; ``` ### Override the project configuration during development The `projectConfiguration` is shared across all developers working on the same project. However, sometimes you need to use a different value for some credentials locally without changing the value in the Studio. To override the project configuration during development, you can create a wrapper function in your code to read the `projectConfiguration` and conditionally return the credential based on the execution environment. In the following example, the `getFromProjectConfig` function checks if the required credential exists in the `projectConfigurationOverrides` local object and returns it from there instead of from `context`. ```ts title="Override project configuration during development" import { Context } from '@frontastic/extension-types'; /** * Use this object to locally override the values that would be * fetched from the projectConfiguration by default. * It only works in development. */ const projectConfigurationOverrides = { API_KEY: 'myCustomKey', }; const isDevEnv = (context: Context) => { return context.environment === 'development' || context.environment === 'dev'; }; export const getFromProjectConfig = (key: string, context: Context) => { if (isDevEnv(context) && projectConfigurationOverrides[key]) { return projectConfigurationOverrides[key]; } return context.projectConfiguration[key]; }; ``` ### Share project configuration with Frontend components Sometimes you might need to use project configuration values in your Frontend components. For example, some client-side SDKs like Adyen need a client ID to work. The API hub doesn't expose the values directly to the frontend, but you can implement a data source to selectively expose the values you need in a Frontend component. To avoid security issues, you must expose configuration values as little as possible. A good practice is creating separate data sources for each secret needed on the frontend. The following example shows how to expose the `API_KEY` secret from the project configuration to a Frontend component. 1. Create a [data source](/frontend-development/developing-a-data-source-extension.md) to read the value from `context.frontasticContext.projectConfiguration` and return the value as the `dataSourcePayload`. ```typescript highlightLines="10" title="Read and return project configuration value from a data source" export default { // ... other extensions 'data-sources': { 'secrets/api-key': async ( config: DataSourceConfiguration, context: DataSourceContext ) => { return { dataSourcePayload: context.frontasticContext.projectConfiguration.API_KEY, }; }, }, // ... other extensions }; ``` 2. [Upload the following data source schema to the Studio](/frontend-development/developing-a-data-source-extension.md). ```json title="secrets/api-key data source schema" { "customDataSourceType": "secrets/api-key", "name": "Expose API_KEY", "category": "Secrets", "icon": "key", "schema": [] } ``` 3. Specify the data source inside the schema of the Frontend component that requires the API key. ```json highlightLines="13" title="Frontend component schema with secrets/api-key data source" { "tasticType": "example/share-api-key", "name": "Example share API key", "icon": "money", "category": "payment", "schema": [ { "name": "Secrets", "fields": [ { "label": "API_KEY", "field": "apiKey", "type": "dataSource", "dataSourceType": "secrets/api-key", "required": true } ] } ] } ``` 4. Read `apiKey` from the data source payload in the Frontend component. ```typescript title="Use the apiKey value in the Frontend component" function ExamplePayment({ data }) { return (

I got this secret from data source {data?.apiKey?.dataSource}

); } export default ExamplePayment; ``` ## Related pages - [Area overview page with navigation](/frontend-development.md) - [Previous page: CLI](/frontend-development/cli.md) - [Next page: Work with links](/frontend-development/working-with-links.md) - [Search documentation and API specs](/search.md)