Skip to content

Secrets

Data apps

Secrets let you define environment variables for your data app’s managed builds. This lets you avoid checking sensitive values into your source control, or define different values for local development and your production app. Once you add a secret under app settings, you can’t see its value there; it is only available to your app at build time, and it is redacted from logs. You can use it in your data loaders and page loaders, e.g. to fetch private data, but should be careful not to output or render it on your built pages.

Secrets are securely hosted by Observable. To avoid ever sending us your secrets, Enterprise customers can pass environment variables directly to their on-premises builder.

Add a secret

Under app settings, go to the Secrets tab and click “Add secret”.

Screenshot of the Secrets tab with an “Add secret” button

The “Key name” is the variable you will reference in code; “Key value” is the secret itself. Once you click “Create new secret”, you won’t be able to see the value again.

Screenshot of the Secrets modal with “Key name” and “Key value” fields

For each secret, the table shows the name, who added it, and when.

Screenshot of the Secrets tab with two secrets listed in the table, DB_CREDENTIALS and GITHUB_TOKEN, with columns Name, Value, Updated by, and Updated at

You can edit or delete the secret with the “⋯” menu at the end of the row. Editing lets you redefine the secret, but does not let you see its current value. Once changed or deleted, there is no way to recover previous secrets.

Use a secret

Secrets are passed as standard environment variables to data loaders and page loaders. You can read its value with process.env.KEY_NAME. For example, you can use a secret called GITHUB_TOKEN to make an authenticated request to the GitHub API:

js
const response = await fetch(
  "https://api.github.com/repos/observablehq/framework/issues",
  {headers: {
    authorization: `token ${process.env.GITHUB_TOKEN}`,
    accept: "application/vnd.github.v3+json"
  }}
);
process.stdout.write(await JSON.stringify(response));

That code will fail on a Markdown page, like github.md, but work in a data loader, like github.json.js. That means the secret can only be used at build time, not at run time. This is important for security. You app’s viewers can see its runtime scripts, but they cannot see your data loader source — only its output.

Notice that, in the example above, we pass the secret to GitHub, get JSON back, and write the JSON to stdout. We can then load the resulting file on a page. The secret remains secret, but the data we get in return — in this case, a list of repository issues — does not.

WARNING

Do not output the value of your secret from a data or page loader, or it could be leaked to app viewers. You are responsible for using your secret securely in your app code.

Using secrets locally

Secrets are only injected into your data app during managed builds. For local development, you can pass them on the command line:

bash
GITHUB_TOKEN=a-secret-token npm run dev

Or you can add a .env file in your project directory (and add it to .gitignore so it doesn’t get checked in):

env
GITHUB_TOKEN=a-secret-token

Install dotenv and include import "dotenv/config" at the top of a data loader to run it with the values from .env as environment variables.

On-premises environment variables

EnterpriseLearn more about Enterprise

Secrets are available whether you’re building your app on the Observable Cloud or on your own on-premises environment. If you’re using the latter, you also have the option to pass environment variables directly to your builder without ever sending the secret to Observable’s servers.

The builder looks for environment variables called BUILDER_SECRETS and BUILDER_VARIABLES that define comma-separated lists of other environment variables that should be exposed to the build process. The only difference is that we make a best effort to redact BUILDER_SECRETS from logs (though you should try to avoid logging them in the first place); BUILDER_VARIABLES are not redacted.

For example, given these environment variables:

env
GITHUB_ORG=observablehq
REPO_NAME=framework
GITHUB_TOKEN=a-secret-token
BUILDER_VARIABLES=GITHUB_ORG,REPO_NAME
BUILDER_SECRETS=GITHUB_TOKEN

GITHUB_ORG, REPO_NAME, and GITHUB_TOKEN will be available to your data and page loaders as environment variables, to be used in the same way we showed above, and GITHUB_TOKEN will be redacted from logs. If any of them don’t exist in the environment, the builder will error when it starts.

TIP

If you want the host’s GITHUB_TOKEN variable to be available to your data loaders as TOKEN, you can map the two names with a colon: BUILDER_SECRETS=TOKEN:GITHUB_TOKEN.