ZTS Docs

Environment Variables Philosophy

How environment variables are managed and validated.

Core Principles

  1. Type Safety with Zod: We use zod to define schemas for our environment variables (src/env/schemas). This provides compile-time and runtime validation, preventing errors caused by missing or incorrectly typed variables.
  2. Clear Separation: Environment variables are strictly separated into:
    • Client-side: Variables prefixed with NEXT_PUBLIC_ are accessible in the browser. These are defined and validated in src/env/client.ts.
    • Server-side: Variables used exclusively on the server (e.g., API keys, database URLs) are handled in src/env/index.ts.
  3. Validation on Build/Start: The application validates all required environment variables when it builds or starts. If any variables are missing or invalid according to the Zod schemas, the process will fail with a descriptive error message, preventing runtime issues.
  4. Modular Schemas: Server-side schemas are further broken down by feature (e.g., email, auth) in src/env/schemas/ and then merged. This keeps the configuration organized and easier to manage as the application grows.
  5. Single Source of Truth: The validated and processed environment variables are exported from src/env/index.ts (serverEnv) and src/env/client.ts (clientEnv), serving as the single source of truth throughout the application.

Application URL Configuration

The application needs to know its public-facing URL for various features like authentication callbacks and generating absolute links. The deployment URL is typically derived automatically based on environment variables provided by platforms like Vercel, Railway, Render, and Coolify.

This derived URL is configured in next.config.js and passed to the application via the NEXT_PUBLIC_APP_URL environment variable.

Overriding the URL: If the automatically derived URL is incorrect, or if you need to specify a different primary URL, you can manually set the SERVER_URL environment variable. This value will take precedence.

Handling Multiple Domains

If your deployment platform supports multiple domains for a single deployment, be aware that relying on the automatically derived URL might lead to issues. The platform might provide a list of domains, causing problems for features expecting a single canonical URL (like authentication). The recommended approach is to create a separate deployment for each domain you want to serve. Each deployment should then have the SERVER_URL environment variable explicitly set to its corresponding domain.

Refer to .env.example for a list of all required environment variables and their intended purpose. The specific schemas in src/env/schemas/ define the expected types and validations.

Generating .env

To help generate your initial .env file based on these schemas, you can use the online tool zts-env.vercel.app.

Debugging Pages

For debugging purposes during development, there are two pages available to view environment variables:

  • /env: (src/app/env-client/page.tsx) This page is publicly accessible and displays only the client-side NEXT_PUBLIC_ variables that have been explicitly exposed via clientEnv.
  • /env-server: (src/app/env-server/page.tsx) This page displays a curated list of server-side environment variables (primarily related to deployment environments like Vercel, Railway, Coolify). Access to this page is restricted to administrators via the adminProcedure in the tRPC router (src/server/api/routers/admin.ts).

Important: If you prefer not to expose any environment variables through the UI, even for admins, feel free to delete the src/app/env-client/ and src/app/env-server/ directories, as well as the corresponding adminRouter (getEnvVars procedure) in src/server/api/routers/admin.ts.

On this page