Lesson 21 / 25
Environment Variables With $env
Static, dynamic, public and private.
Four $env modules
SvelteKit exposes environment variables through four modules. $env/static/private and $env/static/public are inlined at build time, which enables dead-code elimination; $env/dynamic/private and $env/dynamic/public are read at run time, which suits values that differ between deployments of the same build. Only variables starting with the public prefix (PUBLIC_ by default) can be imported from the public modules and reach the browser. Private modules can only be imported in server-only code; importing them into client code is a build error. Locally, values come from .env files loaded by Vite; in production, from the platform.
Using the right module
Server secret and public base URL.
// .env (not committed)
// DATABASE_URL=postgres://...
// STRIPE_SECRET_KEY=sk_test_...
// PUBLIC_API_BASE=https://api.example.com
// src/lib/server/db.ts (server-only)
import { DATABASE_URL } from '$env/static/private';
import { createClient } from './driver'; // your database client library
export const db = createClient(DATABASE_URL);
// src/routes/+page.server.ts
import { env } from '$env/dynamic/private';
const featureFlag = env.FEATURE_NEW_CHECKOUT === 'true';
// src/lib/api.ts (can run in the browser)
import { PUBLIC_API_BASE } from '$env/static/public';
export const api = (path: string) => fetch(`${PUBLIC_API_BASE}${path}`);A safe and a notice board
Private variables stay in the server-room safe; only notes marked PUBLIC_ are pinned on the notice board that every visitor can read.
Quick check: Which variable can be imported into code that runs in the browser?
- DATABASE_URL from $env/static/private
- PUBLIC_API_BASE from $env/static/public
- Any variable from $env/dynamic/private
- process.env.SECRET_KEY
Answer
PUBLIC_API_BASE from $env/static/public — Only public-prefixed variables reach the client.