Environment variables
Environment variables are settings that differ between your computer and the server: an API address, access keys, the site name. They are kept outside the code, in a .env file. In Astro 5 variables are described with a schema in the config and read from the astro:env/client and astro:env/server modules, and Astro checks that they are set and have the right type.
The .env file
Create a .env file in the project root, next to package.json:
SITE_TITLE=Anna's blog
BOOKS_API_TOKEN=secret-123Each line is NAME=value. The template's .gitignore already lists .env, so it does not get into the repository.
The variable schema
Describe the variables in astro.config.mjs:
// astro.config.mjs
import { defineConfig, envField } from 'astro/config';
export default defineConfig({
env: {
schema: {
SITE_TITLE: envField.string({ context: 'client', access: 'public', default: 'Blog' }),
BOOKS_API_TOKEN: envField.string({ context: 'server', access: 'secret' }),
},
},
});| Option | Meaning |
|---|---|
context: 'client' | The variable can be used in browser code as well |
context: 'server' | Server only: frontmatter, endpoints, actions |
access: 'public' | The value may be embedded in the built code |
access: 'secret' | A secret: never reaches the browser |
default | The value used when the variable is not set |
Besides envField.string there are envField.number, envField.boolean and envField.enum.
Reading variables
A public variable is read from astro:env/client, for example in the layout src/layouts/BaseLayout.astro:
---
import { SITE_TITLE } from 'astro:env/client';
---
<title>{Astro.props.title} | {SITE_TITLE}</title>A secret comes from astro:env/server, for example when loading books in src/pages/books.astro:
---
import { BOOKS_API_TOKEN } from 'astro:env/server';
const response = await fetch('https://example.com/api/books.json', {
headers: { Authorization: `Bearer ${BOOKS_API_TOKEN}` },
});
---If BOOKS_API_TOKEN is not set, Astro stops with an error naming the missing variable. The server module cannot be imported into browser code: Astro fails the build, and the key does not leak.
import.meta.env
Astro's built-in values are read through import.meta.env: import.meta.env.DEV is true in development, import.meta.env.PROD in the built site. Custom variables used to be read this way too; in Astro 5 astro:env is more convenient for them.
Common mistake
After changing .env or the schema, people keep working with the old values. The dev server reads variables at startup: stop it with Ctrl+C and run npm run dev again. On a hosting server variables are set in its settings, not with a .env file from the repository.