`astro:env` for Typed, Validated Configuration
Environment Variables
`astro:env` schemas declare which env vars exist, whether they're client-or-server, public-or-secret, and what type they are.
What you'll learn
- Declare an env var schema
- Read server vs client env safely
- Tell secrets from public values
astro:env lets you declare environment variables in
astro.config.mjs with a schema. Astro validates them at build,
types them, and protects you from accidentally exposing secrets.
Declare The Schema
// astro.config.mjs
import { defineConfig, envField } from "astro/config";
export default defineConfig({
env: {
schema: {
// public (shipped to the client)
PUBLIC_API_URL: envField.string({ context: "client", access: "public" }),
// server-only (NEVER shipped to client)
DATABASE_URL: envField.string({ context: "server", access: "secret" }),
// server-public (server only, but not a secret)
SITE_NAME: envField.string({ context: "server", access: "public", default: "My Site" }),
},
},
}); Read Server Vars
---
import { DATABASE_URL, SITE_NAME } from "astro:env/server";
const db = connect(DATABASE_URL);
---
<title>{SITE_NAME}</title> If DATABASE_URL is missing at runtime, the build / page fails
with a clear error — not a silent undefined.
Read Client Vars
import { PUBLIC_API_URL } from "astro:env/client";
export default function Search() {
// Yes, this is shipped to the browser
return <a href={`${PUBLIC_API_URL}/docs`}>Docs</a>;
} Trying to import a server-only var from astro:env/client is a
build error. Astro keeps secrets server-side automatically.
Setting Values
Same as any Vite project — .env, .env.local, host’s environment
UI:
# .env
PUBLIC_API_URL=https://api.example.com
DATABASE_URL=postgres://... Don’t commit .env. Most hosts have a per-environment env config.
The Old import.meta.env.PUBLIC_* Still Works
Pre-astro:env, you’d use import.meta.env.PUBLIC_API_URL. Still
works, but astro:env gives you types and validation. New code
should prefer it.
Up Next
Setting response headers and runtime redirects.
Headers and Redirects →