Environment variables

Qwik apps can read environment variables in two main ways: build-time variables and server-side variables.

process.env is a Node.js only API, and should be avoided at all costs.

Build-time variables

Build-time variables are powered by Vite. They are defined in .env files and are available in the browser and in the server-side code.

IMPORTANT! DO NOT use import.meta.env.PUBLIC_* to store any sensitive information, such as API keys, secrets, passwords, etc. Only public data.

Notice that build-time variables should be considered as public, since they will be hardcoded in the browser build, which can be easily read by anyone.

Build-time variables are prefixed by default with PUBLIC_ and can be accessed with with import.meta.env.PUBLIC_*.

.env
PUBLIC_API_URL=https://api.example.com
src/routes/index.tsx
import { component$ } from '@builder.io/qwik';
 
export default component$(() => {
  // `import.meta.env.PUBLIC_*` variables can be read anywhere, including browser
  return <div>PUBLIC_API_URL: {import.meta.env.PUBLIC_API_URL}</div>
})

import.meta.env.PUBLIC_* variables can be read anywhere, but do not put any sensitive information in them, since they will be visible to the client.

Server-side variables

Server-side variables are fundamentally runtime variables that are only available in the server-side code.

They are not known at build-time and are not available in the browser, so they can be considered as private.

Server-side variables can only be accessed in server-only APIs that expose the RequestEvent object, such as routeLoader$(), routeAction$(), server$() and endpoint handlers such as onGet, onPost, onRequest etc.

src/routes/index.tsx
import {
  routeLoader$,
  routeAction$,
  server$,
  type RequestEvent,
} from '@builder.io/qwik-city';
 
export const onGet = (requestEvent: RequestEvent) => {
  console.log(requestEvent.env.get('DB_PRIVATE_KEY'));
};
 
export const onPost = (requestEvent: RequestEvent) => {
  console.log(requestEvent.env.get('DB_PRIVATE_KEY'));
};
 
export const useAction = routeAction$(async (_, requestEvent) => {
  console.log(requestEvent.env.get('DB_PRIVATE_KEY'));
});
 
export const useLoader = routeLoader$(async (requestEvent) => {
  console.log(requestEvent.env.get('DB_PRIVATE_KEY'));
});
 
export const serverFunction = server$(function () {
  // `this` is the `RequestEvent` object
  console.log(this.env.get('DB_PRIVATE_KEY'));
});

Defining server-side variables

During development server-side variables can be defined in the .env.local file, this file is ignored by git by default, so it is safe to put sensitive information in it.

.env.local
DB_PRIVATE_KEY=123456789

Make sure you never commit .env.local files to git.

During production, setting server-side variables is very platform specific. Most of the platforms allow you to set environment variables from their dashboard, or CLI. Please, refer to your platform (cloudflare, vercel, netlify) documentation for more information.

Accessing the environment variables in serverfull architecture (Example:Express)

For accessing the .env variables in serverfull architecture we need to use singleton design pattern, initialize the db in a plugin and access it with getDB wherever it is needed

src/util/db.ts
let _db!: AppDatabase;
 
export function getDB() {
  // eslint-disable-next-line
  if (!_db) {
    throw new Error('DB not set');
  }
  return _db;
}
 
export async function initializeDbIfNeeded(factory: () => Promise<AppDatabase>) {
  // eslint-disable-next-line
  if (!_db) {
    _db = await factory();
  }
}
export const onRequest: RequestHandler = async ({ env }) => {
  const url = env.get('PRIVATE_LIBSQL_DB_URL')!;
  const authToken = env.get('PRIVATE_LIBSQL_DB_API_TOKEN')!;
  await initializeDbIfNeeded(initLibSql(url, authToken));
};

Contributors

Thanks to all the contributors who have helped make this documentation better!

  • manucorporat
  • the-r3aper7
  • mrhoodz
  • wtlin1228