API hub configuration
In this guide, you'll learn to set environment variables in the API hub and access them in your extension handlers.
Configuring variables in API hub
You can provide your API hub extensions with credentials to connect to your backend services. To do so, you need to edit the project.yml
file in a directory you're not usually meant to touch: <customer>_<project>/config/project.yml
. In this file, you can edit the section configuration
and store arbitrary YAML content, which is then available to the FrontasticContext
in each extension point.
apiKey:configuration:# ...commerce-backend:apiKey: <perfect-api-key-secrets>serverKey: <secret-server-key>
You'll break your API hub setup if you edit any other section in this file.
Configuring SMTP credentials
To send emails from your application for events such as user registration or password reset, you must configure your Simple Mail Transfer Protocol (SMTP) credentials in the project.yml
file.
When developing locally, set http://localhost:3000
as the client_host
value.
configuration:# ...smtp:host: <smtp-host>port: 587encryption: tlsuser: <username>password: <password>sender: email@example.comclient_host: https://<project>-<customer>.netlify.app
Accessing variables in extension handlers
You can access the specified variables through the context
property that's passed in as the second argument to your extension handlers. See the examples below to learn more.
export default {'dynamic-page-handler': async (request: Request,context: DynamicPageContext): Promise<DynamicPageSuccessResult | DynamicPageRedirectResult | null> => {const { apiKey } =context.frontasticContext.project.configuration['commerce-backend'];// fetch data for dynamic pages},'data-sources': {'amazing-data-source': async (config: DataSourceConfiguration,context: DataSourceContext): Promise<DataSourceResult> => {const { serverKey } =context.frontasticContext.project.configuration['commerce-backend'];// fetch data with the server key},},actions: {commerce: {getStores: async (request: Request,context: ActionContext): Promise<Response> => {const { serverKey } =context.frontasticContext.project.configuration['commerce-backend'];// fetch stores with the server key},},},};
Accessing secrets in frontend components
Sometimes you'd need the variables in the frontend components. For example, some client-side SDKs like Adyen need a client id to work. The API hub doesn't expose the variables directly to the frontend, but you can easily implement a data source to selectively expose the variables you need in a component.
The following example shows how you can expose the adyen.clientID
secret from the project.yml
to a frontend component.
# other details...configuration:adyen:clientID: top_secret_client_id# more configurations ...
- Create a data source to read the variable from
project.yml
and return the variable.
export default {// ... other extensions'data-sources': {'secrets/adyen-client-id': async (config: DataSourceConfiguration,context: DataSourceContext) => {return {dataSourcePayload:context.frontasticContext.project.configuration.adyen.clientID,};},},// ... other extensions};
- Upload the data source schema to the studio.
{"customDataSourceType": "secrets/adyen-client-id","name": "Expose Adyen Client ID","category": "Secrets","icon": "key","schema": []}
- Specify the data source in the Frontend component's schema that needs the Adyen client ID.
{"tasticType": "example/adyen-payment","name": "Example payment","icon": "money","category": "payment","schema": [{"name": "Secrets","fields": [{"label": "Adyen client id","field": "adyenClientId","type": "dataSource","dataSourceType": "secrets/adyen-client-id","required": true}]}]}
- Use the
adyenClientId
in the Frontend component.
function ExamplePayment({ data }) {return (<h2>I got this secret from data source{' '}<b>{data?.adyenClientId?.dataSource}</b></h2>);}export default ExamplePayment;
This implementation keeps your application secrets safe by allowing you to granularly expose secrets to the components.
It's essential to expose as little as possible to avoid security issues. A good practice is creating separate data sources for each secret needed on the frontend.
Sourcing hierarchy
The files are sourced in the following order and values are overwritten by later files:
Production
- project.yml
Staging
- project.yml
- project.yml.staging
Development
- project.yml
- project.yml.dev
So, if you have the same key-value pair specified in both project.yml
and project.yml.dev
the .dev
one will be used.
Securing your project secrets
We've introduced a way to add another ansible-vault for encrypted project configurations. This vault should be just an encrypted version of the project.yml
with the necessary overwrites and should be named accordingly:
project.yml.crypt
for Productionproject.yml
project.yml.staging.crypt
for Stagingproject.yml.staging
These files will then get decrypted on our servers to make them available there.
Creating the Ansible-Vault
In order to create a vault, you could follow the documentation of Ansible.
Basically, you'll need to run the following command on your shell inside the project's config directory:
# cd to project's config directory, where $PROJECT is something like "demo_de"cd $PROJECT/config# create the ansible vault there with an vault-id that equals your customer's name, for example, "demo"# Keep in mind that it should be a unique password that needs to be known by us as well, so please don't reuse a password hereansible-vault create --vault-id $CUSTOMER@prompt project.yml.crypt
We need to know your password to configure our servers properly. Don't reuse another password here!
Choose any new password you like and contact us using the Submit a ticket button (at the top of this page) so we can configure the servers properly to use the password you've used so that it gets decrypted on the production and staging machines.
Please don't forget to check the generated encrypted vault file in Git.
Editing the Ansible-Vault
You could edit the vault by running the following command:
ansible-vault edit --vault-id $CUSTOMER@prompt project.yml.crypt
After editing and once the changes are pushed into your master branch, please contact our Support team (using the Submit a ticket button) who will make sure these are applied to your production and/or staging servers.
For further details, see the Ansible documentation.